Elasticsearch-модель - пытается ссылаться на родительские данные для добавления в индекс - PullRequest
0 голосов
/ 29 апреля 2020

Я использую эластичный поиск с рельсами для поиска в реальном времени в твиттероподобном фиде. У меня есть таблица User и таблица Post , которые хранятся в Postgres. Я хочу индексировать только таблицу Пост в ES для поиска, однако мне нужны данные Пользователь для каждого поста, чтобы я мог показать, кто сделал пост, каков его ранг и т. Д. c. По сути, я хочу присоединиться к User и Post data, а затем проиндексировать их вasticsearch. Прямо сейчас моя Пост модель выглядит следующим образом:


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, каждый Post , который он возвращает, представляет собой объект, который выглядит так:

{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1}

Я хочу иметь возможность хранить соответствующий объект пользователя или пользовательские данные в каждом объекте публикации, а не только в user_id. В идеале я хотел бы видеть объект Post , который выглядит примерно так:

{ "id": x , "title": "y" , "description": "z", "image": "", "vouches": 0, "user_id": 1, "username": "a", "rank": 0...etc}

Мне кажется, что это должно произойти где-то в модели Post , но я мне не удалось использовать вложенные отображения среди других.

1 Ответ

0 голосов
/ 01 мая 2020

Таким образом, я смог решить эту проблему, используя метод 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
...