Disable hits and use exclusively inner_hits - elasticsearch

>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" : {}
}
}
}

Related

Elasticsearch conditional query for nested array

Using the following document, I'm trying to perform an Elasticsearch keyword query, conditionally excluding field data from the scope of the search. Is this possible?
{
"Name":"doc1",
"UserData":[
{
"EnteredBy":"Eric",
"Description":"Desc entered by Eric, abc"
},
{
"EnteredBy":"Alex",
"Description":"Desc entered by Alex, def"
}
]
}
The Elasticsearch query I need will allow me to search across the whole document, except it should exclude from the search UserData items where EnteredBy does not match the specified user.
The following queries would return results:
User:Eric doc1
User:Eric abc
User:Alex doc1
User:Fred doc1
The following queries would not return results:
User:Eric def
User:Fred def
Everything I've tried thus far, ends up filtering content based on the presence of UserData nodes which apply to the specified user. I can't think of a way to specify that a field should be searched, only if the EnteredBy field matches.
I could restructure the document, if that would solve the problem.
Edit 1
The index..
PUT index1
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0
},
"mappings": {
"properties" : {
"UserData" : {
"type":"nested"
},
"Name": {
"type":"text"
}
}
}
}
Edit 2
The query below is providing the results that I need, except for the child entity, I have to search in a specific field. If I change the second condition of the nested search into a query_string search, then it no longer uses the EnteredBy condition.
GET index1/_search
{
"query": {
"bool": {
"should": [
{
"nested":
{
"path": "UserData",
"query": {
"bool": {
"must": [{
"match": {
"UserData.EnteredBy": "Eric"
}},
{
"match": {
"UserData.Description": "def"
}
}]
}
}
}
},
{
"query_string":
{
"query": "doc1x"
}
}
]
}
}
}
This query appears to be working. I think I answered my own question.
GET index1/_search
{
"query": {
"bool": {
"should": [
{
"nested":
{
"path": "UserData",
"query": {
"bool": {
"must": [{
"match": {
"UserData.EnteredBy": "Eric"
}},
{
"query_string": {
"query": "def"
}
}]
}
}
}
},
{
"query_string":
{
"query": "doc1"
}
}
]
}
}
}

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

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: Return only nested inner_hits

I have the following query:
GET /networkcollection/branch_routers/_search/
{
"query": {
"nested": {
"path": "queries",
"query": {
"bool": {
"must": [
{ "match":
{ "queries.dateQuery": "20160101T200000.000Z" }
}
]
}
},
"inner_hits" : {}
}
}
}
This returns both the "hits" object (the entire document), as well as the "inner_hits" object (nested inside of hits).
Is there a way to for me to only return the matched "queries" element(s) which appear in the "inner_hits" results, without getting the whole document?
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" : {}
}
}
}

ElasticSearch How to AND a nested query

I am trying to figure out how to AND my Elastic Search query. I've tried a few different variations but I am always hitting a parser error.
What I have is a structure like this:
{
"title": "my title",
"details": [
{ "name": "one", "value": 100 },
{ "name": "two", "value": 21 }
]
}
I have defined details as a nested type in my mappings. What I'm trying to achieve is a query where it matches a part of the title and it matches various details by the detail's name and value.
I have the following query which gets me nearly there but I haven't been able to figure out how to AND the details. As an example I'd like to find anything that has:
detail of one with value less than or equal to 100
AND detail of two with value less than or equal to 25
The following query only allows me to search by one detail name/value:
"query" : {
"bool": {
"must": [
{ "match": {"title": {"query": titleQuery, "operator": "and" } } },
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{ "match": {"details.name" : "one"} },
{ "range": {"details.value" : { "lte": 100 } } }
]
}
}
} // nested
}
] // must
}
}
As a second question, would it be better to query the title and then move the nested part of the query into a filter?
You were so close! Just add another "nested" clause in your outer "must":
POST /test_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": {
"query": "title",
"operator": "and"
}
}
},
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{"match": {"details.name": "one" } },
{ "range": { "details.value": { "lte": 100 } } }
]
}
}
}
},
{
"nested": {
"path": "details",
"query": {
"bool": {
"must": [
{"match": {"details.name": "two" } },
{ "range": { "details.value": { "lte": 25 } } }
]
}
}
}
}
]
}
}
}
Here is some code I used to test it:
http://sense.qbox.io/gist/1fc30d49a810d22e85fa68d781114c2865a7c92e
EDIT: Oh, the answer to your second question is "yes", though if you're using 2.0 things have changed a little.

Resources