I am super new to Elastic Search. I have a use case which seems can be solved by the parent-child relationship. Parent doc contains the description of an NGO. Child doc contains various feedbacks sent to the NGO.
Parent Doc structure
{
name
address
description
}
Child doc
{
feedbackContent
}
Let's say, NGO-A 4 feedbacks (meaning 4 child documents)
best teachers
best facilities
good students
location is too far
Another NGO-B has 2 feedbacks (meaning 2 child documents)
good food quality
awesome location
The client should be able to look up the NGOs which has all the terms in the query string passed. Example - client searched for "best" AND "location".
Since best
is present in child1 and child2 and location
is present in child 4, NGO-A is a valid output. However, for NGO-B child2 contains one search term and the other search term is not present in any other child doc so NGO-B is not a valid result.
I read the doc - https://blog.mimacom.com/parent-child-elasticsearch/ which is quite good but unable to conclude if this can be done.
Examples I tried
PUT message_index
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0,
"mapping.single_type": true
},
"mappings": {
"doc": {
"properties": {
"ngo": {"type": "text"},
"feedback": {"type": "text"},
"ngo_relations": {
"type": "join",
"relations": {
"ngo": "feedback"
}
}
}
}
}
}
POST message_index/doc/_bulk
{"index": {"_id":1}}
{"name":"teach for india", "ngo_relations": {"name":"ngo"}}
{"index":{"_id":2}}
{"name":"hope for autism", "ngo_relations": {"name":"ngo"}}
PUT message_index/doc/3?routing=1
{"feedback":"best food","ngo_relations":{"name":"feedback", "parent":1}}
PUT message_index/doc/4?routing=1
{"feedback":"average location","ngo_relations":{"name":"feedback", "parent":1}}
PUT message_index/doc/5?routing=1
{"feedback":"awesome staff","ngo_relations":{"name":"feedback", "parent":1}}
PUT message_index/doc/6?routing=2
{"feedback":"best teachers","ngo_relations":{"name":"feedback", "parent":2}}
PUT message_index/doc/7?routing=2
{"feedback":"awesome overload","ngo_relations":{"name":"feedback", "parent":2}}
For best and location search, just teach for india NGO should be returned.
No hits:
GET message_index/_search
{
"query": {
"has_child": {
"type": "feedback",
"query": {
"bool": {
"must": {
"term": {"feedback": "best"}
},
"must": {
"term": {"feedback": "location"}
}
}
}
}
}
}
Both the documents are returned
GET message_index/_search
{
"query": {
"has_child": {
"type": "feedback",
"query": {
"bool": {
"should": {
"term": {"feedback": "best"}
},
"should": {
"term": {"feedback": "location"}
}
}
}
}
}
}
This can be done. You were close just a small mistake in the query.
In your child query, you are performing a bool with two must/should. Therefore, your query is: Give me all documents such that they have a child such that the child has both (or 'one of the' in case of should) the terms "best" and "location".
Whereas, what you want is: Give me all documents such that they have a child such that the child has the term "best" and also have a child such that the child has the term "location".
Tweak your query as follows:
GET message_index/_search
{
"query": {
"bool": {
"must": [
{
"has_child": {
"type": "feedback",
"query": {
"term": {
"feedback": "best"
}
}
}
},
{
"has_child": {
"type": "feedback",
"query": {
"term": {
"feedback": "location"
}
}
}
}
]
}
}
}