I have some data like so in elasticsearch:
account (http://localhost:9200/myapp/account/1)
========
name
state
groups //groups is an array containing objects like so {id: 1, starred: true}
//the id is the id of the group type
email (http://localhost:9200/myapp/email/1?parent=1)
========
email
primary //just a boolean to denote whether this email is primary or not
group
========
name
description
emails are children of account.
Based on imotov’s excellent answer, I am able to run a search on account.name and email.email and return ALL accounts where the searched prefix matches the above 2 fields:
{
"query": {
"bool": {
"must": [
{
"term": {
"statuses": "active"
}
}
],
"should": [
{
"prefix": {
"name": "a"
}
},
{
"has_child": {
"type": "email",
"query": {
"prefix": {
"email": "a"
}
}
}
}
],
"minimum_number_should_match" : 1
}
}
}
What I would like to do now is to return 2 custom fields for each result:
-
For each result return a field called
email, if the search was matched on theemailtype (which is a child ofaccount), return that email, otherwise return theprimaryemail linked to the account, if none,nullcan be returned. -
For each result return a field called
group. The value of the field should contain the name of the starredgroupwhose id is stored in thegroupsarray. Essentially: Findgroup.idwheregroup.starredis true in eachaccount.groups, then return the matchinggroup.namefrom thegrouptype base on the id we found.
I have been looking at script fields, but I am not sure if it is able to return fields for each hit. I am also not sure if the above is actually accomplishable in ES.
Could someone provide some pointers as to whether this is possible and how to get started?
Currently, there is simply no way to get to access the data in a
has_childornestedclause.The only solution is to get some data, make some decisions on the client and then get more data.
Here’s what I did to achieve it:
Run the query above and get back the data.
To deal with showing the match emails or the primary email (run on the email type):
Base on the above query, we can get any email addresses that were matched by the search term. Remember to set the fields in the above query to include
_parent.We can then use
array_diff()or a similiar function in languages other than PHP to diff the parent ids from above and and original query. This should then give us a list of accounts where no email was matched. Simply then send another request to get the primary emails for those accounts.For the groups, send a query to type
accountand:_idto the list of account ids.group.starredtotrue.This should get you a list of starred groups. To get more information (name etc), send a query to type
groupand:_idto the group ids above.Finally, do some client side processing to put it together so that it is easier for the next part of your program to use.