Skip to content
Headless Platform
GitHubDiscordYouTube

Using GraphQL Search API

Find API Documentation

NOTE: This API and its endpoints are in BETA. Beta Services as described by Section 2.e. of the terms of services located here

Overview

The Find API allows you to search for documents in an index based on specific parameters.

Basic Usage

To search for documents using the find query. Below, you can see examples:

Find query basic example

query FindSimpleQuery {
  find(query: "hello") {
    total
    documents {
      id
      score
      data
    }
  }
}

Find query advance example

query FindAdvanceQuery {
  find(
    query: "Austin"
    filter: "post_type:post,page"
    fields: [{ name: "title", weight: 2 }, { name: "description" }]
    orderBy: [{ field: "published_at", direction: desc }]
    limit: 100
    offset: 200
    tolerance: { name: fuzzy, fuzzyDistance: 2 }
  ) {
    total
    documents {
      id
      score
      data
    }
  }
}

You can write the same query with separated variables:

query FindAdvanceQuery(
  $query: String!
  $filter: String
  $fields: [SearchField!]
  $orderBy: [OrderBy!]
  $limit: Int!
  $offset: Int!
  $tolerance: SearchOption!
) {
  find(
    query: $query
    filter: $filter
    fields: $fields
    orderBy: $orderBy
    limit: $limit
    offset: $offset
    tolerance: $tolerance
  ) {
    total
    documents {
      id
      score
      data
    }
  }
}

GraphQL Variables

{
  "query": "Austin",
  "filter": "post_type:post,page",
  "orderBy": [
    { "field": "published_at", "direction": "desc" }
  ],
  "offset": 200,
  "limit": 100,
  "fields": [{ "name": "title", "weight": 2 }, { "name": "description" }],
  "tolerance": { "name": "fuzzy", "fuzzyDistance": 2 }
}

The query returns a SearchResult object that includes fields:

  • total - an integer of the total documents matching the query. Independent to offset and limit arguments.
  • documents - an array of search documents with fields:
    • id is unique id of the document in the index
    • score is a relevance score, which determines how closely each document matches the query

Advanced Usage

Logical operators: AND, OR, NOT

Using NOT search operator:

query FindNotQuery {
  find(query: "Austin NOT Minnesota") {
    total
    documents {
      id
      score
      data
    }
  }
}

Using AND search operator:

query FindAndQuery {
  find(query: "New York AND Texas") {
    total
    documents {
      id
      score
      data
    }
  }
}

Using OR search operator:

query FindOrQuery {
  find(query: "New York OR Texas") {
    total
    documents {
      id
      score
      data
    }
  }
}

Search field value with greater, less or equal operator

query FindRangeQuery {
  find(query: "seats.count:(>4 AND <20)") {
    total
    documents {
      id
      score
      data
    }
  }
}

The seats.count field has a value greater than 4 and lower than 20.

Filtering for exact keywords

It is possible to have two categories which might share the same keywords, Car and Car Sales.

query FindFilterQuery {
  find(query: "Toyota", filter: "categories.name:Car") {
    total
    documents {
      id
      score
      data
    }
  }
}

Executing the query above will return records where the categories.name field contains both Car and Car Sales etc.

If we only want to return records with Car we must use the keyword field i.e if the path to the field is categories.name we can update it to be categories.name.keyword

query FindKeywordFilterQuery {
  find(query: "Toyota", filter: "categories.name.keyword:Car") {
    total
    documents {
      id
      score
      data
    }
  }
}

Executing the query above will ensure only the categories which match Car will be returned.

Ordering

The orderBy input is an array of objects that specify how the results of the find query should be sorted. Each object in the orderBy array has two properties: field and direction.

Ordering by dates

The following query sorts documents in descending order using the post_date_gmt field:

query OrderByQueryWithDates {
  find(
    query: "my search query"
    orderBy: [{field: "post_date_gmt", direction: desc}]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

Ordering by strings

NOTE: String fields can only be used in orderBy by appending a subfield which is automatically present for all string fields, this field is called keyword.

The following query sorts documents in ascending order using a string field post_title, we must then append .keyword to enable string sorting.

query OrderByQueryWithStrings {
  find(
    query: "my search query"
    orderBy: [{field: "post_title.keyword", direction: asc}]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

Ordering by numbers

The following query sorts documents in ascending order using the price field:

query OrderByQueryWithNumbers {
  find(
    query: "my search query"
    orderBy: [{field: "price", direction: asc}]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

Ordering by multiple clauses

It is possible to order by one or more clauses, each subsequent ordering clause has less priority than the preceding clause. For example if we order by price and then post_date_gmt, the post_date_gmt comes into effect when two or more records with the same price are the same.

The following query sorts documents using multiple fields, price and post_date_gmt:

query OrderByQueryWithMultipleClauses {
  find(
    query: "my search query"
    orderBy: [
      {field: "price", direction: asc},
      {field: "post_date_gmt", direction: asc},
    ]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

Cursor pagination

Search also supports cursor pagination.

Notes:

  • orderBy would need to be provided in order to avoid sort field of returned documents being empty
  • In order cursor pagination to work properly, {field:"_score"} can’t be provided alone, since it’s a calculated field and needs a second standard field to work as “tiebreaker”.

Here is an example:

query FindTest {
  find(
    query: "test"
    orderBy: [{field:"_score"},{field: "post_date_gmt", direction: desc}]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

And result documents returned are:

{
  "data": {
    "find": {
      "total": 5,
      "documents": [
        {
          "id": "post:19",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:37"
          ]
        },
        {
          "id": "post:17",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:25"
          ]
        },
        {
          "id": "post:15",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:14"
          ]
        },
        {
          "id": "post:13",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:01"
          ]
        },
        {
          "id": "post:10",
          "sort": [
            "4.680951",
            "2024-01-23T11:05:46"
          ]
        }
      ]
    }
  }
}

For returning the results after post:17 we need to provide the sort of that document and make the following call:

query FindTest {
  find(
    query: "test"
    orderBy: [{field:"_score"},{field: "post_date_gmt", direction: desc}]
        searchAfter:["4.680951", "2024-01-23T11:06:25"]
  ) {
    total
    documents {
      id
      sort
    }
  }
}

which will return:

{
  "data": {
    "find": {
      "total": 5,
      "documents": [
        {
          "id": "post:15",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:14"
          ]
        },
        {
          "id": "post:13",
          "sort": [
            "4.680951",
            "2024-01-23T11:06:01"
          ]
        },
        {
          "id": "post:10",
          "sort": [
            "4.680951",
            "2024-01-23T11:05:46"
          ]
        }
      ]
    }
  }
}

Semantic search uses machine learning to interpret the meaning of words and phrases. The results of a semantic search will return documents matching the meaning of a query, as opposed to full text search that literally matches words in the query.

Hybrid search is a combination of full-text search and semantic search to deliver more relevant and comprehensive results.

Before using Semantic / Hybrid search, you need to configure it. Semantic / Hybrid Search Configuration API is available here.

Once configuration is done, you can use the semanticSearch input in the find query to perform a semantic search.

query FindWithSemanticSearch {
  find(
    query: "eats carrots and is a rodent"
    semanticSearch: {searchBias:10, fields: ["post_title"]}
  ) {
    total
    documents {
      score
      data
    }
  }
}
  • semanticSearch is an input that accepts options used by semantic / hybrid search.
  • searchBias: 10 is indicating that we want to use only semantic search and not full-text search. If the value is 0, only full-text search is used. If the value is between 1-9, it’s a combination of full-text and semantic search.
  • fields: ["post_title"] We specify that we want to perform a semantic search on the post_title field. (This field should be configured for semantic search in the configuration step)

Sample output from executing the graphql query above:

{
  "data": {
    "find": {
      "total": 2,
      "documents": [
        {
          "score": 2.209324,
          "data": {
            "ID": 6,
            "fieldGroup1": {
              "field1": null,
              "field2": 0
            },
            "history": {
              "owners": null
            },
            "post_content": "",
            "post_date_gmt": "2024-02-09T15:21:20",
            "post_excerpt": "",
            "post_modified_gmt": "2024-02-14T16:06:44",
            "post_name": "rabbit-1",
            "post_status": "publish",
            "post_title": "Rabbit-1 rabbit",
            "post_type": "rabbit",
            "testNumbers": {
              "test_number": 0
            }
          }
        },
        {
          "score": 2.0539768,
          "data": {
            "ID": 7,
            "post_content": "",
            "post_date_gmt": "2024-02-09T15:21:23",
            "post_excerpt": "",
            "post_modified_gmt": "2024-02-09T15:21:23",
            "post_name": "rabbit-2",
            "post_status": "publish",
            "post_title": "Rabbit-2",
            "post_type": "rabbit"
          }
        }
      ]
    }
  }
}

Note: For a complete example of how to configure, index and use semantic search, please refer to this section.

Facets

Faceted search is a way to navigate large sets of data by aggregating terms and/or ranges, and then applying filters based on the results to narrow down a search.

Terms

Consider the following query:

{
  find(
    query: "my search query"
    aggregate: {
      terms: [{field: "categories.name"}]
    }
  ) {
    total
    aggregations {
      terms {
        field
        terms {
          term
          count
        }
      }
    }
  }
}
  • aggregate is an input that accepts a list of terms or ranges
  • terms: [{field: "categories.name"}] is indicating that we want to aggregate on the field categories.name
  • We also specify to return the terms aggregations in the query

Sample output from executing the graphql query above:

{
  "find": {
    "aggregations": {
      "terms": [
        {
          "field": "categories.name",
          "terms": [
            {
              "count": 5,
              "term": "sport"
            },
            {
              "count": 4,
              "term": "farming"
            },
            {
              "count": 5,
              "term": "shopping"
            }
          ]
        }
      ]
    },
    "total": 14
  }
}
  • The output of the query returns unique terms that occur in the field categories.name
  • term is the instance of the term.
  • count is the ammount of occurences of the term.
  • The total indicates how many documents were considered for the given search query “my search query”

Lets filter the results and select documents where categories.name are equal to sport

{
  find(
    query: "my search query AND categories.name:sport"
    aggregate: {
      terms: [{field: "categories.name"}]
    }
  ) {
    total
    aggregations {
      terms {
        field
        terms {
          term
          count
        }
      }
    }
  }
}

Result:

{
  "find": {
    "aggregations": {
      "terms": [
        {
          "field": "categories.name",
          "terms": [
            {
              "count": 5,
              "term": "sport"
            }
          ]
        }
      ]
    },
    "total": 5
  }
}

For the example above we didn’t include the found documents, lets do that now.

{
  find(
    query: "my search query AND categories.name:sport"
    aggregate: {
      terms: [{field: "categories.name"}]
    }
  ) {
    total
    aggregations {
      terms {
        field
        terms {
          term
          count
        }
      }
    }
    documents {
      data
    }
  }
}

Result:

{
  "find": {
    "documents": [
      {
        "id": "post:2",
        "data": {
          "ID": 2,
          "categories": {
            "name": "sport"
          },
          "post_title": "Search with aggregations query example",
          "post_type": "post"
        }
      }
      // 4 more documents
    ],
    "aggregations": {
      "terms": [
        {
          "field": "categories.name",
          "terms": [
            {
              "count": 5,
              "term": "sport"
            }
          ]
        }
      ]
    },
    "total": 5
  }
}

Ranges

Consider the following query:

{
  find(
    query: "*"
    aggregate: {
      ranges: [{
        field: "prices.price"
        ranges: [
          { from: 0, to: 100 },
          { from: 101, to: 200 }
        ]
      }]
    }
  ) {
    total
    documents {
      data
    }
    aggregations {
      ranges {
        field
        ranges {
          from
          to
          count
        }
      }
    }
  }
}
  • aggregate is an input that accepts a list of terms or ranges
  • ranges: [{field: "prices.price" ...] is indicating that we want to return the range on the field prices.name
  • We then specify the ranges we want, in this example we want to bucket ranges from 0-100 and 101-200

Sample output from executing the graphql query above:

{
  "data": {
    "find": {
      "total": 5,
      "documents": [
        {
          "data": {
            "post_title": "price fifty",
            "prices": {
              "price": 50
            }
          }
        },
        {
          "data": {
            "post_title": "price sixty",
            "prices": {
              "price": 60
            }
          }
        },
        {
          "data": {
            "post_title": "price seventy",
            "prices": {
              "price": 70
            }
          }
        },
        {
          "data": {
            "post_title": "price one hundred and twenty",
            "prices": {
              "price": 120
            }
          }
        },
        {
          "data": {
            "post_title": "price one hundred and fifty",
            "prices": {
              "price": 150
            }
          }
        }
      ],
      "aggregations": {
        "ranges": [
          {
            "field": "prices.price",
            "ranges": [
              {
                "from": 0,
                "to": 100,
                "count": 3
              },
              {
                "from": 101,
                "to": 200,
                "count": 2
              }
            ]
          }
        ]
      }
    }
  }
}
  • The output of the query returns range aggregations counting documents that match each range that occur in the field prices.prices
  • from designates the start of a range bucket.
  • to designates the end of a range bucket
  • count is the ammount of occurences of the doucments in the specified range.
  • The total indicates how many documents were considered for the given search query ”*”

Lets update the query to filter out prices less than 100:

{
  find(
    query: "prices.price:>100"
    aggregate: {
      ranges: [{
        field: "prices.price"
        ranges: [
          { from: 0, to: 100 },
          { from: 101, to: 200 }
        ]
      }]
    }
  ) {
    total
    aggregations {
      ranges {
        field
        ranges {
          from
          to
          count
        }
      }
    }
  }
}

Sample output:

{
  "data": {
    "find": {
      "total": 2,
      "documents": [
        {
          "data": {
            "post_title": "price one hundred and twenty",
            "prices": {
              "price": 120
            }
          }
        },
        {
          "data": {
            "post_title": "price one hundred and fifty",
            "prices": {
              "price": 150
            }
          }
        }
      ],
      "aggregations": {
        "ranges": [
          {
            "field": "prices.price",
            "ranges": [
              {
                "from": 0,
                "to": 100,
                "count": 0
              },
              {
                "from": 101,
                "to": 200,
                "count": 2
              }
            ]
          }
        ]
      }
    }
  }
}

API Reference

The schema defines the GraphQL query type for searching documents in an index. It includes various parameters to customize the search query.

Query

Field Description
find Searches for documents in an index based on specific parameters.

Find Parameters

Parameter Type Description
query String! The search query. This is required.
filter String Filter string that will be added to the search query and filter out search results.
orderBy [OrderBy] Used for ordering the search results. By default, a weight policy is applied.
searchAfter [String!] Results offset used for cursor pagination.
offset Int Results offset used for pagination.
limit Int Results limit used for pagination.
fields [SearchField] Specifies the fields to search for in the documents.
tolerance SearchOption = \{ name: stemming \} Selects either Fuzzy or Stemming search option. By default, find will use stemming.
meta MetaInput Optional meta data.
aggregate AggregateInput Aggregation support.
semanticSearch SemanticSearchInput Semantic Search query input.

SearchField Input

Field Type Description
name String! The field name to search for in the document.
weight Int The weight of the field, affecting the order of returned documents.

MetaInput

Optional meta data input for logging

Field Type Description
action String Performed action e.g. index
system String The requester system name
source String The requester hostname

AggregateInput

Field Type Description
terms [TermAggregateInput] Aggregation based on terms.
ranges [RangeAggregateInput] Aggregation based on ranges.

TermAggregateInput

Field Type Description
field String! Field name we want to aggregate on
size Int To retrieve additional terms, employ the "size" parameter. By default, the terms aggregation fetches the top ten terms with the highest document counts.
minCount Int If minCount is zero, zero count results are returned (else we omit them)

RangeAggregateInput

Field Type Description
field String! Field name we want to aggregate on
ranges [RangeInput] Range Input options
size Int To retrieve additional terms, employ the "size" parameter. By default, the terms aggregation fetches the top ten terms with the highest document counts.

RangeInput

A multi-bucket value source based aggregation that enables the user to define a set of ranges - each representing a bucket

Field Type Description
to Float From value (Inclusive)
from Float To value (Exclusive)

OrderBy Input

Field Type Description
field String! The field to order the documents by.
direction OrderByDirection The sort direction (asc or desc).
unmappedType String Deprecated: Going to be removed soon. When its present default weight score is applied for ordering

SearchOption Input

Field Type Description
name SearchOptionEnum! The search option name (fuzzy or stemming).
fuzzyDistance Int Optional fuzzy distance. Applicable only if the fuzzy search option is selected. It represents the number of one-character changes needed to turn one term into another.

SemanticSearchInput

Semantic Search query input

Field Type Description
searchBias Int! The search bias of the semantic search query vs full text search - 0 = Full text search only, 10 = Semantic search only - 1-9 mix of both weighted respectfully
fields [String!]! Fields for search
type SEMANTIC_SEARCH_TYPE Semantic Search type

SearchResult Type

Field Type Description
total Int The total number of documents returned.
documents [SearchDocument] The list of documents matching the search.

SearchDocument Type

Field Type Description
id ID! The Search ID of the document.
score Float The Search score of the document.
sort [String] Values used to sort documents. Can be used in combination with searchAfter for cursor pagination.
data Map! The document data.

Enumerations

SearchOptionEnum

Name Description
fuzzy The fuzzy search option.
stemming The stemming search option.

OrderByDirection

Name Description
asc Sort in ascending order.
desc Sort in descending order.

SEMANTIC_SEARCH_TYPE

Value Description
BASIC Basic Search type