Query documents that contains all values in nested array Elasticsearch - elasticsearch

I'm trying to query documents where the nested array contains all of the elements passed in the query.
The index stores groups and each group has a list of members. I want to query all the groups that contains the given members.
Mapping:
"properties" : {
"members" : {
"type" : "nested",
"properties" : {
"name" : {
"type" : "keyword"
}
}
},
"name" : {
"type" : "text"
}
}
}
}
Example content:
[
{
"name" : "group 1",
"members" : [
{
"name" : "alice"
},
{
"name" : "bob"
}
]
},
{
"name" : "group 2",
"members" : [
{
"name" : "alice"
},
{
"name" : "foo"
},
{
"name" : "bob"
}
]
},
{
"name" : "group 3",
"members" : [
{
"name" : "foo"
},
{
"name" : "bar"
}
]
}
]
How can I find all groups that have both "alice" and "foo" as members?
I have tried the following query but it returns nothing:
GET /group/_search
{
"query": {
"nested": {
"path": "members",
"query": {
"bool": {
"must": [
{"match": {"members.name": "alice"}},
{"match": {"members.name": "foo"}}
]
}
}
}
}
}
I have also tried with term instead of match but it gives no results.

You can use the nested within a must clause. Like this:
GET /group/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "members",
"query": {
"term": {
"members.name": {
"value": "alice"
}
}
}
}
},
{
"nested": {
"path": "members",
"query": {
"term": {
"members.name": {
"value": "foo"
}
}
}
}
}
]
}
}
}

Related

Elastic search source filtering query for nested JSON document

I have the below JSON object as _source in Elastic search. I need to filter the source object based on conditions. For example, I need only JSON with applied_as == "COMMISSION"
"_source": {
"factor" : [
{
"some_amount_usd" : [
{
"applied_as" : "TCKT_CNT",
"version" : "8",
"factor_value" : "1.12",
"start_date" : "2022-01-01"
},
{
"applied_as" : "TCKT_CNT",
"version" : "8",
"factor_value" : "1.12",
"start_date" : "2022-02-01"
},
{
"applied_as" : "COMMISSION",
"version" : "8",
"factor_value" : "1.12",
"start_date" : "2022-02-01"
},
]
}
]
}
I am using this documentation.
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-fields.html#source-filtering
I am currently using this query with no luck. What am I missing?
GET form_some_index/_search
{
"query": {
"match": {
"factor.some_amount_usd.applied_as": "COMMISSION"
}
}
}
You can start using Nested Query.
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "factor",
"query": {
"nested": {
"path": "factor.some_amount_usd",
"query": {
"bool": {
"must_not": [
{
"term": {
"factor.some_amount_usd.applied_as.keyword": {
"value": "COMMISSION"
}
}
}
]
}
}
}
}
}
}
]
}
}
}

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
}

Nested Elasticsearch queries

I'm trying to create a nested query which would filter out some documents with specific terms. In this case I'm trying to filter out documents which have matching terms in user.first. Data example:
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Tim",
"last" : "White"
}
]
},
{
"group" : "fans",
"user" : [
{
"first" : "Jim",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "Black"
}
]
}
My query doesn't get the desired result as it returns me all records which are not filtered. I tried querying using:
"query": {
"bool": {
"must_not": [
{
"nested": {
"query": {
"terms": {
"user.first": [
"John",
"Thomas"
]
}
},
"path": "user"
}
}
]
}
}
I expect here to get documents which don't match with the filter. In this case it should return only the second document. What is the right way to do this?
After a lot of trial and error I've managed to find a solution for the problem. This is the query that filters out documents we don't need.
"query": {
"bool": {
"must_not": [
{
"bool": {
"filter": [
{
"nested": {
"query": {
"terms": {
"user.first": [
"John",
"Thomas"
]
}
},
"path": "user"
}
}
]
}
}
]
}
}

Elasticsearch - OR in term conditions

I need little help with transfering mysql query to ES. The query looks like this
SELECT * FROM `xyz` WHERE visibility IN (1,2) AND (active=0 OR (active=1 AND finished=1)
It's easy, to make only AND conditions, but how to mix AND with OR in term?
"query" : {
"bool" : {
"must" : [{
"terms" : { "visibility" : ["1", "2"] }
}, {
"term" : { "active" : "1" }
}, {
"term" : { "active" : "0", "finished" : "1" } // OR
},]
}
}
Try like this by nesting a bool/should and bool/filter query inside the main bool/filter query:
{
"query": {
"bool": {
"filter": [
{
"terms": {
"visibility": [
"1",
"2"
]
}
},
{
"bool": {
"should": [
{
"term": {
"active": "0"
}
},
{
"bool": {
"filter": [
{
"term": {
"active": "1"
}
},
{
"term": {
"finished": "1"
}
}
]
}
}
]
}
}
]
}
}
}

elasticsearch searching array field inside nested type

i am trying to filter my result using nested filter but i am getting incorrect result
here is my mapping info
{
"stock" : {
"mappings" : {
"clip" : {
"properties" : {
"description" : {
"type" : "string"
},
"keywords" : {
"type" : "nested",
"properties" : {
"category" : {
"type" : "string"
},
"tags" : {
"type" : "string",
"index_name" : "tag"
}
}
},
"tags" : {
"type" : "string",
"index_name" : "tag"
},
"title" : {
"type" : "string"
}
}
}
}
}
}
clip document data
{
"_index" : "stock",
"_type" : "clip",
"_id" : "AUnsTOBBpafrKleQN284",
"_score" : 1.0,
"_source":{
"title": "journey to forest",
"description": "this clip contain information about the animals",
"tags": ["birls", "wild", "animals", "roar", "forest"],
"keywords": [
{
"tags": ["spring","summer","autumn"],
"category": "Weather"
},
{
"tags": ["Cloudy","Stormy"],
"category": "Season"
},
{
"tags": ["Exterior","Interior"],
"category": "Setting"
}
]
}
i am trying to filter tags inside nested field 'keywords'
here is my query
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "keywords",
"filter": {
"bool": {
"must": [
{
"terms": { "tags": ["autumn", "summer"] }
}
]
}
}
}
}
}
}
}
i am getting no result why ?
what's wrong with my query or schema please help
The above query is syntactically incorrect . You need to provide the full path to tags from root keywords in the term query i.e.keywords.tags
{
"query": {
"filtered": {
"query": {
"match_all": {}
},
"filter": {
"nested": {
"path": "keywords",
"filter": {
"bool": {
"must": [
{
"terms": { "keywords.tags": ["autumn", "summer"] }
}
]
}
}
}
}
}
}
}

Resources