Concepts
The ReactiveSearch
API is derived from the ReactiveSearch
library. If you're already using ReactiveSearch
in your projects, then you will feel right at home because API maintains a 100% prop parity with the library. Even if you haven't worked with ReactiveSearch
before, you should be able to follow along as we'll cover all aspects of ReactiveSearch API
in this document.
Query Identifier(ID)
Every query made via the ReactiveSearch API
must have an id
property defined. id
is a unique identifier for each query. The id
property is also useful to access the response for a particular query if multiple queries are defined within a single ReactiveSearch API call. The id can be referenced in the react
property of any other queries that wish to also apply this query. We'll talk more about the usage of react
property later and will explain how to reference an id
in react
property to combine multiple queries.
Type of Queries
ReactiveSearch API
has five types of queries, each serving a different use-case. You can decide which query has to be used by defining the type
property in the query object.
Search Query (default)
Search queries (type: search
) allow you to find documents for which the value
matches in any of the fields specified in its dataField
property. Search queries can take into account the text analysis process, partial words, as-you-type queries, can handle typo tolerance, offer response highlighting and search on synonyms. All of these are configurable by the search query's properties.
You should use this query type when:
- you want to provide an approximate or intelligent match instead of or in addition to providing an exact match.
Example
The below query returns all the books for which either the title
or description
fields match with the value as harry
.
{
id: "book_search",
type: "search",
dataField: ["title", "title.keyword", "title.search", "description", "description.keyword", "description.search"],
value: "harry"
}
Note: The above example searches on title
, title.keyword
and title.search
fields.
When you use appbase.io, it indexes all the search use-case fields using a variety of analyzers so that they are searchable no matter what the context is. The table below explains the sub-fields indexed by appbase.io and when to use them:
Field |
Description |
>When To Use</p |
---|---|---|
${field} |
Analyzed field using a standard analyzer. | A good default field to search on. |
${field}.keyword |
Non-analyzed field. | Useful for finding exact matches. |
${field}.search |
Analyzed field using a {2, 9} n-gram analyzer. | This is useful for partial word matches. |
${field}.autosuggest |
Analyzed field using a {2, 20} edge n-gram analyzer. | This is useful for longer partial word matches, typically suited for an autosuggest search. |
${field}.lang |
Analyzed field using the user provided language. | This is useful when searching on text in a specific language, e.g. Spanish. |
${field}.synonyms |
Analyzed field for handling synonyms at search time. | This is useful when synonyms are enabled. |
Suggestion
A suggestion type query is an extension of the search
type of query designed to retrieve typeahead or autocomplete suggestions.
The ideal use-cases are:
- To build an auto-suggestions or autocompletion based searchbox,
- To programmatically display search suggestions via an API
Suggestion type of queries support the following types of suggestions:
-
Promoted suggestions represents the documents promoted by the Query Rules UI of Appbase.io dashboard.
-
Recent suggestions are the past searches made by the user in last 30 days.
-
Popular suggestions are the most searched queries for a particular index.
-
Index suggestions are the suggestions derived from the index, can take into account the text analysis process, partial words, as-you-type queries, can handle typo tolerance, offer response highlighting and search on synonyms.
Depending on the user request, it combines and returns the requested suggestion types in a single API request.
Example
The below suggestions API request returns matching popular, recent, and index suggestions for search query harry
.
Term
Term queries (type: term
) allow you to find documents that contain an exact
term match in the field specified in its dataField
property. Term queries also return the terms aggregation (unique terms present for the field with the counts) for the specified dataField
.
You use this query type when:
- you want to provide an exact match filter,
- you want to show a list of unique terms with their counts, e.g. as a facet filter.
Note: Term queries can further filter
on a subset of the search results based on other queries that are applied alongside the term query using the react property.
Example
The below query returns all the books for which authors.keyword
field has a value of J.K. Rowling
.
{
id: "author_search",
type: "term",
dataField: ["authors.keyword"],
value: "J.K. Rowling"
}
Range
Range (type: range
) queries allow you to find documents that contain a range match on the fields specified in its dataField
property. The field's mapping must of either numeric or date type.
You use this query type when:
- you want to provide a range filter that optionally can aggregate on provided intervals.
Example
The below query returns all the books for which the price
field has a value between 200
to 400
.
{
id: "book_search",
type: "range",
dataField: ["price"],
value: {
start: 200,
end: 400
},
}
Geo
Geo queries (type: geo
) allow you to find documents within a provided distance of a location.
You use this query type when:
- you want to search on a field of
geopoint
mapping.
Example
The below query returns all the restaurants within a 50
miles radius of the provided location
value.
{
id: "restaurant_search",
type: "geo",
dataField: ["location"],
value: {
"distance": 50,
"unit": "mi",
"location": "22.3184816, 73.17065699999999"
}
}
How to define a query
Let's have a look at this simple search query with ReactiveSearch
API. It retrieves all the results for which the title
field matches the value iphone
.
{
query: [{
id: "phone-search", // Unique identifier for the query
dataField: ["title"], // data field in the database
value: "iphone", // search term
size: 10 // sizes of the documents to retrieve
}]
}
Instead of what would typically be an imperative query DSL, we are using a declarative API. The above query will return up to 10
documents for which the title
field matches with the search term iphone
. The response will have the following structure:
{
"phone-search": {
"hits": {
"hits": [
{
....
},
{
....
},
....
]
"max_score": 6.967817,
"total": {
"relation": "eq",
"value": 25
}
},
"status": 200,
"timed_out": false,
"took": 362
},
"settings": { // reserved key
"took": 369
}
}
How do multiple queries work?
It's simple to define multiple queries with the ReactiveSearch API
endpoint. Check the example below which executes two different queries in a single API request. This is the equivalent of using the msearch
API of Elasticsearch.
{
query: [
{
id: "phone-search",
type: "search",
dataField: ["title"],
value: "iphone", // search term
size: 10 // size of the documents to retrieve
},
{
id: "launch-year",
type: "term",
dataField: ["launched_year"],
size: 10 // size of the aggregations to retrieve
}
]
}
The first query is a search
query and the second query is a term
query to return the aggregated results for the launched_year
field.
The above query will return the response in the following shape:
{
"phone-search": {
"hits": {
"hits": [
{
....
},
{
....
},
....
]
"max_score": 6.967817,
"total": {
"relation": "eq",
"value": 25
}
},
"status": 200,
"timed_out": false,
"took": 362
},
"launch-year": {
"aggregations": {
"launched_year": {
...
}
},
"hits": {
"hits": [],
"max_score": null,
"total": {
"relation": "eq",
"value": 10
}
},
"status": 200,
"timed_out": false,
"took": 56
},
"settings": { // reserved key
"took": 369
}
}
How to combine multiple queries?
In the above example, we showed an example that defines multiple queries using the ReativeSearch API
. Now, in addition - we want a defined query to also influence another query's results. We can do this with the help of the react
property.
{
query: [
{
id: "phone-search",
type: "search",
dataField: ["title"],
value: "iphone",
size: 10,
react: { // `react` property defines a dependency on the `launch-year` query id
and: "launch-year"
}
},
{
id: "launch-year",
type: "term",
dataField: ["launched_year"],
size: 10,
execute: false // Set `execute` property to false to prevent execution of the query
}
]
}
Custom and Default Queries
Although ReactiveSearch API
covers most of the common use-cases for search, sometimes you may require a complete control over the query that is being generated. Query customization is possible with the help of customQuery
and defaultQuery
properties. You can read more about it in the ReactiveSearch API Reference.
How to implement?
REST API
POST /:index/_reactivesearch.v3 endpoint allows you to execute the ReactiveSearch
queries from any platform of your choice.
For example:
curl --location --request POST 'http://{{user}}:{{password}}@{{host}}/{{index}}/_reactivesearch.v3' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": [
{
"id": "book_search",
"dataField": [
"original_title"
],
"value": "harry",
"size": 10
}
]
}'
Frontend libraries
We have a set of frontend libraries for different platforms that support the ReactiveSearch API
. These libraries have a property called enableAppbase
which can be set to true
to use the ReactiveSearch API
instead of using Elasticsearch's query DSL.
Here is a list of all frontend libraries available for different platforms:
Library |
Variant |
Docs |
---|---|---|
ReactiveSearch |
React |
Learn More |
ReactiveSearch |
Vue |
Learn More |
SearchBox |
VanillaJS |
Learn More |
SearchBox |
React |
Learn More |
SearchBox |
Vue |
Learn More |
SearchBase |
VanillaJS |
Learn More |