Elasticsearch: querying documents by nested Array properties - elasticsearch

I have something like this as the document:
{ name : "name1",
age : 30,
address :[{street : "st1" , no : 10},
{street : "st2", no : 20},
{street : "st3", no : 20}]
}
{ name : "name2",
age : 31,
address :[{street : "st2" , no : 10},
{street : "st3", no : 20},
{street : "st10", no : 20}]
}
I want to issue a query to find the records, in their address array both "st1"
AND "st2" are present. This query should return the first document in the above example.
Find all documents that have address in both "st1" AND "st2". I wrote this query which returns nothing.
{
"query": {
"nested": {
"path": "address",
"query": {
"bool": {
"must": [
{
"term": {
"address.street": "st1"
}
},
{
"term": {
"address.street": "st2"
}
}
]
}
}
}
}
}
How can I write this query?

I could find a way to write a query for mentioned problem with the help of my colleague. It may not the optimal solution but it works.
{
"query": {
"bool": {
"must": [
{
"query": {
"nested": {
"path": "address",
"query": {
"term": {
"address.street": "st1"
}
}
}
}
},
{
"query": {
"nested": {
"path": "address",
"query": {
"term": {
"address.street": "st2"
}
}
}
}
}
]
}
}
}
If you know the more optimal solution, please share it.

Related

AND query nested objects

Full disclaimer: elasticsearch noob here.
I'm using the nested field value_per_id for an array of objects. Each object has the properties: value and id.
E.g.
"value_per_id": [
{
"id": 2,
"value": "positive"
},
{
"id": 23,
"value": "positive"
},
{
"id": 65,
"value": "neutral"
}
]
I have a query that looks like this (edited for clarity):
{
"query" : {
"bool" : {
"filter" : [
{
"bool" : {
"must" : {
"nested" : {
"path" : "value_per_id",
"query" : [
{"terms" : {"value_per_id.value" : <MY_VALUES>}},
{"terms" : {"value_per_id.id" : <MY_IDS>}},
]
}
}
}
}
]
}
}
}
With this query, I get all the elements that have an object with value in MY_VALUES OR id in MY_IDS.
I want all the elements that have value in MY_VALUES for any id in MY_IDS.
(E.g. if MY_VAULES = ['positive', 'neutral'] and MY_IDS = [1, 2], I want those that have an object with 1 - positive, 1 - negative, 2 - positive or 2 - negative).
What's the syntax for this?
EDIT - Wrong format
You need to use the bool within the nested query like this:
{
"query": {
"bool": {
"filter": [{
"nested": {
"path": "value_per_id",
"query": {
"bool": {
"must": [
{"term": {"value_per_id.value": 1}},
{"term": {"value_per_id.id": 2}}
]
}
}
}
}]
}
}
}
Use must or filter in the bool query.
If you use must, the sub queries will contribute to the score, if you use filter they won't. Also, if you use filter elasticsearch will be able to cache the results.
{
"bool": {
"must": [
{
"nested": {
"path": "value_per_id",
"query": {
"terms": {
"value_per_id.value": <MY_VALUES>
}
}
}
},
{
"nested": {
"path": "value_per_id",
"query": {
"terms": {
"value_per_id.id": <MY_IDS>
}
}
}
}
]
}
}

In Elasticsearch, how do I search string on multiple fields from multi-level nested objects

In Elasticsearch 6, I have data with nested objects like this:
{
"brands" :
[
{
"brand_name" : "xyz",
"products" :
[
{
"title" : "test",
"mrp" : 100,
"sp" : 90,
"status" : 1
},
{
"title" : "test1",
"mrp" : 50,
"sp" : 45,
"status" : 1
}
]
},
{
"brand_name" : "aaa",
"products" :
[
{
"title" : "xyz",
"mrp" : 100,
"sp" : 90,
"status" : 1
},
{
"title" : "abc",
"mrp" : 50,
"sp" : 45,
"status" : 1
}
]
}
]
}
I want to search from either from the field brand_name or from the field title. And I want return all results in same inner_hits.
For example : If I input the search string as "xyz" it should return both brands object with correspondent product object.
If I input the search string as "test" it should return only first brand array with only first product object.
How can I achieve this. Any ideas?
I have tried with the nested path query like this:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "brands",
"query": {
"bool": {
"should": [
{
"term": {
"brands.brand_name": "xyz"
}
},
{
"term": {
"brands.brand_name.keyword": "aaa"
}
},
{
"nested": {
"path": "brands.products",
"query": {
"bool": {
"should": [
{
"match": {
"brands.products.title": "xyz"
}
}
]
}
},
"inner_hits": {}
}
}
]
}
},
"inner_hits": {}
}
}
]
}
}
}
But this query returning with multiple inner_hits response with multiple array objects for each brands and for each products.
I want the response like all brand names which is matching with the string should list under one array and all the products should list under another array under same inner_hits.
Since you want the inner hits to be different based on where the match has happened i.e. brands.brand_name or brands.products.title, you can have two queries one for brand name and other for product title as independent nested queries. These queries then should be inside should clause of a bool query. Each of the nested query should have its own inner_hits as below:
{
"query": {
"bool": {
"should": [
{
"nested": {
"path": "brands",
"inner_hits": {},
"query": {
"term": {
"brands.brand_name.keyword": "test"
}
}
}
},
{
"nested": {
"path": "brands.products",
"inner_hits": {},
"query": {
"term": {
"brands.products.title": "test"
}
}
}
}
]
}
},
"_source": false
}

