Nested query trong elasticsearch là gì ?
Là thực hiện 1 truy vấn để tìm kiếm các đối tượng lồng nhau. Nested query tìm kiếm các đối tượng lồng nhau như thể chúng được đánh index là những tài liệu riêng biệt. Nếu một đối tượng khớp với điều kiện tìm kiếm thì nested query sẽ trả về đối tượng gốc.
Tạo index
Để sử dụng nested query, thì index của bạn phải bao gồm những ánh xạ lồng nhau
VD:
1 2 3 4 5 6 7 8 9 10 11 | PUT /my_index { "mappings" : { "properties" : { "obj1" : { "type" : "nested" } } } } |
Trong rails chúng ta dùng gem “chewy” để khai báo và quản lý index
chewy ở trang chủ gem chewy này sẽ có hướng dẫn config, cài đặt, nên chúng ta sẽ bỏ qua bước này.
VD: Có 2 model là User và Post.
- User có các field (name, email),
- Post có các field (title, content)
Chúng ta sẽ thực hiện tìm kiếm Post title để lấy ra User tạo ra bài Post đó
User có quan hệ has_many với Post. Thì dùng chewy chúng ta sẽ khai báo index nested như thế này
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 –> khai báo tên trường cần đánh index
- type –> khai báo kiểu dữ liệu của index đó
Đến đây chung ta đã xong bước setup index để sử dụng cho nested query
Thực hiện 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) : đường dẫn đến nested object mà bạn muốn tìm kiếm
- query (require, object query): Truy vấn bạn muốn chạy trên các đối tượng lồng nhau trong path. Nếu một đối tượng thõa mãn điều kiện, nested query sẽ trả về đối tượng gốc là User
Các đối tượng lồng nhau nhiều cấp
cách khai báo index tương tự như trên
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" } } } } } } } } |
Hoặc
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 |
Đối với lồng nhau nhiều cấp thế này, query search cũng tương tự như trên
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" } } ] } } } } } } } |
Nếu có đối tượng thõa mãn điều kiện tìm kiếm, thì nó cũng trả về đối tượng gốc User.
Tham khảo
1: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html