How can I dynamically create a combined Q query in elasticsearch dsl python? I have gone through docs and this SO post. I constructed a q_query dictionary with all required info.
ipdb> q_queries
{'queries': [{'status': 'PASS'}, {'status': 'FAIL'}, {'status': 'ABSE'}, {'status': 'WITH'}], 'operation': 'or'}
I want to perform the following q_query
qq=Q("match", status='PASS') | Q("match", status="FAIL") | Q("match", status="ABSE") | Q("match", status="WITH")
for a list of dict following works out
ipdb> [Q('match', **z) for z in q_queries['queries']]
[Match(status='PASS'), Match(status='FAIL'), Match(status='ABSE'), Match(status='WITH')]
But How to combine multiple Qs with an or operator or an and operator? Also what is the corresponding elasticsearch raw query
for the above? I tried following since I have to filter based on test_id.
{
"query": {
"bool": {
"must": [
{ "match": { "test_id": "7" }},
{
"range": {
"created": {
"gte": "2016-01-01",
"lte": "2016-01-31"
}
}
}
],
"should": [
{ "match": { "status": "PASS"}},
{ "match": { "status": "FAIL"}}
]
}
}
}
But results are not as expected I same query without should filter
and the results obtained were the same. So should filters were not executed by elasticsearch in my case.
Any help is much appreciated.
TIA
After exploring elasticsearch dsl python for some more time, this piece of documentation helped me to solve above issue. Below posted is the function that I wrote to resolve this issue.
def create_q_queries(self, q_queries, search_query):
"""
create q queries and chain if multiple q queries.
:param q_queries: Q queries with operation and query params as a dict.
:param search_query: Search() object.
:return: search_query updated with q queries.
"""
if q_queries:
logical_operator_mappings = {'or': 'should', 'and': 'must'}
for query in q_queries:
queries = [Q('match', **query) for query in query['queries']]
search_query = search_query.query(Q('bool', **{
logical_operator_mappings.get(query.get('operation')): queries
}))
return search_query
I changed format of q_queries to perform chaining based on multiple operators like and
, or
etc.
q_queries = [
{
"operation": "or",
"queries":
[
{"status": "PASS"}, {"status": "FAIL"}, {"status": "ABSE"}, {"status": "WITH"}
]
}
]