Searching nested objects with parent-child relationship

Here's the mapping:

{
 "mappings":{
  "_doc":{
   "properties":{
    "person":{
     "type": "nested",
     "properties":{
      "name": {
       "type": "text"
      }
     }
    },
    "item": {
     "type": "nested",
     "properties": {
      "label":{
       "type":"text"
      },
      "description":{
       "type":"text"
      }
     }
    },
    "owner": {
     "type": "join",
     "relations": {
      "person": "item"
     }
    }
   }
  }
 }
}

So then I create a person:

XPUT /_doc/1?refresh
{
 "person": {
  "name": "John Smith"
 },
 "owner": "person"
}

And an item:

XPUT /_doc/1-1?routing=1
{
 "item": {
  "label": "Bag",
  "description": "Used to carry around stuff"
 },
 "owner": {
  "name": "item",
  "parent": 1
 }
}

Now, I want to query ES to fetch both the item and the owner of that item (not just the id, but also all the owner's fields).
I've already tried using nested queries with has_parent filters, or has_parent queries with a nested query within it, but I always get no results.

Any ideas on how I can do that?

Hi Slobbard,

nested and parent/child are 2 different approaches to joins.

  • Nested is about storing related content in the same JSON but storing as neighbouring Lucene documents in an index.
  • Parent/child is about storing parents and children in different JSON docs but routing them to the same shard.

Each has different indexing and query apis accordingly.

Hi Mark, thanks for your reply.

Should I change my mapping or my query then?
Is there a way to query children and fetch also parents' data?

You need to decide if you want parent/child or nested (this flowchart can help) then ensure that your indexing and querying use the appropriate parameters for that choice.

Yep.

So my mapping as described above is in fact incompatible with what I want to achieve..?
From your flowchart I'd say that flattening everything into a single JSON structure would probably be best, and then querying for child-parent with a join.

My idea was to use a more encapsulated approach like the one above because person and item will have many more properties within them, and I figured it'd encapsulate better the two entities.
Is a flattened JSON the recommended ElasticSearch approach?

You're confusing bullet point 1 with 2 again

Hey Mark, thanks again for your replies.
I am a little confused. You said that nested and parent/child are two different approaches to joins.
I'm trying to make them work together, in fact, as I wanted to achieve what I've described above. Is there a way to make that work? What am I doing wrong exactly?

It depends what you're trying to achieve. Looking at the mapping for example I can't see any reason why person is modelled as a nested property when a plain object type would suffice.
You would typically only resort to nested when you have an array of JSON objects each with >1 field and you want to avoid confusing properties of one object with that of another. For example, if a person has many car objects you might use nested if you wanted to query for car.colour:blue AND car.make:Ford to avoid confusing values of the blue BMW and the black Ford. If you only have one property (eg vehicleNumber) then there's no confusion and no need for nested. Your Person object is like that - it only has one property. This old slide deck explains the outline of why nested is sometimes required with Lucene.

1 Like

Alright I see what you're trying to say, the example helped a lot, thanks Mark!

1 Like

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.