HomeGuidesAPI Reference
Submit Documentation FeedbackJoin Developer CommunityOptimizely GitHubOptimizely NuGetLog In

Facets

This topic describes the facets field, part of the GraphQL API used for the Optimizely querying service, when retrieving faceted content in Optimizely solutions. It is a sibling field of items, which contain the matching hits.

How it works

The facets field enables the retrieval of facets. Facets are values in fields that which can be used to navigate through the results by filtering. 

Fields that can be used for faceting will be suggested in the autocomplete of the GraphQL user interface. Multiple fields can be specified for faceting. Nested fields can also be used for faceting.

Tip: In case only the facets should be returned, but no results, the limit parameter in the where field has to be set to 0. This will significantly improve the query times.

String and Bool fields

For each string or bool (filter) field, there are 4 optional parameters for each field:

  • orderType – This can be by COUNT or VALUE (default: COUNT).
  • orderBy – Specifies the order of the facets. This can be either in ASC or DESC order (default: DESC) 
  • limit – Specifies the number of facets to retrieve (default: 10). This cannot be greater than 1,000 or an error message will be shown.
  • filters – Optional input argument that specifies the facets that should be applied with the field. This can be a list of string values. This is used to support multi-select of facets, i.e., applying a facet as a filter to update the list of results, while preserving the list of original facets but get updated hit counts for the items and facets without filters.

📘

Filters in the string fields are used to support multi-select

There are cases where multiple facets within a field should be selectable and be applied (e.g., using check boxes), where the original facets should persist so more facets can be enabled/disabled while only updating the result list and other facets.

How does multi-select of facets work? The following example is by courtesy of Yonik Seely. Imagine we have the following fields with facets:

=== Size ===   === Color ===    === Brand ===
[Small] (7)    [ ] Red (2)      [ ] Nike (7)
[Medium] (5)   [ ] Blue (8)     [ ] Adidas (5)
[Large] (6)    [ ] Green (3)    [ ] Reebok (4)
               [ ] Black (5)    [ ] Under Armour (2)

If the user selects the facet Blue, then we get the updated view, where the other facets are updated and the search results, but the original Color facets stay the same so they can be turned on/off.

=== Size ===   === Color ===    === Brand ===
[Small] (3)    [ ] Red (2)      [ ] Nike (3)
[Medium] (2)   [x] Blue (8)     [ ] Adidas (2)
[Large] (3)    [ ] Green (3)    [ ] Reebok (2)
               [ ] Black (5)    [ ] Under Armour (1)

(Top Blue running shorts displayed here)

And in case the user also selects black, then we get this updated view:

=== Size ===   === Color ===    === Brand ===
[Small] (5)    [ ] Red (2)      [ ] Nike (5)
[Medium] (4)   [x] Blue (8)     [ ] Adidas (3)
[Large] (4)    [ ] Green (3)    [ ] Reebok (3)
               [x] Black (5)    [ ] Under Armour (2)

(Top Blue and Black running shorts displayed here)

We see that the search results will be expanded with the extra added filter in Color and as well as the facet counts in the other fields.

The facets are projected by:

  • name – This field shows the name of the facet, i.e. the value that can be faceted on. 
  • count – This fields shows the facet count, i.e. the number of hits that would match with the name.

Request with string example:

query MyQuery {
  StandardPage (locale: en, limit: 1) {
    items {
      RouteSegment
      Saved
    } 
    facets {
      RouteSegment (limit: 8, orderType: VALUE, orderBy: ASC) {
        name
        count
      }
    }
  }
}

This will return the facets as part of the facets projection:

"facets": {
    "RouteSegment": [
        {
            "name": "about-us",
            "count": 1
        },
        {
            "name": "become-a-reseller",
            "count": 1
        },
        {
            "name": "collaboration-made-simple",
            "count": 1
        },
        {
            "name": "contact-us",
            "count": 1
        },
        {
            "name": "download-whitepaper-alloy-track",
            "count": 1
        },
        {
            "name": "find-a-reseller",
            "count": 1
        },
        {
            "name": "management",
            "count": 1
        },
        {
            "name": "news-events",
            "count": 1
        }
    ]
}

Request example with multi-select of facets using filters, where only the items and counts of facets are updated, while preserving the list of facets:

{
  Content(locale: en, limit: 1)  {
    items {
      _score
      Name
      ContentType
    }
    total
    facets {
      ContentType(filters: ["ImageFile"]) {
        name
        count
      }
    }
  }
}

This will return all original facets with orginal facet counts and the new updated result list that applies VideoFile to ContentType, resulting in 32 items:

