Data Aware UI components
One of the key ideas behind Reactive Search and Reactive Maps is the abstraction of a query interface.
The UI components are already associated with the data queries. For instance,
- SingleList, MultiList and TreeList components create a exact term match query based on the selected items.
- A RangeSlider component creates a numeric range query based on the selected
start
andend
values.
Components rely on the dataField
prop for selecting the database field on which the query needs to be applied.
However, there are cases where you would wish to override the associated query with your own.
When to use Custom Query
customQuery
is used to change the component's behavior for its subscribers. It gets triggered after an interaction on the component. Every component is shipped with a default behavior i.e. selecting a city on the SingleList component generates a term query. If you wish to change this behavior i.e. maybe perform additional query besides term
query or do something else altogether, you can use customQuery
prop.
customQuery = {() => ({
query: {
term: {
user : "Kimchy"
}
}
})
}
Defining a Custom Query
Each component has a customQuery
prop that accepts a function. The function can return an object in which you can define a query
key(to modify the actual query) along with the query options(to add the query options in the query generated by ReactiveSearch) compatible with Elasticsearch Query DSL. Here is a simple query object that applies a match query.
SearchBox
...
customQuery={this.customQuery}
/>
this.customQuery=function() {
return {
"query": {
"match": { "fieldName": "text to match" }
}
}
}
Here is another example that applies a match_phrase_prefix
query.
SearchBox
...
customQuery={this.customQuery}
/>
this.customQuery=function() {
return {
"query": {
"match_phrase_prefix": {
"fieldName": {
"query": "hello world",
"max_expansions": 10
}
}
}
}
}
You can also define the query options in custom query:
SearchBox
...
customQuery={this.customQuery}
/>
this.customQuery=function() {
return {
"timeout": "1s",
"query": {
"match_phrase_prefix": {
"fieldName": {
"query": "hello world",
"max_expansions": 10
}
}
},
}
}
When to use Default Query
defaultQuery
is ideally used with data-driven components to impact their own data. It is meant to modify the default query which is used by a component to render the UI.
Some of the valid use-cases are:
- To modify the query to render the
suggestions
in search components. - To modify the
aggregations
inlist
components. - To modify the default
results
inReactiveList
component.
For example, in a SingleList
component showing a list of cities, you may only want to render cities belonging to India.
defaultQuery = {() => ({
query: {
terms: {
country: [ "India" ]
}
}
})
}
Defining a Default Query
Some components have a defaultQuery
prop that accepts a function that has the same specifications as customQuery
.DefaultQuery is used to apply the query on the source component. Unlike customQuery
, It doesn't get leaked to other components. It's as if you create an internal component and apply the defaultQuery on it. Ideally, you would use this with components that are data-driven.
<SingleList
...
defaultQuery={this.defaultQuery}
/>
this.defaultQuery=function() {
return {
"query": {
"match_phrase_prefix": {
"fieldName": {
"query": "hello world",
"max_expansions": 10
}
}
}
}
}
You can also define the query options in the custom query:
<SingleList
...
defaultQuery={this.defaultQuery}
/>
this.defaultQuery=function() {
return {
"timeout": "1s",
"query": {
"match_phrase_prefix": {
"fieldName": {
"query": "hello world",
"max_expansions": 10
}
}
},
}
}
Not familiar to Elasticsearch?
You need to write a custom query but haven't worked with Elasticsearch. Okay, as a super quick primer, Elasticsearch is a data store search engine with a NoSQL JSON data model.
The docs link above is a good way to explore Elasticsearch in depth. Another alternative to get started with the query syntax is Mirage, a GUI for composing Elasticsearch queries.