Подход для поиска связанной модели с Elasticsearch [Ruby, ActiveRecord, эластичный поиск модели) - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть вопрос о выборе наилучшего подхода в случае поиска в Elasticsearch.

У меня есть Ruby off Rails API, с ActiveRecord, вместе с Elasticsearch (elasticsearch-model gem).

Это простой API, который возвращает projects (модель Project AR), где я настраиваю индексы:

mapping dynamic: false do
indexes :created_at, type: 'date'
end

Затем я просто выполняю поиск в Elasticsearch и возвращаю AR отношения напрямую с контролером. Он отлично работает.

Теперь я пытаюсь добавить categories к projects, как categories has_many projects и projects belongs_to categories. Я задаюсь вопросом о двух вещах:

Как теперь я должен сделать запрос для получения проектов из определенных c категорий, должен ли я переопределить его, чтобы вернуть result = Category.search(...) и вернуть result.jobs, или все еще искать по projects, но поиск по category_id?

Как объединить Category и Project в Elasticsearch, чтобы сделать возможным поиск проектов из определенной категории c и из нескольких различных категорий? Объединить сопоставления?

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

// отображение (вложенные категории)

 mapping dynamic: false do
  indexes :created_at, type: 'date'
  indexes :categories, type: 'nested' do
    indexes :name, type: :text, analyzer: :english
  end 
 end

// json

  def as_indexed_json(_options = nil)
  { 
   created_at: created_at,
   # in case project belong_to category  
   # categories: [category.name, Category::DEFAULT].map do ... 
   categories: categories.map do |category|
     {
       name: category.name
     }
   end
  } 
 end

// функция поиска (asticsearch DSL ), как вы хотите искать проекты по категориям

def by_categories(categories)
  filters = []
  categories.each { |category|
    filters.push term: {"categories.name":category.name}
  }
  Project.__elasticsearch__.search(
     query: {            
        nested: {
           path: "categories",
           query: {
              bool: {
                 filter:{
                    bool:{
                        should:filters                                       
                    }
                  }
               }
            }
        }    
     }
  )
end
1 голос
/ 19 февраля 2020

Мое первое, хотя здесь, это то, что вы используете очень простой случай. Вам не нужен Elasticsearch вообще. Вы можете упростить и использовать только ActiveRecord, выбрать SQL и вернуть записи. Вам не нужны никакие функции, предоставляемые Elasticsearch для вашего случая использования, вы просто делаете больше работы для себя, делая это.

Однако я буду предполагать, что ваша разработка будет повторяться и ваше использование получит значительно сложнее. Обоснование использования Elasticsearch.

Реляционные и нереляционные данные

ActiveRecord представляет собой ORM для реляционных данных. Типичный https://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.htmlly находится поверх реляционной базы данных на основе языка структурированных запросов . Он действительно хорошо поддерживает отношения (ассоциации на языке Rails).

Elasticsearch - это нереляционное хранилище документов , хранящее информацию как JSON в инвертированном индексе. Это позволяет очень быстрый полнотекстовый поиск (среди прочего). Это не очень хорошо поддерживает отношения между документами. Он разработан, чтобы не связывать данные! Он хочет, чтобы вы не хранили отношения и вместо этого постоянно повторяли данные, в противоположность подходу SQL. Это называется денормализация, подробнее об этом ниже.

Это очень разные способы восприятия хранения данных! Это не значит, что они плохо играют вместе. Они могут хорошо работать вместе, если используются правильно. Тем не менее, они используют разные способы мышления. На мой взгляд, важно иметь хорошую оценку asp основных принципов для каждого, чтобы составить здравое суждение о том, как их использовать.

Elasticsearch имеет отличную документацию . Я рекомендую вам потратить пару часов, читая об этом.

Как Elasticsearch связывает вас?

Вас волнует базовая c has-many ассоциация в вашей вопрос, так как же Elasti c справляется с этим? Какие есть варианты?

Есть 4 основных варианта. Я думаю, вам следует денормализовать ваши данные здесь.

Я думаю, что вы хотите вернуть все проекты из определенных категорий. Таким образом, вы должны создать индекс, который содержит документ для каждой категории. Каждая категория должна иметь полный список своих проектов. Затем вы можете запросить категорию и вернуть все ее проекты.

Это один из подходов. Ваш вариант использования настолько прост, что мне кажется это излишним, вы можете решить эту проблему, используя любой из 4 основных вариантов Elasticsearch, указанных выше. Или, в идеале, вообще не использовать Elasticsearch.

Если вы предоставите более подробную информацию о вашем сценарии использования, я смогу подробнее обсудить, какой подход вы можете использовать.

...