{
  "data": {
    "Content": {
      "items": [
        {
          "_score": 0,
          "Name": "ToddSlayton.jpg",
          "ContentType": [
            "Image",
            "Media",
            "ImageFile",
            "Content"
          ]
        }
      ],
      "total": 32,
      "facets": {
        "ContentType": [
          {
            "count": 89,
            "name": "Content"
          },
          {
            "count": 34,
            "name": "Page"
          },
          {
            "count": 33,
            "name": "Media"
          },
          {
            "count": 32,
            "name": "Image"
          },
          {
            "count": 32,
            "name": "ImageFile"
          },
          {
            "count": 22,
            "name": "Block"
          },
          {
            "count": 12,
            "name": "StandardPage"
          },
          {
            "count": 8,
            "name": "PageListBlock"
          },
          {
            "count": 5,
            "name": "ContactPage"
          },
          {
            "count": 5,
            "name": "TeaserBlock"
          }
        ]
      }
    }
  },
  "extensions": {
    "correlationId": "f3c1dd78-5a01-4595-a3ef-a0065a1e0f28"
  }
}

An example of using filters for a multi-select request with Bool field example.

query MyQuery {
  AllPropertiesTestPage(locale: en) {
    facets {
      Boolfield(filters: "true") {
        name
        count
      }
    }
    items {
      Name
      Boolfield
    }
  }
}

This returna all facets with value equal to True.

📘

Use only matching values for filters

Enter valid values for filters. For example, note that there are only two possible values for Bool fields: true and false. Therefore, if a string value that is other than those two possible values is inserted, the results will be empty.

{
  "data": {
    "AllPropertiesTestPage": {
      "facets": {
        "Boolfield": [
          {
            "name": "true",
            "count": 1
          }
        ]
      },
      "items": [
        {
          "Boolfield": true
        }
      ]
    }
  }
}

Date fields

The facets of date fields can be retrieved as a histogram, where the latest 1,000 units of value are retrieved. For each date field, there are two optional parameters:

  • value – The quantity for the unit. It can be an integer. By default it is 1. 
  • unit – The unit of time. This can be MINUTE, HOUR, or DAY, where DAY is default.

Request example where we drop the items from the response and only project the facets:

query MyQuery {
  StandardPage (locale: en, limit: 0) {
    facets {
      Created (unit: DAY, value: 14) {
        name
        count
      }
    }
  }
}

This response will do the bucketing of documents with the Created field by 14 days (bi-weekly):

"data": {
    "StandardPage": {
        "facets": {
            "Created": [
                {
                    "2012-08-02T00:00:00Z": 1
                },
                {
                    "2012-08-16T00:00:00Z": 2
                },
                {
                    "2012-08-30T00:00:00Z": 2
                },
                {
                    "2012-09-13T00:00:00Z": 2
                },
                {
                    "2012-09-27T00:00:00Z": 3
                }
            ]
        }
    }
}

Number fields

For each number (filter) field, there is a ranges parameter and this parameter is array of objects that has two optional parameters:

  • from – The minimum (lowerbound) value in range. This can be nullable.
  • to – The maximum (upperbound) value in range. The upperbound value is treated as non-inclusive, so the to value always needs to be higher than the from value to return results. This is indicated with the notation of the bucket name like [10,100) (starting with square bracket and ending with parenthesis). This can be nullable.

Request example:

query MyQuery {
  StartPage(locale: en) {
    items {
      Visitor
    }
    facets {
      Visitor(ranges: [{from: 10, to: 100}, {from: 1000}, {to: 100000}])
    }
  }
}

This will return the facets as part of the extensions section of the response:

"data": {
    "StandardPage": {
        "items": [...],
        "facets": {
            "Visitor": [
                {
                    "[,100000)": 1
                },
                {
                    "[10,100)": 1
                },
                {
                    "[1000,)": 0
                }
            ]
        }
    }
}

Combining different facet types

We can request a mixture of (multiple) different field types in the facets projection, letting you retrieve multiple facets of different fields in a single request.

Request example:

query MyQuery {
  Content(locale: en) {
    items {
      Name
      Changed
      ContentLink {
        Id
      }
    }
    facets {
      Changed(unit: DAY, value: 100) {
        name
        count
      }
      Name(limit: 10, orderBy: ASC, orderype: VALUE) {
        name
        count
      }
      ContentLink {
        Id(ranges: [{from: 10, to: 100}, {from: 1000}]) {
          name
          count
        }
      }
    }
  }
}