Elasticsearch Nested object Search with AND Condition

Here is my data in Elasticsearch - I kept Tags as nested object
PUT myblog/3
{
"id" : 10003,
"tags" : [
{
"tag" : 45647
},
{
"tag" : 45648
}
]
}
PUT myblog/4
{
"id" : 10004,
"tags" : [
{
"tag" : 45647
}
]
}
PUT myblog/5
{
"id" : 10005,
"tags" : [
{
"tag" : 45648
}
]
}
I want to retrieve documents with tag is 45647 & 45648. I tried it in this way
GET myblog/_search
{
"query": {
"nested": {
"path": "tags",
"query": {
"bool": {
"must": [
{ "match": { "tags.tag": 45648}},
{ "match": { "tags.tag": 45647}}
]
}
}
}
}
}
But it is not returning the expected result. What is missing in my query to get expected result?
You're almost there. You need two nested clauses since each nested element is a different document underneath. Try like this:
GET myblog/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "tags",
"query": {
"match": {
"tags.tag": 45648
}
}
}
},
{
"nested": {
"path": "tags",
"query": {
"match": {
"tags.tag": 45647
}
}
}
}
]
}
}
}

elasticsearch query nested array of objects

Hi I am trying to get a query to filter based on values in an array of objects, the structure is like this
{
"_index": "test",
"_type": "home",
"_id": "1247816",
"_score": 1,
"_source": {
"TranCust": {
"CustId": 1247816,
"sourceNodeName": "SRC"
},
"TranList": [
{
"TranId": 2431015,
"batchNr": "211"
},
{
"TranId": 2431016,
"batchNr": "213"
}
]
}
}
as an example, i would like to find all documents with a TranId of 2431015, my query looks like this
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "TranList",
"query": {
"bool": {
"must": [
{
"match": {
"TranId": "2431015"
}
}
]
}
}
}
}
]
}
}
}
it seems to return no results, is there a better way to try and write this query ?
EDIT,
here are the mappings put in
{
"mappings": {
"home": {
"properties": {
"TranCust": {
"type": "object"
}
},
"TranList": {
"type": "nested"
}
}
}
}
}
ok, so after lots of attempts this is how i got it to work
{
"query": {
"bool": {
"must": [{
"nested": {
"path": "TranList",
"query": {
"bool": {
"must": [{
"match": {
"TranList.TranId": "2431015"
}
}]
}
}
}
}]
}
}
}
Not sure what was your ES version, but the following should ideally work for ES 6.x+ versions. You don't actually need to wrap your nested query with bool:must
{
"query": {
"nested" : {
"path" : "TranList",
"query" : {
"bool" : {
"must" : [
{ "match" : {"TranList.TranId" : "2431015"} }
]
}
}
}
}
}
{
"query": {
"query_string": {
"default_field": "TranList.TranId",
"query": "2431015"
}
}
}

ElasticSearch sort by field

i have this query:
GET /_search
{
"from" : 0, "size" : 30,
"query": {
"filtered": {
"query" : {
"query_string": {
"query": "((categoria.id:1752) AND (cidadeId:7300))
OR ((categoria.id:1752) and (estadoId:13)) "
}
}
}
},
"sort": [
{ "img": { "order": "desc" } }
]
}
I would like to order by cidadeId = 7300 and then the other but do not know how to do this in the sort
I have considered a small example :
PUT test/test/1
{
"categoria.id":1752,
"cidadeId":7300
}
PUT test/test/2
{
"categoria.id":1752,
"estadoId":13
}
PUT test/test/3
{
"categoria.id":175,
"cidadeId":1
"estadoId":13
}
With the few information you are giving in your answer, I can give you the following solution for ascendant sorting on cidadeId
GET test/_search
{
"from": 0,
"size": 30,
"query": {
"filtered": {
"query": {
"query_string": {
"query": "((categoria.id:1752) AND (cidadeId:7300)) OR ((categoria.id:1752) and (estadoId:13))"
}
}
}
},
"sort": [
{
"cidadeId": {
"order": "asc"
}
}
]
}
I hope this will help

Resources