AND query nested objects - elasticsearch

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

Related

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: querying documents by nested Array properties

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.

Elasticsearch 5.2 nested query for multi terms

nested document look like this
{
"userid": "123",
"usertag": [
{
"tag": "A",
"logcreatetime": "2017-01-14"
},
{
"tag": "C",
"logcreatetime": "2017-01-17"
}
]
},
{
"userid": "456",
"usertag": [
{
"tag": "A",
"logcreatetime": "2017-01-12"
},
{
"tag": "B",
"logcreatetime": "2017-01-19"
}
]
},
.....
usertag object is nested mapping,
how to get user id by 2017-01-12 to 2017-01-19 , has tag A and B?
thanks
sorry for my english.
I'm assuming you've indexed your logcreatetime as Date field, so you can use the following query:
curl -XGET http://localhost:9200/my_users/_search -d '
{
"query": {
"bool": {
"must": [ {
"nested": {
"path": "usertag",
"query": {
"bool": {
"must": [
{ "match": { "usertag.tag": "A" }},
{ "range" : {
"usertag.logcreatetime" : {
"gte": "2017-01-12",
"lte": "2017-01-19"
}
}}
]
}
}
}
}, {
"nested": {
"path": "usertag",
"query": {
"bool": {
"must": [
{ "match": { "usertag.tag": "B" }},
{ "range" : {
"usertag.logcreatetime" : {
"gte": "2017-01-12",
"lte": "2017-01-19"
}
}}
]
}
}
}
}]
}
}
}'
The limitation of syntax is that you can look for particular child which both has particular tag AND its logcreatetime lies within given range. But in order to ensure you'll have two children you should combine two nested queries into 2 must clauses of top-level bool.

Disable hits and use exclusively inner_hits

>Beginner here.
I have made a architecture for my profile - photo's application. In this application user can search for member by member's attributes and photo's attributes. And returned is only the photo's that have matched the query.
The problem is that one user might have thousands of photo's and each time a search is ran it return's hits: full object's of the profiles( with the nested photos ).
How can i make elasticsearch return only the value's of inner_hits?
Here is my query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "photo",
"query": {
"bool": {
"must": [
{
"match": {
"photo.make": "BMW"
}
},
{
"match": {
"photo.model": "111"
}
}
]
}
},
"inner_hits" : {"size": 1}
}
}
]
}}}
Duplicate of: Elasticsearch: Return only nested inner_hits
Quoting:
Should be able to achieve it by disabling source-field at top-level by specifying "_source" : false
POST /networkcollection/branch_routers/_search/
{
"_source" : false,
"query": {
"nested": {
"path": "queries",
"query": {
"bool": {
"must": [
{ "match":
{ "queries.dateQuery": "20160101T200000.000Z" }
}
]
}
},
"inner_hits" : {}
}
}
}

Elastic Search Nested Object mapping and Query for search

I am trying to use Elastic Search and I am stuck trying to query for the nested object.
Basically my object is of the following format
{
"name" : "Some Name",
"field2": [
{
"prop1": "val1",
"prop2": "val2"
},
{
"prop1": "val3",
"prop2":: "val4"
}
]
}
Mapping I used for the nested field is the following.
PUT /someval/posts/_mapping
{
"posts": {
"properties": {
"field2": {
"type": "nested"
}
}
}
}
Say now i insert elements for /field/posts/1 and /field/posts/2 etc. I have k values for field2.prop1 and i want a query which gets the posts sorted based on most match of field2.prop1 among the K values i have. What would be the appropriate query for that.
Also I tried a simple filter but even that doesnt seem to work right.
GET /someval/posts/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
}
},
"filter" : {
"nested" : {
"path" : "field2",
"filter" : {
"bool" : {
"must" : [
{
"term" : {"field2.prop1" : "val1"}
}
]
}
},
"_cache" : true
}
}
}
}
The above query should match atleast the first post. But it returns no match. Can anyone help to clarify whats wrong here ?
There was problem in your json structure, you used filtered query , but filter(object) was in different level than query.
Find the difference.
POST /someval/posts/_search
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "field2",
"filter": {
"bool": {
"must": [
{
"term": {
"field2.prop1": "val1"
}
}
]
}
},
"_cache": true
}
}
}
}
}

Resources