Nested query to find child containing term X and child's parent contains term Y - elasticsearch

I have a mapping like this
{
"properties" : {
"text" : {
"type" : "nested",
"properties": {
"header": {
"type" : "text"
},
"nodes": {
"type": "nested",
"properties": {
"subheader" : {
"type" : "text"
},
"nodes" : {
"type" : "nested"
}
}
}
}
}
}
}
I'll like to return the documents where the innermost child text.nodes.nodes contains some term 'X' if and only if that child's parent text.nodes.subheader contains some term 'Y'
Here's a reproducible gist, where I expect that a search for 'SUPERFRAGILISTIC' in the child, and 'Restrictions' in the subheader should return only document 2.
It is now returning both documents.
From the gist, my query right now looks like:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "text.nodes",
"query": {
"bool": {
"must": [
{
"match": {
"text.nodes.subheader": {
"query": "Restrictions"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "text.nodes.nodes",
"query": {
"bool": {
"must": [
{
"match": {
"text.nodes.nodes.content": {
"query": "SUPERFRAGILISTIC"
}
}
}
]
}
}
}
}
]
}
}
}

In order to find a result with two conditions that are contained in the same json node of a single document, you need to nest the second condition in the first one. With this query you'll get only document2:
{
"query":{
"bool":{
"must":[
{
"nested":{
"path":"text.nodes",
"query":{
"bool":{
"must":[
{
"match":{
"text.nodes.subheader":{
"query":"Restrictions"
}
}
},
{
"nested":{
"path":"text.nodes.nodes",
"query":{
"bool":{
"must":[
{
"match":{
"text.nodes.nodes.content":{
"query":"SUPERFRAGILISTIC"
}
}
}
]
}
}
}
}
]
}
}
}
}
]
}
}
}

Related

ElasticSearch adjacent words for nested queries

I'm using ES 7.14/Kibana 7.10, I have to search for adjacent words (any order), hence I'm using this query:
{
"query":{
"bool":{
"must":[
{
"query_string":{
"query":"*antonio* *banderas*",
"fields":[
"text"
],
"default_operator":"and",
}
}]
}
}
}
This works ok for a text plain field. Now, I have a nested field metadata, let's say the mapping is
{
"mappings:": {
"properties": {
"text": {
"type": "text"
},
"metadata": {
"type": "nested",
"properties": {
"text": {
"type": "text"
}
}
}
}
}
}
and I would like to search that nested field in the same way (adjacent words search), so assumed that it's is possibile to write a nested query for query_string in this way
{
"query": {
"query_string": {
"query": "metadata.text:*antonio* *banderas*"
}
}
}
How to adapt this approach to the previous one with default_operator=and etc.? If I do
{
"query": {
"query_string": {
"query": "metadata.text:*antonio* *banderas*",
"default_operator": "and"
}
}
}
I don't get any result (but any error too).
A similar question, but related to matching adjacent words for multiple nested fields is here.
Adjacent word with any order should not be search with query_string but wildcard or match or term or span_term
There is also a mapping type wildcard optimised for this usage, depends on what type of queries you will need.
So for you first example :
{
"query": {
"bool": {
"must": [
{
"wildcard": {
"text": "*antonio*"
}
},
{
"wildcard": {
"text": "*banderas*"
}
}
]
}
}
}
OR
{
"query": {
"bool": {
"must": [
{
"wildcard": {
"text": "*antonio*banderas*"
}
}
]
}
}
}
and for nested queries :
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "metadata",
"query": {
"bool": {
"must": [
{
"wildcard": {
"metadata.text": "*antonio*"
}
},
{
"wildcard": {
"metadata.text": "*banderas*"
}
}
]
}
}
}
}
]
}
}
}

nested boolean with match query in elasticsearch

I would like to match within a boolean query in Elasticsearch. I have the match query and boolean query working as expected now, but I am not sure how to have a AND to combine them.
nested boolean
{
"query": {
"constant_score" : {
"filter":{
"bool":{
"must":[
{"terms":{"address.keyword": addr}},
{"bool":{
"should":[
{"terms": {"state.keyword": state}}
,{"terms": {"city.keyword": city}}
]
}}
]
}
}
}}}
match
{"query": {
"match": {
"auct_title": {
"query": keyword,
"operator": "and"
}
}
}
, "collapse" : {
"field" : "id"
}
,"sort" : [
{ sort_field: {"order" : sort_order} }]
,"size":20
}
You can move natch to the must clause . So document has to satisfy three conditions
1.address
2.either of state/city
2.match on auct_title
It will then return one document per Id based on sort order passed
GET <index>/_search
{
"query": {
"constant_score": {
"filter": {
"bool": {
"must": [
{
"term": {
"address.keyword": "addr"
}
},
{
"bool": {
"should": [
{
"term": {
"state.keyword": "state"
}
},
{
"term": {
"city.keyword": "city"
}
}
]
}
},
{
"match": {
"auct_title": {
"query": "keyword",
"operator": "and"
}
}
}
]
}
}
}
},
"collapse": {
"field": "id"
},
"sort": [
{
"FIELD": {
"order": "desc"
}
}
],
"size": 20
}

Filter nested sorting in elasticsearch

