Elasticsearch-model - 尝试引用父数据以添加到索引
Elasticsearch-model - trying to reference parent data to add to index
我将 elasticsearch 与 rails 一起用于类似 Twitter 的提要上的实时搜索功能。我有一个 User table 和一个 Post table 存储在 Post格雷斯。我只想在 ES 中索引 Post table 进行搜索,但是我想要每个 User 数据 post 所以我可以显示谁做了 post,他们的排名是什么等等。所以基本上我想加入 User 和 Post数据,然后索引到elasticsearch。现在,我的 Post 模型如下所示:
class Post < ApplicationRecord
belongs_to :user
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
index_name Rails.application.class.parent_name.underscore
settings index: { number_of_shards: 1 } do
mapping dynamic: false do
indexes :title, analyzer: 'english'
indexes :description, analyzer: 'english'
end
end
def self.search(query)
__elasticsearch__.search(
{
query: {
multi_match: {
query: query,
type: 'phrase',
fields: ['title^5', 'description']
},
}
)
end
我的用户模型是这样的:
class User < ApplicationRecord
has_many :posts
end
我的架构如下所示:
ActiveRecord::Schema.define(version: 2020_04_16_175351) do
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "image"
t.integer "vouches"
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "username"
t.integer "rank"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
add_foreign_key "posts", "users"
end
当我在 localhost:9200 上执行 elasticsearch 查询时,每个 Post 它 returns 是一个如下所示的对象:
{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1}
我希望能够将相关的用户对象或用户数据存储在每个 post 对象中 - 而不仅仅是 user_id。理想情况下,我希望看到一个看起来类似于此的 Post 对象:
{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1, "username": "a", "rank": 0...etc}
我觉得这应该发生在 Post 模型中的某个地方,但我尝试在其他模型中使用嵌套映射却没有成功。
所以我能够使用 elasticsearch-models 中的 'as_indexed_json' 方法解决这个问题。我只是将它放在映射下的 Post 模型中。
def as_indexed_json(options = {})
self.as_json(
options.merge(
only: [:id, :title, :body, :published_at, :created_at, :updated_at],
include: { user: { only: [:id, :name] } }
)
)
end
我将 elasticsearch 与 rails 一起用于类似 Twitter 的提要上的实时搜索功能。我有一个 User table 和一个 Post table 存储在 Post格雷斯。我只想在 ES 中索引 Post table 进行搜索,但是我想要每个 User 数据 post 所以我可以显示谁做了 post,他们的排名是什么等等。所以基本上我想加入 User 和 Post数据,然后索引到elasticsearch。现在,我的 Post 模型如下所示:
class Post < ApplicationRecord
belongs_to :user
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
index_name Rails.application.class.parent_name.underscore
settings index: { number_of_shards: 1 } do
mapping dynamic: false do
indexes :title, analyzer: 'english'
indexes :description, analyzer: 'english'
end
end
def self.search(query)
__elasticsearch__.search(
{
query: {
multi_match: {
query: query,
type: 'phrase',
fields: ['title^5', 'description']
},
}
)
end
我的用户模型是这样的:
class User < ApplicationRecord
has_many :posts
end
我的架构如下所示:
ActiveRecord::Schema.define(version: 2020_04_16_175351) do
create_table "posts", force: :cascade do |t|
t.string "title"
t.text "description"
t.string "image"
t.integer "vouches"
t.bigint "user_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "username"
t.integer "rank"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
add_foreign_key "posts", "users"
end
当我在 localhost:9200 上执行 elasticsearch 查询时,每个 Post 它 returns 是一个如下所示的对象:
{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1}
我希望能够将相关的用户对象或用户数据存储在每个 post 对象中 - 而不仅仅是 user_id。理想情况下,我希望看到一个看起来类似于此的 Post 对象:
{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1, "username": "a", "rank": 0...etc}
我觉得这应该发生在 Post 模型中的某个地方,但我尝试在其他模型中使用嵌套映射却没有成功。
所以我能够使用 elasticsearch-models 中的 'as_indexed_json' 方法解决这个问题。我只是将它放在映射下的 Post 模型中。
def as_indexed_json(options = {})
self.as_json(
options.merge(
only: [:id, :title, :body, :published_at, :created_at, :updated_at],
include: { user: { only: [:id, :name] } }
)
)
end