Result Folding

Result folding allows you to group items that have a certain field value in common, and identify parent-child relationships between those items in the query result set.

This article provides information and an example for using result folding in your search integration with the Coveo Platform.

In a Coveo JavaScript Search Framework search interface, you can request folded query results using the Folding or FoldingForThread component, and render those results using the ResultFolding and/or ResultAttachments result template components.

Parameters

The following search request parameters allow you to request folded query results.

filterField (String)

The @-prefixed name of the field to use to group items into distinct folded query results.

Use a field whose value is identical for all items to group under the same folded query result (e.g., @folding_collection_id).

parentField (String)

The @-prefixed name of the field to use to be able to identify an item as a parent in a folded query result.

Use a field whose value can uniquely identify each item (e.g., @folding_item_id). All items whose childField value is identical to the parentField value of another item are considered children of that other item.

In the index, the values of the parentField must only contain alphanumerical characters. Using a parentField whose values contain non-indexable characters (such as underscores) will make folding fail.

Using a parentField containing values such as message_123 will fail.

The parentField should contain values such as 123 instead.

Moreover, the values of the parentField must contain 60 characters or less (60 being the default maximum of characters for a word in the index).

childField (String)

The @-prefixed name of the field to use to be able to identify an item as a child of another item in a folded query result.

Use a field whose value points to the parentField value of the intended parent (e.g., @folding_parent_item_id). Whenever an item is a child of another item, its childField value must be identical to the parentField value of that other item.

In the index, the values of the childField must only contain alphanumerical characters. Using a childField whose values contain non-indexable characters (such as underscores) will make folding fail.

Using a childField containing values such as message_123 will fail.

The childField should contain values such as 123 instead.

Moreover, the values of the childField must contain 60 characters or less (60 being the default maximum of characters for a word in the index).

filterFieldRange (Unsigned Integer)

The maximum number of items to include in the childResults array of a folded query result.

Default value is 5.

Example

In a Coveo Cloud organization, you have a Push source that indexes forum post items (i.e., messages and their attachments).

In the indexing pipeline mapping phase, a pushed forum post item notably populates the following set of fields in the index:

  • @folding_collection_id with a unique identifier for the conversation thread the forum post item belongs to. This field will be used as the filterField when requesting folded query results.

  • @folding_item_id with a unique identifier for the forum post item itself. This field will be used as the parentField when requesting folded query results.

  • @folding_parent_item_id with the @folding_item_id value of the forum post item parent (when applicable). This field will be used as the childField when requesting folded query results.

Currently, the following forum post items have been indexed through your Push source:

- Message 1
    @folding\_collection\_id: "1"
    @folding\_item\_id: "101"
    - Message 2
        @folding\_collection\_id: "1"
        @folding\_item\_id: "102"
        @folding\_parent\_item\_id: "101"
    - Message 3
        @folding\_collection\_id: "1"
        @folding\_item\_id: "103"
        @folding\_parent\_item\_id: "101"
        - Attachment 1
            @folding\_collection\_id: "1"
            @folding\_item\_id: "104"
            @folding\_parent\_item\_id: "103"
        - Attachment 2
            @folding\_collection\_id: "1"
            @folding\_item\_id: "105"
            @folding\_parent\_item\_id: "103"
    - Message 4
        @folding\_collection\_id: "1"
        @folding\_item\_id: "106"
        @folding\_parent\_item\_id: "101"
- Message 5
    @folding\_collection\_id: "2"
    @folding\_item\_id: "107"
    - Message 6
        @folding\_collection\_id: "2"
        @folding\_item\_id: "108"
        @folding\_parent\_item\_id: "107"

When you query your Push source, you want the Search API to:

  • Return matching items as folded query results based on the conversation thread they each belong to.

  • Return only up to four child results per folded query result.

  • Sort query results from oldest to newest.

To do so, you include the following payload in your search request to the Search API:

{
  "filterField": "@folding_collection_id",
  "parentField": "@folding_item_id",
  "childField": "@folding_parent_item_id",
  "filterFieldRange": 4,
  "sortCriteria": "dateascending"
}

When the Search API returns, the response body contains the following query results (for the sake of brevity, this sample only includes result item properties that are pertinent to the current use case):

{
  "results": [
    {
      "title": "Message 1",
      "parentResult": null,
      "childResults": [
        {
          "title": "Message 2",
          "parentResult": {
            "title": "Message 1"
          }
        },
        {
          "title": "Message 3",
          "parentResult": {
            "title": "Message 1"
          }
        },
        {
          "title": "Attachment 1",
          "parentResult": {
            "title": "Message 3"
          }
        },
        {
          "title": "Attachment 2",
          "parentResult": {
            "title": "Message 3"
          }
        }
      ],
      "totalNumberOfChildResults": 4
    },
    {
      "title": "Message 5",
      "parentResult": null,
      "childResults": [
        {
          "title": "Message 6",
          "parentResult": {
            "title": "Message 5"
          }
        }
      ],
      "totalNumberOfChildResults": 1
    }
  ],
  "totalCount": 2
}

As you can see:

  • The results array contains two folded query results, which are sorted from oldest to newest.

    • The first folded query result contains the four oldest items whose @folding_collection_id field value is "1".

    • The second folded query result contains the items whose @folding_collection_id value is "2".

  • A folded query result is not a recursive tree-like structure, but merely an item with a sorted array of childResults.

  • Each folded result item (including the base item) has a parentResult property whose value points to its parent item. This property is currently null for the base item of both folded query results, as those items are “root” parents that don’t themselves have parents.

If you were to perform another search request, this time using relevancy as a sortCriteria, the response could instead look like what follows (for the sake of brevity, this sample only includes result item properties that are pertinent to the current use case):

{
  "results": [
    {
      "title": "Attachment 2",
      "parentResult": {
        "title": "Message 3"
      },
      "childResults": [
        {
          "title": "Attachment 1",
          "parentResult": {
            "title": "Message 3"
          }
        },
        {
          "title": "Message 3",
          "parentResult": {
            "title": "Message 1"
          }
        },
        {
          "title": "Message 2",
          "parentResult": {
            "title": "Message 1"
          }
        },
        {
          "parentResult": null,
          "title": "Message 1"
        }
      ],
      "totalNumberOfChildResults": 4
    },
    {
      "title": "Message 5",
      "parentResult": {
        "title": "Message 4"
      },
      "childResults": [
        {
          "parentResult": null,
          "title": "Message 4"
        }
      ],
      "totalNumberOfChildResults": 1
    }
  ],
  "totalCount": 2
}

As you can see:

  • A folded query result doesn’t necessarily have its “root” parent as a base item; the first item (and the ordering of its childResults array) is determined by the current sortCriteria.

  • The items in the childResults array of a folded query result base item may consequently not even be children of that base item.

In summary, the childResults array of a folded query result is simply a sorted array of items that have the same filterField field value. This means that to display folded query result items properly in a graphical search interface that does not rely on the Coveo JavaScript Search Framework, you’ll likely need to write client-side logic that will resolve parent-child relationships within each folded query result, using the parentResult property of each item (including the base item).

Recommended Articles