After inserting documents, the most commonly executed action in Elasticsearch is the search. The official Elasticsearch client APIs for searching are similar to the REST API.
You need an up-and-running Elasticsearch installation, as we described in the Downloading and installing Elasticsearch recipe in Chapter 2, Downloading and Setup.
You also need the Python installed packages of the Creating a client recipe of this chapter.
The code of this recipe can be found in the chapter_16/searching.py
file.
To execute a standard query, the client method search
must be called by passing the query
parameters, as we have seen in Chapter 5, Search. The required parameters are index_name
, type_name
and the query DSL. In this example, we show how to call a match_all
query, a term
query, and a filter
query. We will perform the following steps:
import elasticsearch from pprint import pprint es = elasticsearch.Elasticsearch() index_name = "my_index" type_name = "my_type" if es.indices.exists(index_name): es.indices.delete(index_name) from utils import create_and_add_mapping, populate create_and_add_mapping(es, index_name, type_name) populate(es, index_name, type_name)
match_all
query and we will print the results:results = es.search(index_name, type_name, {"query": {"match_all": {}}}) pprint(results)
term
query and we will print the results:results = es.search(index_name, type_name, { "query": { "query": { "term": {"name": {"boost": 3.0, "value": "joe"}}} }}) pprint(results)
bool
filter query and we will print the results:results = es.search(index_name, type_name, {"query": { "bool": { "filter": { "bool": { "should": [ {"term": {"position": 1}}, {"term": {"position": 2}}]} }}}}) pprint(results)
es.indices.delete(index_name)
The idea behind Elasticsearch official clients is that they should offer a common API that is more similar to REST calls. In Python, it is very easy to use the query DSL, as it provides an easy mapping from the Python dictionary to JSON objects and vice versa.
In the preceding example, before calling the search, we need to initialize the index and put some data in it; this is done using the two helpers available in the utils
package, available in chapter_16
directory.
The two methods are:
create_and_add_mapping(es, index_name, type_name)
: This initializes the index and inserts the correct mapping to perform the search. The code of this function is taken from the Managing mappings recipe in this chapter.populate(es, index_name, type_name)
: This populates the index with data. The code of this function is taken from the previous recipe.After having initialized some data, we can execute queries against it. To execute a search, the method that must be called is search
on the client. This method accepts all parameters described for REST calls in the Searching recipe in Chapter 5, Search.
The actual method signature for the search
method is as follows:
@query_params('_source', '_source_exclude', '_source_include', 'allow_no_indices', 'analyze_wildcard', 'analyzer', 'default_operator', 'df', 'docvalue_fields', 'expand_wildcards', 'explain', 'fielddata_fields', 'from_', 'ignore_unavailable', 'lenient', 'lowercase_expanded_terms', 'preference', 'q', 'request_cache', 'routing', 'scroll', 'search_type', 'size', 'sort', 'stats', 'stored_fields', 'suggest_field', 'suggest_mode', 'suggest_size', 'suggest_text', 'terminate_after', 'timeout', 'track_scores', 'version') def search(self, index=None, doc_type=None, body=None, params=None):
The index
value could be:
index1,index2,indexN
)_all
is the special keyword that indicates all the indicesThe type
value could be:
type_name
type1,type2,typeN
)None
to indicate all the typesThe body is the search DSL, as we have seen in Chapter 5, Search. In the preceding example we have:
match_all
query (see the Matching all the documents recipe in Chapter 5, Search) to match all the index-type documents:results = es.search(index_name, type_name, {"query": {"match_all": {}}})
term
query that matches a name term joe
with boost 3.0
(for further details, see the Quering for a single term recipe in Chapter 6, Text and Numeric Queries):results = es.search(index_name, type_name, { "query": { "query": { "term": {"name": {"boost": 3.0, "value": "joe"}}} }})
match_all
) and an or
filter with two term
filters matching position 1
and 2
.results = es.search(index_name, type_name, {"query": { "bool": { "filter": { "bool": { "should": [ {"term": {"position": 1}}, {"term": {"position": 2}}]} }}}})
The returned result is a JSON dictionary, which we discussed in Chapter 5, Search.
If some hits are matched, they are returned in the hits field. The standard number of results returned is 10
. To return more results, you need to paginate the results with the from
and start
parameters.
In Chapter 5, Search, there is a definition of all the parameters used in the search.
18.227.81.42