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
Related
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"
}
}
]
}
}
]
}
}
}
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 have elasticsearch 6.8.8, just for an example of my question. I want to create a query that gets me document with "Test" field with value "1", and i don't want to get "Test" field with value of "3", i know that i could write just the first expression without 3 and it will give me one document with value of "1". But i want to know, is there any way, that i can use must and must_not in the same time, on the same field and getting just the value of "1"?
I wrote this basic example to know what i mean:
{
"from": 0,
"query": {
"nested": {
"path": "attributes",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "1"
}
}
}
],
"must_not": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "3"
}
}
}
]
}
}
]
}
}
}
}
}
I use attributes as nested field with key-value field that use mapping as string type.
You'll need to leave out attributes.key:Test in the must_not because it filters out all Tests:
GET combine_flat/_search
{
"from": 0,
"query": {
"nested": {
"inner_hits": {},
"path": "attributes",
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"attributes.key": {
"query": "Test"
}
}
},
{
"match": {
"attributes.value": {
"query": "1"
}
}
}
],
"must_not": [
{
"match": {
"attributes.value": {
"query": "3"
}
}
}
]
}
}
]
}
}
}
}
}
Tip: use inner_hits to just return the matched nested key-value pairs as opposed to the whole field.
I want to find a document with a name that contains 'Bob' and has a location that is in either 'paducah' or 'smyrna'.
Here's what I have now:
query: {
bool: {
must: [
{ match: { name: 'bob' } },
{ match: { location: ['paducah', 'smyrna'] } }
],
},
},
I know the problem is in the location array, because if i change it to a single element with no array the query works just fine.
This is the closest answer i could find.
It didn't work, i receive the following error:
[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]
You could try this query:
{
"query": {
"bool": {
"must": [
{ "match": { "name": "bob" } }
],
"should": [
{ "match": { "location": "paducah" }},
{ "match": { "location": "smyrna" }}
],
"minimum_should_match": 1
}
}
}
What about the following:
{
"query": {
"bool": {
"must": [
{ "term": { "name": "bob" },
"bool": {
"should": [
{"term": {"location": "paducah"}},
{"term": {"location": "smyrna"}}
]
}
}
]
}
}
}
I have a simple JSON query for Elasticsearch that looks like this:
"query": {
"bool": {
"must": { "match": { "id": "1" }} ,
"must": { "match": { "tags.name": "a1"}}
}
}
How can I execute the second 'must' criteria ONLY if the value ('a1' in this case) is not empty?
You can achieve it using the following -
{
"query": {
"bool": {
"must": [
{
"match": {
"id": "1"
}
},
{
"bool": {
"should": [
{
"missing": {
"field": "tags.name"
}
},
{
"match": {
"tags.name": "a1"
}
}
]
}
}
]
}
}
}
I don't think "missing" can be used in the latest versions of elasticsearch.
But one can use Conditional Clauses instead.
https://www.elastic.co/guide/en/elasticsearch/reference/6.3/search-template.html#_conditional_clauses