Elasticsearch has_child returning no results - elasticsearch

I'm trying to get all child of a parent document but not getting any result with has_child query,
{
"index": "index_x",
"include_type_name": true,
"body": {
"mappings": {
"agents": {
"properties": {
"id": {
"type": "keyword"
},
"listings": {
"type": "join",
"eager_global_ordinals": true,
"relations": {
"agent": "listing"
}
},
"name": {
"type": "object"
}
}
}
}
}
}
here's my query
{
"query": {
"bool": {
"must": [
{
"term": {
"_id": <id>
}
},
{
"has_child": {
"type": "listing",
"query": {
"match_all": {}
},
"inner_hits": {}
}
}
]
}
}
}
however, when I run this query I'm getting child results just fine
{
"query": {
"bool": {
"must": [
{
"parent_id": {
"type":"listing",
"id": <id>
}
}
]
}
}
}
Same with has_parent query, not getting any results.
I'm using Elasticsearch 7.7

Sounds like you want to use the has_parent query. Here is minimal example of how it can work on ESv7.7:
PUT /so
{
"mappings": {
"properties" : {
"my-join-field" : {
"type" : "join",
"relations": {
"parent": "child"
}
},
"tag" : {
"type" : "keyword"
}
}
}
}
POST /so/_doc/1
{
"my-join-field": "parent",
"tag": "Adult"
}
POST /so/_doc/2?routing=1
{
"my-join-field": {
"name": "child",
"parent": "1"
},
"tag": "Youth"
}
POST /so/_doc/3?routing=1
{
"my-join-field": {
"name": "child",
"parent": "1"
},
"tag": "Youth2"
}
GET /so/_search
{
"query": {
"has_parent": {
"parent_type": "parent",
"query": {
"match": {
"tag": "Adult"
}
}
}
}
}

Related

Elasticsearch nested query with aggregation using nested term doesn't return any bucket

I have an ES index with this mapping:
{
"_doc": {
"dynamic": "false",
"properties": {
"original": {
"properties":{
"id": {
"type": "keyword"
},
"purchaseStatus": {
"type": "keyword"
},
"marketCode": {
"type": "keyword"
},
"salesProfiles": {
"type": "nested",
"properties": {
"marketCode": {
"type": "keyword"
},
"purchaseStatus": {
"type": "keyword"
}
}
}
}
},
"recommended": {
"properties":{
"id": {
"type": "keyword"
},
"purchaseStatus": {
"type": "keyword"
},
"marketCode": {
"type": "keyword"
},
"salesProfiles": {
"type": "nested",
"properties": {
"marketCode": {
"type": "keyword"
},
"purchaseStatus": {
"type": "keyword"
}
}
}
}
},
"distance": {
"type": "double"
},
"rank": {
"type": "double"
},
"source": {
"properties": {
"application": {
"type": "keyword"
},
"platform": {
"type": "keyword"
}
}
},
"timestamp": {
"properties": {
"createdAt": {
"type": "date"
},
"updatedAt": {
"type": "date"
}
}
}
}
},
"_default_": {
"dynamic": "false"
}
}
and I need to obtain the recommended docs with salesProfiles.marketCode equal to original.marketCode but my query doesn't return any buckets:
GET index/_search
{
"aggs": {
"similarities": {
"filter": {
"bool": {
"must": [
{
"term": {
"original.storefrontId": "12345"
}
},
{
"nested": {
"path": "recommended.salesProfiles",
"query": {
"bool": {
"must": [
{
"match": {
"recommended.salesProfiles.purchaseStatus": "PAID"
}
}
]
}
}
}
}
]
}
},
"aggs": {
"markets": {
"nested": {
"path": "recommended.salesProfiles"
},
"aggs": {
"recommendedMarket": {
"terms": {
"field": "recommended.salesProfiles.marketCode",
"size": 100
}
}
}
}
}
}
},
"explain": false
}
Any suggestion would be really appreciated. Thanks in advance!
Its hard to debug this without any example docs, but I think this might work
{
"size": 0,
"query": {
"bool": {
"must": [
{
"term": {
"original.storefrontId": "12345"
}
},
{
"nested": {
"path": "recommended.salesProfiles",
"query": {
"bool": {
"must": [
{
"match": {
"recommended.salesProfiles.purchaseStatus": "PAID"
}
}
]
}
}
}
}
]
}
},
"aggs": {
"Profiles": {
"nested": {
"path": "recommended.salesProfiles"
},
"aggs": {
"by_term": {
"terms": {
"field": "recommended.salesProfiles.marketCode",
"size": 100
}
}
}
}
}
}
I don't think you can use "nested" under the filter agg without being under a nested aggregation, so I believe that's why you didn't get any docs.
I basically moved all the filtering to the query and just aggregated the terms later

Elasticsearch nested doc with AND condition

The ES scheme we model a student document which contains multiple nested courses documents. I want to search for students who has course X and Y.
Mapping:
{
"index_classroom": {
"mappings": {
"content": {
"dynamic": "false",
"properties": {
"courses": {
"type": "nested",
"properties": {
"grade": {
"type": "integer"
},
"name": {
"type": "string",
"analyzer": "analyzer_keyword"
}
}
}
}
}
}
}
}
Sample docs:
{
"_index": "index_classroom",
"_type": "content",
"_id": "6170_130",
"_score": 0.72833073,
"_source": {
"courses": [
{
"name": "maths",
"grade": "A"
},
{
"name": "economics",
"grade": "A+"
}
]
}
}
I want to query all students who have taken Math and Economics (further to add is "and not Biology".)
Thanks!
This is your query:
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "courses",
"query": {
"match": {
"courses.name": "economics"
}
}
}
},
{
"nested": {
"path": "courses",
"query": {
"match": {
"courses.name": "maths"
}
}
}
}
],
"must_not": [
{
"nested": {
"path": "courses",
"query": {
"match": {
"courses.name": "Biology"
}
}
}
}
]
}
}
}

