What is a nested query in elasticsearch?
Perform a query to search for nested objects. Nested queries look for nested objects as if they were indexed as separate documents. If an object matches the search criteria, the nested query will return the original object.
Create the index
To use nested queries, your index must include nested mappings, for example:
1 2 3 4 5 6 7 8 9 10 11 | PUT /my_index { "mappings" : { "properties" : { "obj1" : { "type" : "nested" } } } } |
In rails we use the gem “chewy” to declare and manage the chewy index on the home page of this chewy gem will have instructions for config and installation, so we will skip this step. Example: There are 2 models, User and Post.
- Users have fields (name, email),
- Post has fields (title, content) We will perform a post title search to retrieve the user who created that post
User has has_many relationship with Post. Then using chewy we will declare the nested index like this
1 2 3 4 5 6 7 8 9 10 11 12 | class UsersIndex < Chewy::Index define_type Users.includes(:posts) do field :id, type: :integer field :name, type: :text field :email, type: :text field :posts, type: :nested do field :id, type: :integer field :title , type: :text end end end |
- field -> declare the field name to be indexed
- type -> declare the data type of that index We have now completed the setup of the index to use for nested queries
Perform query search
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | GET /users/_search { "query": { "nested" : { "path" : "posts", "query" : { "bool" : { "must" : [ { "match" : {"posts.title" : "Elasticsearch"} } ] } }, "score_mode" : "avg" } } } |
- path (require, string): path to the nested object you want to search
- query (require, object query): The query you want to run on nested objects in path. If an object satisfies the condition, the nested query will return the original object User
Multi-level nested objects
How to declare index similar to above
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | PUT /users { "mappings" : { "properties" : { "posts" : { "type" : "nested", "properties" : { "title" : { "type" : "text" }, "tags" : { "type" : "nested", "properties" : { "name" : { "type" : "text" } } } } } } } } |
Or
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class UsersIndex < Chewy::Index define_type Users.includes(:posts) do field :id, type: :integer field :name, type: :text field :email, type: :text field :posts, type: :nested do field :id, type: :integer field :title , type: :text field :tags, type: :nested do field :name, type: :text end end end end |
For multiple levels of nested, query search is the same
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | GET /users/_search { "query" : { "nested" : { "path" : "posts", "query" : { "nested" : { "path" : "posts.tags", "query" : { "bool" : { "must" : [ { "match" : { "posts.tags.name" : "ES Search" } } ] } } } } } } } |
If the object satisfies the search criteria, it also returns the original User object.
Refer
1: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html