Is it possible to limit the number of Match Queries inside a Bool Query that contribute to the score? - elasticsearch

Let's say I have the following Documents:
[
{
"name": "Berlin",
"name_english": "Berlin"
},
{
"name": "München",
"name_english": "Munich"
}
]
Now I do query 1:
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "Munich"
}
}
},
{
"match": {
"name_english": {
"query": "Munich"
}
}
}
]
}
}
}
Then I do query 2:
{
"query": {
"bool": {
"should": [
{
"match": {
"name": {
"query": "Berlin"
}
}
},
{
"match": {
"name_english": {
"query": "Berlin"
}
}
}
]
}
}
}
Query 1 will have a lower score than query 2, because query 2 has 2 hits. My goal now is to have only 1 hit maximum of the fields to contribute to the score. Is that possible somehow? Like "If there is a hit in the first Match Query, dont do the second one".

There is no out of the box solution, but maybe it's possible using the painless script, or you another way is you handle it from your application by sending queries in if..else conditions.

Related

How to filter result set of elasticsearch from another bool condition

I have to fetch data from API which use ElasticSearch.
The conditions of data fetching are firstname should start with given string and company status should be active,
so I have used the below query
"span_first": {
"match": {
"span_term": {
"employee.firstname": "tas"
}
},
"end": 1
}
to match firstname and now i need to filter the data from companyStatus,
"bool": {
"must": [
{
"match": {
"employee.companyStatus": "Active"
}
}
]
}
I'm trying to plug the above bool query into the span_first query
but I have no idea how to do it,
Can someone help me to create the query, sorry if this is a dumb question,
I'm totally new to Elasticsearch.
You can try to use Term Query for filter status and Match Query for search terms.
GET edx_test/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"employee.companyStatus": "Active"
}
}
],
"must": [
{
"match": {
"employee.firstname": "tas"
}
}
]
}
}
}
Read more:
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
If both the span_first and match query must be true then you can have both the queries in a must clause like below:
GET test_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"employee.companyStatus": "Active"
}
},
{
"span_first": {
"match": {
"span_term": {
"employee.firstname": "tas"
}
},
"end": 1
}
}
]
}
}
}

elasticsearch priorities search result in match query, composite bool query

I have below elasticsearch query and I want to set the priority order in my query.
irrespetive of scoure.
eg:
like if I set priority of attack_id > name > description
in the match query, then the result should come in this sorted order
attack_id, name, description
and if I set name > attack_id > description
name, attack_id, description
boosting query
function query I have tried both of these but don't get success. so I will be very grateful if someone helps me with this.
GET tridant_testing/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"attack_id": "T1592"
}
},
{
"match": {
"name": "T1592"
}
},
{
"match": {
"description": "T1592"
}
}
]
}
}
}
You can use boost param in match query to boost specific query clause like below:
{
"query": {
"bool": {
"should": [
{
"match": {
"attack_id": {
"query": "T1592",
"boost": 6
}
}
},
{
"match": {
"name": {
"query": "T1592",
"boost": 3
}
}
},
{
"match": {
"description": {
"query": "T1592"
}
}
}
]
}
}
}
Note: You may need to increase or decrease boost value as per your need.

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 multimatch substring search

I have to combine two filters to match requirements:
- a specific list of values in r.status field
- one of the multiple text fields contains the value.
Result query (with using Nest, but it doesn't matter) looks like:
{
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{
"term": {
"isActive": {
"value": true
}
}
},
{
"nested": {
"query": {
"bool": {
"must": [
{
"terms": {
"r.status": [
"VALUE_1",
"VALUE_2",
"VALUE_3"
]
}
},
{
"bool": {
"should": [
{
"match": {
"r.g.firstName": {
"type": "phrase",
"query": "SUBSTRING_VALUE"
}
}
},
{
"match": {
"r.g.lastName": {
"type": "phrase",
"query": "SUBSTRING_VALUE"
}
}
}
]
}
}
]
}
},
"path": "r"
}
}
]
}
}
]
}
}
}
Also tried with multi_match query:
{
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{
"term": {
"isActive": {
"value": true
}
}
},
{
"nested": {
"query": {
"bool": {
"must": [
{
"terms": {
"r.status": [
"VALUE_1",
"VALUE_2",
"VALUE_3"
]
}
},
{
"multi_match": {
"query": "SUBSTRING_VALUE",
"fields": [
"r.g.firstName",
"r.g.lastName"
]
}
}
]
}
},
"path": "r"
}
}
]
}
}
]
}
}
}
FirstName and LastName are configured in index mappings as text:
"firstName": {
"type": "text"
},
"lastName": {
"type": "text"
}
Elastic gives a lot of full-text search options: multi_match, phrase, wildcards etc. But all of them fail in my case looking a sub-string in my text fields. (terms query and isActive one work well, I just tried to run only them).
What options do I have also or maybe where I made a mistake?
UPD: Combined wildcards worked for me, but such query looks ugly. Looking for a more elegant solution.
The elasticsearch way is to use ngram tokenizer.
The ngram analyzer will split your terms with a sliding window. For example, the input "Hello World" will generate the following terms:
Hel
Hell
Hello
ell
ello
...
Wor
World
orl
...
You can configure the minimum and maximum size of the sliding window (in the example the minimum size is 3). Once the sub terms are generated you can use a match query an the subfield.
Another point, it is weird to use must within a filter. If you are interested in the score, you should always use must otherwise use filter. Read this article for a good understanding.

How to search with only raw query JSON with Elastic Java API 6.5.1?

How can I take the raw JSON String and query via the Java API? It should
work for any complex query that Curl accepts in Elastic.
For example:
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"name": "<name>"
}
},
{
"match": {
"address": {
"query": "<address>",
"fuzziness": 1,
"prefix_length": 1,
"operator": "or",
"minimum_should_match": "80%"
}
}
},
{
"match_phrase": {
"city_nm": "<city_nm>"
}
},
{
"term": {
"state_province_cd": "<state_province_cd>"
}
}
]
}
}
}
I tried Query Builders' simpleQueryStringQuery method to achieve this but it creates the query which doesn't give a correct result.
For Example, to search a record using just name, this is the query which simpleQueryStringQuery is generating but instead of returning just one record it returns multiple records.
{
"query": {
"simple_query_string": {
"query": """{"query":{"bool":{"must":[{"match_phrase":{"name":"Neeraj"}}]}}}"""
}
}
}
whereas if I run the same query like this in my Kibana console that returns the correct number of results.
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"name": "Jaas"
}
}
]
}
}
}

Resources