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 indexscore
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 avoidsort
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 / Hybrid Search
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 thepost_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 rangesterms: [{field: "categories.name"}]
is indicating that we want to aggregate on the fieldcategories.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 rangesranges: [{field: "prices.price" ...]
is indicating that we want to return the range on the fieldprices.name
- We then specify the ranges we want, in this example we want to bucket ranges from
0-100
and101-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 bucketcount
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 |