Elasticsearch: Rank by most number of should matches - elasticsearch

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
}
}
}

Related

How to combine Boolean AND with Boolean OR in Elasticsearch query?

Query: Get employee name "Mahesh" whose id is "200" and joining datetime is in a given date range and his epf status must be either 'NOK' or 'WRN'. (Possible values of epf_status are {OK,NOK,WRN,CANCELLED}.
I have written the following query, that matches epf_status also with OK, CANCELLED, but it must only match when epf_status is either 'NOK' or 'WRN'. What else do I need to change to make it work, as required?
GET myindex01/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"empname": { "query": "Mahesh", "operator": "AND" }
}
},
{
"match": {
"empid": { "query": "200", "operator": "AND" }
}
},
{
"range": {
"joining_datetime": {
"gte": "2020-01-01T00:00:00",
"lte": "2022-06-24T23:59:59"
}
}
}
],
"should": [
{ "match": { "epf_status": "NOK" } },
{ "match": { "epf_status": "WRN" } }
]
}
}
}
SAMPLE DATA:
{"Mahesh","200","2022-04-01","OK"}
{"Mahesh","200","2022-04-01","NOK"}
{"Mahesh","200","2022-04-01","WRN"}
{"Mahesh","200","2022-04-01","CANCELLED"}
REQUIRED OUTPUT:
{"Mahesh","200","2022-04-01","NOK"}
{"Mahesh","200","2022-04-01","WRN"}
Tldr;
You could be using the terms query for that I believe.
Returns documents that contain one or more exact terms in a provided field.
To solve
GET myindex01/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"empname": { "query": "Mahesh", "operator": "AND" }
}
},
{
"match": {
"empid": { "query": "200", "operator": "AND" }
}
},
{
"range": {
"joining_datetime": {
"gte": "2020-01-01T00:00:00",
"lte": "2022-06-24T23:59:59"
}
}
}
],
"should": [
{ "terms": { "epf_status": ["NOK", "WRN"] } }
]
}
}
}

How to create an ElasticSearch Query which should not match any of multiple categories

I'm looking for documents inside elasticSearch which do not match one or the other brand, but fullFill a fix requirement. I'm looking for any entries which are not from Toyota, BMW or Audi. But the entry must be a superEntry (exact match)
The following Query is what I'm working on:
"query": {
"bool": {
"filter": {
"term": {
"superEntry": true
}
},
"must": {
"bool": {
"must_not": [
{
"term": {
"brand": "Toyota"
}
},
{
"term": {
"brand": "BMW"
}
},
{
"term": {
"brand": "Audi"
}
}
]
}
}
}
}
}
Expected: I find any super-entries from any other brand, but not from those 3. The query above still lists me cars from BMW as an example..
Not tested but something like this will help-
{
"size": 10,
"query": {
"bool": {
"must": [
{
"match": {
"superEntry": true
}
}
],
"must_not": [
{
"terms": {
"brand": [
"Toyota",
"BMW",
"Audi"
]
}
}
]
}
}
}

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
}
}
}
]
}
}
}

Elasticsearch query + filter

This is my original query dsl, and total of hits was 8,981.
GET /{index}/{document}/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "blue shoes",
"boost": 2
}
}
},
{
"match": {
"description": {
"query": "blue shoes",
"operator": "and",
"boost": 1
}
}
}
]
}
}
}
I want to add filter to this query.
GET /{index}/{document}/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "blue shoes",
"boost": 2
}
}
},
{
"match": {
"description": {
"query": "blue shoes",
"operator": "and",
"boost": 1
}
}
}
],
"filter": {
"terms": {
"store.id": [ "store_a.com", "store_b.com" ]
}
}
}
}
}
Now its total of hits is 15,989(increased).
And I sort the result by score in asc(I don't know why it's asc not desc), there are documents which is scored 0.
I think there is no more filtering by query because it is already filtered.
Can I remove 0 scored documents from the result?
To add a filter, use a must clause in your bool query to add a mandatory value. Try :
GET /{index}/{document}/_search
{
"query": {
"bool": {
"must": [
"terms": {
"store.id": [ "store_a.com", "store_b.com" ]
}
],
"should": [
{
"match": {
"title": {
"query": "blue shoes",
"boost": 2
}
}
},
{
"match": {
"description": {
"query": "blue shoes",
"operator": "and",
"boost": 1
}
}
}
]
}
}
}

Elasticsearch Parse Exception for boolean queries

I'm trying to create queries similar to kibana queries in elasticsearch lucene queries. What I'm basically trying to do is matching some phrases. For example; my kibana query looks like this:(+"anna smith") AND ( (+"university"), (+"chairman"), (+"women rights")) It searches "anna smith" as must and one of the other phrases as should(there should be at least one of them exist in the text). I wrote a query to do this but it gives "elasticsearch parse exception:expected field name but got start_object". How can I solve this. Here is my query;
{
"query": {
"bool": {
"must": {
"match": {
"text": {
"query": "anna smith",
"operator": "and"
}
}
}
},
"query": {
"bool": {
"must": [
{
"bool": {
"should": [
{
"match": {
"text": {
"query": "university",
"boost": 2
}
}
},
{
"match": {
"text": {
"query": "chairman",
"boost": 2
}
}
}
]
}
}]
}}}}
Your second query at the bottom cannot be there, it needs to be inside the first bool/must like this
{
"query": {
"bool": {
"must": [
{
"match": {
"text": {
"query": "anna smith",
"operator": "and"
}
}
},
{
"bool": {
"should": [
{
"match": {
"text": {
"query": "university",
"boost": 2
}
}
},
{
"match": {
"text": {
"query": "chairman",
"boost": 2
}
}
}
]
}
}
]
}
}
}

Resources