I have a document with a nested structure the nested object has an assignment_name and a due_date:
The mapping
{
"goal": {
"mappings": {
"doc": {
"properties": {
"title": {
"type": "keyword"
},
// lot's of other fields here ...
"steps": {
"type": "nested",
"properties": {
"assignment_name": {
"type": "keyword"
},
"due_date": {
"type": "date"
}
// lots of other fields here
}
}
}
}
}
}
}
I want to:
Filter all document that have a specific assignment_name (e.g.user_a)
Sort the result by the next due_date, not taking other assignements into account.
This query gives me random result (no sortings):
{
"query":{
"bool":{
"filter":[
{
"nested":{
"path":"steps",
"query":{
"term":{
"steps.assignment_name":"user_a"
}
}
}
}
]
}
},
"sort":[
{
"steps.due_date":{
"order":"asc",
"nested":{
"path":"steps",
"filter":{
"term":{
"steps.assignment_name":"user_a"
}
}
}
}
}
],
"from":0,
"size":25
}
Firstly you need to ensure that datatype for steps field is nested. Then you have to use nested sorting to sort documents based on a nested document field.
The query would be:
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "steps",
"query": {
"term": {
"steps.assignment_name": "user_a"
}
}
}
}
]
}
},
"sort": [
{
"steps.due_date": {
"order": "asc",
"nested": {
"path": "steps",
"filter": {
"term": {
"steps.assignment_name": "user_a"
}
}
}
}
}
]
}
The catch above is to use the same filter in sort as used in the main query to filter the documents. This ensures that the correct nested document's field value is considered to sort the documents.

elasticsearch nested query, more than one one object should meet conditions

I have some questions about nested query.
Here is my example. The mapping is {"user":"nested"}.The exist data just like this:
{
"user": [
{
"first":"John",
"last":"Smith"
},
{
"first":"Alice",
"last":"White"
}
]
}
How do I create a query to find this document that meets all the conditions:
the first object of user that its "first" is "John" and "last" is "Smith";
the second object of user that its "first" is "Alice" and "last" is "White"
Try with below query :
{
"query":{
"bool":{
"filter":[
{
"bool":{
"must":[
{
"bool":{
"must":[
{
"nested":{
"query":{
"bool":{
"must":[
{
"match_phrase":{
"user.first":{
"query":"John"
}
}
},
{
"match_phrase":{
"user.last":{
"query":"Smith"
}
}
}
]
}
},
"path":"user"
}
},
{
"nested":{
"query":{
"bool":{
"must":[
{
"match_phrase":{
"user.first":{
"query":"Alice"
}
}
},
{
"match_phrase":{
"user.last":{
"query":"White"
}
}
}
]
}
},
"path":"user"
}
}
]
}
}
]
}
}
]
}
}
}
Below query is what you are looking for. You simply need to have two nested queries, one for each conditions you've mentioned, combined in a bool using must clause.
Note that I'm assuming that the fields user.first and user.last are of text type having standard analyzer
POST <your_index_name>
{
"query":{
"bool":{
"must":[
{
"nested":{
"path":"user",
"query":{
"bool":{
"must":[
{
"match":{
"user.first":"john"
}
},
{
"match":{
"user.last":"smith"
}
}
]
}
}
}
},
{
"nested":{
"path":"user",
"query":{
"bool":{
"must":[
{
"match":{
"user.first":"alice"
}
},
{
"match":{
"user.last":"white"
}
}
]
}
}
}
}
]
}
}
}
Hope this helps!
The answer is:
{
"query": {
"bool": {
"must": [
{
"has_parent": {
"parent_type": "doc",
"query": {
"bool": {
"must": [
{
"terms": {
"id": [
713
]
}
},
{
"range": {
"created": {
"lte": "now/d"
}
}
},
{
"range": {
"expires": {
"gte": "now/d"
}
}
}
]
}
}
}
},
{
"nested": {
"path": "prices",
"query": {
"bool": {
"filter": [
{
"term": {
"prices.id_prcknd": 167
}
}
]
}
}
}
},
{
"term": {
"doc_type": "item"
}
},
{
"bool": {
"should": [
{
"term": {
"have_prices": true
}
},
{
"term": {
"is_folder": true
}
}
]
}
}
],
"must_not": {
"exists": {
"field": "folder"
}
}
}
},
"sort": [
{
"is_folder": {
"order": "desc"
}
},
{
"title_low.order": {
"order": "asc"
}
}
],
"size": 1000
}

Combining Multiple Queries with 'OR' or 'AND' in Elasticsearch

I have two distinct query, and I want to combine them with an 'OR'/'AND' in between. How do I do that?
For example, for the given queries
I just want to run Query1 OR Query2 in the elasticsearch.
Query1:
{
"query": {
"filtered": {
"query": {
"query_string":{
"query":"Batman",
"default_operator":"AND",
"fields"::[
"Movies._all"
]
}
},
"filter": {
"bool": {
"must": [
{
"query":{
"filtered":{
"filter":{
"and":[
{
"term":{
"cast.firstName":"Christian "
}
},
{
"term":{
"cast.lastName":"Bale"
}
}
]
}
}
}
}
]
}
}
}
}
}
Query2:
{
"query": {
"filtered": {
"query": {
"query_string":{
"query":"Dark Knight",
"default_operator":"AND",
"fields"::[
"Movies._all"
]
}
},
"filter": {
"bool": {
"must": [
{
"query":{
"filtered":{
"filter":{
"and":[
{
"term":{
"director.firstName":"Christopher"
}
},
{
"term":{
"director.lastName":"Nolan"
}
}
]
}
}
}
}
]
}
}
}
}
}
You need to use a bool query
Something like below will work fine -
{
"query" : {
"bool" : {
"must" : [
{ // Query1 },
{ // Query2}
]
}
}
}
Use must for AND and should for OR

Resources