An Elasticsearch filter to determine the absence of a value

I have a document that has students and grades for each student. It looks something like this:
"name": "bill",
"year": 2015,
"grades": [
{"subject": "math", grade: "A"},
{"subject": "english", grade: "B"}
], ...
I'm looking for query filter(s) that can give me:
a list of students who have studied 'math', and
a list of students who have not studied 'math'.
I'm thinking that an exists filter should do it, but I'm struggling to get my head around it.
It's a stylised example but the mappings are something like this:
"mappings": {
"student": {
"properties": {
"name": {
"type": "string"
},
"grades": {
"type": "nested",
"properties": {
"subject": {
"type": "string"
},
"grade": {
"type": "string"
}
}
}
}
}
}
You need to change a bit your mapping and, depending on the your needs, I'd suggest aggregations.
First, your nested object needs to be "include_in_parent": true so that you can easily do the not studied 'math' part:
PUT /grades
{
"mappings": {
"student": {
"properties": {
"name": {
"type": "string"
},
"grades": {
"type": "nested",
"include_in_parent": true,
"properties": {
"subject": {
"type": "string"
},
"grade": {
"type": "string"
}
}
}
}
}
}
}
And the full query, using aggregations:
GET /grades/student/_search?search_type=count
{
"aggs": {
"studying_math": {
"filter": {
"nested": {
"path": "grades",
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"grades.subject": "math"
}
}
]
}
}
}
}
}
},
"aggs": {
"top_10": {
"top_hits": {
"size": 10
}
}
}
},
"not_studying_math": {
"filter": {
"bool": {
"must_not": [
{
"term": {
"grades.subject": "math"
}
}
]
}
},
"aggs": {
"top_10": {
"top_hits": {
"size": 10
}
}
}
}
}
}
A term filter should do just fine. For the inverse query, just negate it with a not filter:
"query":
{
"filtered" : {
"query": {
"match_all": {}
},
"filter" : {
"term": {
"grades.subject": "math"
}
}
}
}
And for the ones who did not study math:
"query":
{
"filtered" : {
"query": {
"match_all": {}
},
"filter" : {
"not": {
"filter": {
"term": {
"grades.subject": "math"
}
}
}
}
}
}

ElasticSearch Nested Query formulation

I have a mapping like this
{
"experience": {
"type": "nested",
"properties": {
"end": {
"type": "string"
},
"organization": {
"type": "nested",
"properties": {
"details": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
}
}
Now I want to make a query like this:
{
"nested": {
"path": "experience",
"query": {
"bool": {
"must": [{
"match": {
"experience.organization.name": {
"query": company_name,
"operator": "and"
}
}
}, {
"match": {
"experience.end": "Present"
}
}]
}
}
}
}
The above query is not returning any results, is this the correct way to index and query the above scenario?
I am confused about what should be the value of the path variable since organisation.name and end are not at the same level.
Here is a complete working sample with your code:
PUT index1/test1/_mapping
{
"test1": {
"properties": {
"experience": {
"type": "nested",
"properties": {
"end": {
"type": "string"
},
"organization": {
"type": "nested",
"properties": {
"details": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}
POST index1/test1
{
"experience": {
"end": "Present",
"organization": {
"name": "org1",
"details": "some details here"
}
}
}
GET index1/test1/_search
{
"query": {
"nested": {
"path": "experience",
"query": {
"bool": {
"must": [
{
"match": {
"end": "present"
}
},
{
"nested": {
"path": "experience.organization",
"query": {
"match": {
"name": "org1"
}
}
}
}
]
}
}
}
}
}
That being said, you have a double nested object here which you will probably find will work against you in the long run. I would consider flattening the data so that the nested is not necessary.

Elasticsearch OR query

Can anyone tell me how do I write the below Mysql query in elastisearch
Select * from `table` WHERE `Name`='A' OR `Name`='B' order by `rank` DESC
I have tried multiple solutions the internet like
{
"sort":{"rank":{"order":"desc"}},
"query": {
"query_string" : {
"fields" : ["Name"],
"query" : "A OR B"
}
}
and also tried the below code
{
"sort":{"rank":{"order":"desc"}},
"query" : {
"bool": {
"should": [
{
"match_phrase" : {
"Name" : "A"
}
},
{
"match_phrase": {
"Name": "B"
}
}
]
}
}
}
You could do it with Bool-Filter and Order on all Documents:
{
"query": {
"match_all": {}
},
"filter": {
"bool": {
"should": [
{
"term": {
"Name": "A"
}
},{
"term": {
"Name": "B"
}
}
]
}
},"sort": [
{
"rank": {
"order": "desc"
}
}
]
}
Or have a subset with Range Query:
"query": {
"range": {
"JoinDate": {
"lte": 1431051540
}
}
}
This is my current mappings are
{
"class": {
"mappings": {
"students": {
"properties": {
"Name": {
"type": "string"
},
"rank": {
"type": "string"
},
"Description": {
"type": "string"
},
"Image": {
"type": "string"
},
"JoinDate": {
"type": "date",
"format": "dateOptionalTime"
}
}
}
}
}
}
Try Terms filter. Below is equivalent of SQL query you wrote.
curl -XGET 'http://localhost:9200/_search?pretty' -d '{
"filter": {
"terms": {
"Name": ["A", "B"]
}
},
"sort": {
"rank": {
"order": "desc"
}
}
}'

Resources