Elastic search ORing and ANDing in query - elasticsearch

I want to use ORing and ANDing in my Elastic Search Query. I did parent -child mapping. I used query as:
{
"from" : 0, "size" : 100,
"query": {
"bool": {
"should": [
{
"query": {
"match_phrase": {
"question_title": {
"query": 'searchKey',
"slop": 3
}
}
}
},
{
"query": {
"has_parent": {
"type": "question_data",
"query": {
"match_phrase": {
"question_title": {
"query": 'searchKey',
"slop": 3
}
}
}
}
}
}
]
}
}
}
Thanks in advance..

Related

Convert intervals query to the earlier version that doesn't support it

I have an ES query that was written in a newer version of ES that supports intervals query.
But I want to convert this simple query that has intervals in it to the query to run on the earlier version of 6 that doesn't support intervals
GET /myindex/_search
{
"query": {
"bool": {
"should": [
{
"intervals": {
"title_en": {
"match": {
"query": "title phrase in en",
"max_gaps": -1,
"ordered": true
}
}
}
},
{
"intervals": {
"title_de": {
"match": {
"query": "title phrase in de",
"max_gaps": -1,
"ordered": true
}
}
}
}
],
"minimum_should_match" : 1,
"filter": [
{
"terms": {"status.id": [1,2]}
}
]
}
}
}
I think I should solve it with query_string.
I write something like this(part of it):
{
"query_string": {
"default_field": "title_en",
"query": "\"title phrase in en\"~3"
}
}
But I think it's not the correct solution.
The following query allows getting results similar to intervals.
intervals are replaced with match_phrase and slop is used.
slop value can be configured to allow us to control how many words can be placed between query words.
So query is:
GET /myindex/_search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"title_en": {
"query": "title phrase in en",
"slop": 5
}
}
},
{
"match_phrase": {
"title_de": {
"query": "title phrase in de",
"slop": 5
}
}
}
],
"minimum_should_match" : 1,
"filter": [
{
"terms": {"status.id": [1,2]}
}
]
}
}
}

Elasticsearch: Rank by most number of should matches

I have an indexed job description field. I am trying to rank or order the results by number of matches.
Example, I am searching for:
friendly
honest personality
excellent communication skills
Records with most number of matches will be ranked highest.
I tried the suggested here https://stackoverflow.com/a/45319822/2445717 but did not work as what I expected.
Below is my current query:
{
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"job_description": {
"query": "friendly",
"operator": "and"
}
}
},
{
"match": {
"job_description": {
"query": "honest personality",
"operator": "and"
}
}
},
{
"match": {
"job_description": {
"query": "excellent communication skills",
"operator": "and"
}
}
}
]
}
}
]
}
}
}
match_query & minimum_should_match did the trick.
posting example code in case someone will need it.
{
"query": {
"bool": {
"should": [
{
"match_query": {
"job_description": {
"query": "friendly",
"boost": 1
}
}
},
{
"match_query": {
"job_description": {
"query": "honest personality",
"boost": 1
}
}
},
{
"match_query": {
"job_description": {
"query": "excellent communication skills",
"boost": 1
}
}
}
],
"minimum_should_match": 1
}
}
}

Elasticsearch return exact match first then other matches

I have some PageDocuments which I would like to search based on the title, excluding PageDocuments with a path starting with some particular text. This field is analyzed. I would like some fuzziness to help users with spelling mistakes. I need to be able to do partial matches so some would match some text and this is some text.
If I use the following query I don't get an exact match back as the first result because of tf-idf
{
"size": 20,
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "myterm",
"fuzziness": 1
}
}
}
],
"must_not": [
{
"wildcard": {
"path": {
"value": "/test/*"
}
}
}
]
}
}
}
So then I added a not_analyzed version of the title field at title.not_analyzed and tried adding a function score to increase the weighting of an exact match using term.
{
"query": {
"function_score": {
"functions": [
{
"weight": 2,
"filter": {
"fquery": {
"query": {
"term": {
"title.not_analyzed": {
"value": "myterm"
}
}
}
}
}
}
],
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "myterm",
"fuzziness": 1
}
}
}
],
"must_not": [
{
"wildcard": {
"path": {
"value": "/path/*"
}
}
}
]
}
},
"boost_mode": "multiply"
}
}
}
But this gives me the same results. How can I get the exact matches returned first?
We found a solution to this by adding a combination of should and boost.
{
"size": 20,
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "myterm",
"fuzziness": 1
}
}
}
],
"must_not": [
{
"wildcard": {
"path": {
"value": "/path/*"
}
}
}
],
"should": [
{
"term": {
"title": {
"value": "myterm",
"boost": 10
}
}
}
]
}
}
}

How to Boost a field based on condition in ElasticSearch

I am having a query structure like
{
"sort": {},
"query": {
"bool": {
"should": [
{
"match_phrase": {
"user_categories": "Grant Writing"
}
},
{
"match_phrase": {
"user_agencies": "Census"
}
},
{
"match_phrase": {
"user_agencies": "MDA"
}
},
{
"match_phrase": {
"user_agencies": "OSD"
}
}
]
}
},
"size": 500,
"from": 0
}
Suppose this will return a list of 10 users.
What I need to get is, the user having Agency: 'Census' to be the first one in the search result (boost the results having Census as agency). How can we do this?
The following will do it. I converted some of the match_phrase queries to match queries as they contain only single terms
{
"sort": {},
"query": {
"bool": {
"should": [
{
"match_phrase": {
"user_categories": "Grant Writing"
}
},
{
"match": {
"user_agencies": {
"query": "Census",
"boost": 3
}
}
},
{
"match": {
"user_agencies": {
"query": "MDA",
}
},
{
"match": {
"user_agencies": {
"query": "OSD",
}
}
]
}
},
"size": 500,
"from": 0
}
You should boost at query time, and give a big boost documents with "Census" in the agency field. If the boost is high enough, a document matching "Census" will always be on top, regardless of the values for the other fields.
{
"sort": {},
"query": {
"bool": {
"should": [
{
"match_phrase": {
"user_categories": "Grant Writing"
}
},
{
"match_phrase": {
"user_agencies": "Census", "boost": 10
}
},
{
"match_phrase": {
"user_agencies": "MDA"
}
},
{
"match_phrase": {
"user_agencies": "OSD"
}
}
]
}
},
"size": 500,
"from": 0
}

How to distinguish hits of several should clauses

I have a query with several "should" clauses:
{
"query": {
"filtered": {
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "<condition1>"
}
},
{
"query_string": {
"query": "<condition1>"
}
}
]
}
},
}
},
"size": 1000,
"sort": [
{
"#timestamp": {
"order": "asc"
}
}
]
}
How can I find out which query results were produced by condition1, and which by condition2? Is it possible to inject a field with different values for different conditions, or distinguish hits in any other way?
You can use named queries to achieve this.
{
"query": {
"bool": {
"should": [
{
"query_string": {
"query": "<condition1>",
"_name": "sub_query_1"
}
},
{
"query_string": {
"query": "<condition1>",
"_name": "sub_query_2"
}
}
]
}
}
}
You result will then contain a matched_filters array with either sub_query_1, sub_query_2, or both in it.
Update
Play link: https://www.found.no/play/gist/af1a1fa2b5cf3aa279b1

Resources