The query_string
type lets us construct a query using operators such as AND
or OR
, as well as the logical operators such as > (greater than), <= (less than or equal to), * (contains in), and so on. This is easily understood when explained with an example, so let’s jump right in to getting our code ready.
To fetch Bert’s books, we use a request url query like: title:Java and author :Bert and edition:2 and release_date>=2000–01–01.
The same is ahieved this by writing a query_string
query as the code in the following listing demonstrates.
Listing : Creating a query string with operator
The query_string
query expects a query parameter where we provide our criteria. The query is constructed as name-value pairs: for example, in the previous listing, author
is the field, and Bert
is the value. Looking at the code in that listing, we notice a few things:
- The search query is built using the Query DSL syntax (the GET request has a body).
- The search criteria is written to concatenate the fields using operators.
The query is as simple as writing a question in plain English. We can create a complex criteria using these operators (in plain English) and provide it to the engine to get the results for us.
Sometimes, we do not know which fields users are expected to search; they may want the query to focus on the title
field, or on the synopsis
or tags
fields, or all of them. In the next section, we will go over the ways of specifying fields.
Fields in a query string query
In a typical search box, the user does not need to mention the field when searching for something. For example, take a look at the query in the following listing.
GET books/_search
{
"query": {
"query_string": {
"query": "Patterns"
}
},
"highlight": {
"fields": {
"title": {},
"synopsis": {},
"tags": {}
}
}
}
We want to search for the keyword Patterns in the previous query (previous listing). One quick thing to remember is that the query is not asking us to search any fields. It is a generic query that’s actually expected to be executed across all fields. The response (shown in the following snippet) shows that some results were highlighted on a different field for individual documents:
"highlight" : {
"synopsis" : ["Head First Design <em>Patterns</em> is one of ..."],
"title" : ["Head First Design <em>Patterns</em>"]
},
...
"highlight" : {
"synopsis" : [ "create .. using modern application <em>patterns</em>"]
},
...
Instead of letting the engine search query against all the available fields, we can assist Elasticsearch by providing the fields to run the search on. The next listing shows how to do this.
GET books/_search
{
"query": {
"query_string": {
"query": "Patterns",
"fields": ["title","synopsis","tags"]
}
}
}
Here, we specify the fields explicitly in an array in the fields
parameter and mention the fields that this criteria is expected to be performed against.
If we are not sure of the fields when constructing this query, we can use another parameter, default_field
as the query in the following listing demonstrates.
GET books/_search
{
"query": {
"query_string": {
"query": "Patterns",
"default_field": "title"
}
}
}
If a field is not mentioned in the query, the search is carried out against the title
field. That’s because the title field is declared as the default_field
in the previous listing.
Default operator
In our earlier code example listing, we searched for a single word, Patterns. If we extend that search to include an additional word such as Design, we may get multiple books (two books with the current dataset) instead of the correct one: Head First Design Patterns. The reason is that Elasticsearch uses the OR operator by default when searching. Hence, it finds books with both words, Design OR Patterns in the title
field.
If this is not our intention (say, for example, we want to fetch a book with the exact phrase Design Patterns in the title), we should use the AND operator. The query_string
query in the following listing has an additional parameter, default_operator
, where we can set the operator to AND
.
GET books/_search
{
"query": {
"query_string": {
"query": "Design Patterns",
"default_field": "title",
"default_operator": "AND"
}
}
}
This query_string
query is declared with the AND
operator. Hence, you’d expect Design Patterns to be treated as a single word.