0

I'm struggling to build a query where I can do a nested search across a sub-object of a document.

Say I have the following index/mapping:

curl -XPOST "http://localhost:9200/author/" -d '
{
    "mappings": {
        "item": {
            "properties": {
                "books": {
                    "type": "object",
                    "properties": {
                        "data": {
                            "type": "nested"
                        }
                    }
                }
            }
        }
    }
}
'

And the following 2 documents in the index:

{
    "id": 1,
    "name": "Robert Louis Stevenson",
    "books": {
        "count": 2,
        "data": [
            {
                "id": 1,
                "label": "Treasure Island"
            },
            {
                "id": 3,
                "label": "Dr Jekyll and Mr Hyde"
            }
        ]
    }
}

and

{
    "id": 2,
    "name": "Philip K. Dick",
    "books": {
        "count": 1,
        "data": [
            {
                "id": 4,
                "label": "Do Android Dream of Electric Sheep"
            }
        ]
    }
}

I have an array of Book ID's, say [1,4]; how would I write a query which does a keyword search of the author name AND only returns them if they wrote one of the books in the array?

I haven't managed to get a query which doesn't cause some sort of query parse_exception, but as a starting block, here's the current iteration of my query - maybe it's obvious where I'm going wrong?

{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "label": "Louis"
                }
            }
        },
        "nested": {
            "path": "books.data",
            "query": {
                "bool": {
                    "must": {
                        "terms": {
                            "books.data.id": [
                                1,
                                4
                            ]
                        }
                    }
                }
            }
        }
    },
    "from": 0,
    "size": 8
}

In the above scenario I'd like the document for Mr Robert Louis Stevenson to be returned, as his name contains Louis and he wrote book ID 1.

For what it's worth, the current error I get looks like this:

{
   "error": {
      "root_cause": [
         {
            "type": "parse_exception",
            "reason": "failed to parse search source. expected field name but got [START_OBJECT]"
         }
      ],
      "type": "search_phase_execution_exception",
      "reason": "all shards failed",
      "phase": "query",
      "grouped": true,
      "failed_shards": [
         {
            "shard": 0,
            "index": "author",
            "node": "sCk3su4YSnqhvdTGjOztlw",
            "reason": {
               "type": "parse_exception",
               "reason": "failed to parse search source. expected field name but got [START_OBJECT]"
            }
         }
      ]
   },
   "status": 400
}

This makes me feel like I've got my "nested" object all wrong, but the docs suggest that I'm right!

1 Answer 1

2

You have it almost right, the nested query must simply be located inside the bool one like in the query below. Also the match query needs to be made on the name field since this is where the author name is stored:

{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "Louis"
          }
        },
        {
          "nested": {
            "path": "books.data",
            "query": {
              "bool": {
                "must": {
                  "terms": {
                    "books.data.id": [
                      1,
                      4
                    ]
                  }
                }
              }
            }
          }
        }
      ]
    }
  },
  "from": 0,
  "size": 8
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that got me on the right track. I also needed to place my must and nested objects into an array... subtle!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.