I need to retrieve documents that match the following criteria:
{ "field1: "string1" AND "field2": "string2"}
OR
{ "field1: "string3" AND "field2": "string4"}
OR
{ "field1: "string5" AND "field2": "string6"}
I can do that for one set of conditions like this
How to achieve that for multiple sets in a single query?
You can simply wrap all your OR conditions in a bool/should query:
{
"query": {
"bool": {
"minimum_should_match": 1,
"should": [
{
"bool": {
"must": [
{
"match": {
"field1": "string1"
}
},
{
"match": {
"field2": "string2"
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"field1": "string3"
}
},
{
"match": {
"field2": "string4"
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"field1": "string5"
}
},
{
"match": {
"field2": "string6"
}
}
]
}
}
]
}
}
}
Related
For example in SQL I would write (a AND b) OR (c AND d). But I can't find a direct analogue in elasticsearch.
Yes, it's doable via bool/should, like this:
{
"query": {
"bool": {
"should": [
{
"bool": {
"filter": [
{
"match": {
"field1": "foo"
}
},
{
"match": {
"field2": "bar"
}
}
]
}
},
{
"bool": {
"filter": [
{
"match": {
"field1": "baz"
}
},
{
"match": {
"field2": "fox"
}
}
]
}
}
]
}
}
}
In Elasticsearch,
should is equivalent to OR in SQL and must is equivalent to AND.
So the following query is equivalent to your SQL query and will fetch first 10 results.
(A=a AND B=b) OR (C=c AND D=d)
GET /<indexName>/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"bool": {
"must": [
{
"match": {
"A": "a"
}
},
{
"match": {
"B": "b"
}
}
]
}
}
},
{
"match": {
"bool": {
"must": [
{
"match": {
"C": "c"
}
},
{
"match": {
"D": "d"
}
}
]
}
}
}
]
}
},
"from": 0,
"size": 10,
"sort": [],
"aggs": {}
}
Reference: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
So I have an search query in Elasticsearch which queries a field called myList. Inside that list are elements. elm1, elm2, and elm3. I want to be able to query that list such that all the elements must match. For example:
myList: [{
elm1: "value1",
elm2: "value2",
elm3: "value4"
},
{
elm1: "value2"
elm2: "value3"
elm3: "value3"
},
{
elm1: "value3",
elm2: "value4",
elm3: "value5"
}]
If I construct a query such that it searches for the field: elm1 = value1 and elm2 = value2 and elm3=value3,
"query": {
"bool": {
"must": [],
"filter": [
{
"bool": {
"filter": [
{
"bool": {
"should": [
{
"query_string": {
"fields": [
"myList.elm1.keyword"
],
"query": "value1"
}
}
],
"minimum_should_match": 1
}
},"bool": {
"filter": [
{
"bool": {
"should": [
{
"query_string": {
"fields": [
"myList.elm2.keyword"
],
"query": "value2"
}
}
],
"minimum_should_match": 1
}
},"bool": {
"filter": [
{
"bool": {
"should": [
{
"query_string": {
"fields": [
"myList.elm3.keyword"
],
"query": "value3"
}
}
],
"minimum_should_match": 1
}
}
}
]
}
}
It will return true because
myList[0]['elm1']=value1
myList[0]['elm2']=value2
myList[1]['elm3']=value3
This is not what I want.
How do I get it such that
myList[x]['elm1']=value1
myList[y]['elm2']=value2
myList[z]['elm3']=value3
Where x=y=z
When you're deailing with arrays of objects, these objects get flattened and essentially lose the connections between each other.
You should use the nested field type instead:
PUT elms_deep
{
"mappings": {
"properties": {
"myList": {
"type": "nested"
}
}
}
}
then re-add your documents:
POST elms_deep/_doc
{
"myList": [
{
"elm1": "value1",
"elm2": "value2",
"elm3": "value4"
},
{
"elm1": "value2",
"elm2": "value3",
"elm3": "value3"
},
{
"elm1": "value3",
"elm2": "value4",
"elm3": "value5"
}
]
}
and then proceed with the 3 nested term queries -- no need for your original query_string queries when you're targeting .keyword fields:
POST elms_deep/_search
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "myList",
"query": {
"term": {
"myList.elm1.keyword": {
"value": "value1"
}
}
}
}
},
{
"nested": {
"path": "myList",
"query": {
"term": {
"myList.elm2.keyword": {
"value": "value2"
}
}
}
}
},
{
"nested": {
"path": "myList",
"query": {
"term": {
"myList.elm3.keyword": {
"value": "value3"
}
}
}
}
}
]
}
}
}
So Joe's answer is nearly there, he's right you need to use the nested field type. His answer gives the possibility of
myList[x]['elm1']=value1
myList[y]['elm2']=value2
myList[z]['elm3']=value3
Where x,y,z are independent elements.
If you want x=y=z:
{
"query": {
"nested": {
"path": "myList",
"query": {
"bool": {
"filter": [
{
"term": {
"myList.elm1.keyword": {
"value": "value1"
}
}
},
{
"term": {
"myList.elm1.keyword": {
"value": "value1"
}
}
},
{
"term": {
"myList.elm1.keyword": {
"value": "value1"
}
}
}
]
}
}
}
}
}
I'm trying write a query to achieve the following result:
field1: value1 AND
field2: value2 OR "" (empty)
I've tried the following but it always returns me empty results:
{
"_source": ["field1", "field2"],
"query": {
"bool": {
"must": [
{"match": { "field1": "value1" }},
{
"bool": {
"should": [
{
"match": {
"field2": "value2"
}
}
],
"must_not": [
{
"exists": { "field": "field2" }
}
]
}
}
]
}
}
}
I believe I'm making a query that contradicts itself.
This is looking very complicated.
Try using queryStringQuery
Try rewriting your query like this
{
"_source": ["field1", "field2"],
"query": {
"query_string": {
"query": "field1:value1 AND (field2:value2 OR (!field2:*))"
}
}
}
If you still want to use in this format
You have used must_not clause which would mean somewhat this as below according to your use case.
field1: value1 AND
field2: value2 AND NOT "" (empty)
What you should do is
{
"_source": [
"field1",
"field2"
],
"query": {
"bool": {
"must": [
{
"match": {
"field1": "value1"
}
},
{
"bool": {
"should": [
{
"match": {
"field2": "value2"
}
},
{
"bool": {
"must_not": [
{
"exists": {
"field": "field2"
}
}
]
}
}
]
}
}
]
}
}
}
But it would be more easy for you to use queryString if you want to analyze the terms in query first which you have done in your query.
So using queryString OR bool in your this case would be same
I want to create the equivalent of the following query -
(city = 'New York' AND state = 'NY') AND ((businessName='Java' and businessName='Shop') OR (category='Java' and category = 'Shop'))
I tried different combinations of bool queries using must and should but nothing seems to be working. Can this be done?
How about something like this:
{
"query": {
"match_all": {}
},
"filter": {
"bool": {
"must": [
{
"term": {
"city": "New york"
}
},
{
"term": {
"state": "NY"
}
},
{
"bool": {
"should": [
{
"bool": {
"must": [
{
"term": {
"businessName": "Java"
}
},
{
"term": {
"businessName": "Shop"
}
}
]
}
},
{
"bool": {
"must": [
{
"term": {
"category": "Java"
}
},
{
"term": {
"category": "Shop"
}
}
]
}
}
]
}
}
]
}
}
}
I'm running Elasticsearch 1.5.2 and trying the following query:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": 1,
"boost": 2
}
}
]
}
}
}
}
}
Everything is fine until I add the "boost": 2 to the should -> term part. The complete query is much more complex, that's why I need to boost, but the remaining queries don't make any difference: ES returns an error 400 if a term query gets a boost argument:
QueryParsingException[[index_name] [_na] query malformed, must start with start_object]
Any suggestions?
It should be like this:
{
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"gender": "male"
}
}
]
}
},
"query": {
"bool": {
"must": [
{
"match_all": {}
}
],
"should": [
{
"term": {
"top_users": {
"value": "1",
"boost": 2
}
}
}
]
}
}
}
}
}