Elastic Search/Tire: как сопоставить атрибут ассоциации?

Я использую Tire для Elastic Search. В моем приложении у меня есть 2 модели; Цена и продукт.

Я пытаюсь найти свой класс цен и использовать атрибут :name продукта, которому он принадлежит, для поля поиска. Прямо сейчас, если бы у меня был продукт под названием Product 1 и я набрал "pro", "prod" или "duct", никаких результатов не появилось бы. Но ввод «продукт» или «продукт» показывает результаты. Я считаю, что проблема заключается в моем отображении. Я посмотрел на запрос и его:

...localhost:3000/search/results?utf8=%E2%9C%93&query=product

Когда я думаю, что это должно быть:

...localhost:3000/search/results?utf8=%E2%9C%93&query:product=product

Судя по этому вопросу: отображение ElasticSearch не работает

Я не знаю, как сделать так, чтобы мой params[:query] брал только product.name. Я пытался использовать: string params[:query], default_field: "product.name", но это не сработало.

Я не хочу использовать поле _all.

Вот мой код:

Цена.руб.

  include Tire::Model::Search
  include Tire::Model::Callbacks

  def self.search(params)
    tire.search(load: true, page: params[:page], per_page: 20) do
       query do
         boolean do
            must { string params[:query] } if params[:query].present?
            must { term :private, false }
         end
       end
       sort do
         by :date, "desc"
         by :amount, "asc"
       end
    end
  end

  def to_indexed_json
    to_json( include: { product: { only: [:name] } } )
  end

  mapping do
    indexes :id,        type: "integer"
    indexes :amount,    type: "string", index: "not_analyzed"
    indexes :date,      type: "date",   index: "not_analyzed"
    indexes :private,   type: "boolean"
    indexes :product do
      indexes :name, type: "string", analyzer: "custom_analyzer"
    end
  end

  settings analysis: {
    analyzer: {
      custom_analyzer: {
        tokenizer: [ "whitespace", "lowercase" ],
        filter: [ "ngram_filter", "word_delimiter_filter" ],
        type: "custom"
      }
    },
    filter: {
      ngram_filter: {
        type: "nGram",
        min_gram: 2,
        max_gram: 15
      }
    },
    filter: {
      word_delimiter_filter: {
        type: "word_delimiter",
        generate_word_parts: true,
        generate_number_parts: true,
        preserve_original: true,
        stem_english_possessive: true
      }
    }
  }

Итак, есть ли у кого-нибудь какие-либо предложения или кто-нибудь знает, как настроить поле запроса для использования только имени продукта?

Спасибо.


person LearningRoR    schedule 22.08.2012    source источник
comment
В ближайшее время мне предстоит заняться этим же вопросом. Так что я буду обновлять свой прогресс, если вы меня не опередите!   -  person Alain    schedule 24.08.2012
comment
@ Ален, я все еще работаю над этим, поэтому, если у вас есть идеи, как заставить это работать, дайте мне знать. Ваш прогресс был бы большим подспорьем.   -  person LearningRoR    schedule 26.08.2012


Ответы (2)


Когда вы делаете

 query   { string params[:query] } 

и в запросе не указано поле, вы ищете волшебное поле _all. Это поле имеет свои собственные настройки анализатора — он не будет использовать тот, который вы настроили для поля имени.

Вы можете либо настроить поле _all для использования вашего анализатора, либо изменить анализатор по умолчанию, либо изменить свой запрос, чтобы запрашивать конкретно поле name, например

 query { string params[:query], :default_field => 'name'}
person Frederick Cheung    schedule 24.08.2012
comment
Я не смог найти никакой документации по default_field => 'name'. Где ты это узнал? Если бы я пытался использовать поле product.name. Как это могло случиться? - person LearningRoR; 26.08.2012
comment
Это не работает для меня. Правильно ли мое сопоставление с product.name? Я думаю, поэтому он не работает. - person LearningRoR; 26.08.2012
comment
О, вы, вероятно, хотите установить поле по умолчанию для product.name, не заметили вложенности вашего сопоставления - person Frederick Cheung; 26.08.2012
comment
Так что я просто делаю: must { string params[:query], :default_field => "product.name" }? Потому что он не работает. Я понятия не имею, куда идти отсюда, но я все еще осматриваюсь. - person LearningRoR; 27.08.2012
comment
Все еще делаю все, что могу, чтобы понять это. Я полностью изменил свой код выше. - person LearningRoR; 28.08.2012
comment
Вы пробовали текстовый запрос с явным полем? Вы проверили, что эластичный поиск подобрал ваши настройки (для таких настроек, как анализатор, я думаю, вам нужно воссоздать индекс при их изменении) - person Frederick Cheung; 28.08.2012
comment
Если вы имеете в виду этот :default_field => 'name' или этот :default_field => 'product.name', тогда да, и оба не вернут результатов поиска. По подбору настроек у меня работает только $ rake environment tire:import CLASS='Price' FORCE=true. Возможно проблема в моей версии Rails and Tire ( "rails", "3.1.0", "tire", "0.4.2") - person LearningRoR; 28.08.2012
comment
Я имею в виду использование запроса типа текста, а не строки. Стоит покопаться, чтобы увидеть, действительно ли elasticsearch использует указанное вами сопоставление (посмотрите на настройки и mappin apis) - person Frederick Cheung; 28.08.2012
comment
Я думаю, ты прав. Я считаю, что сопоставление не происходит. Я обновил свой код, чтобы показать вам странную ошибку. Я меняю свой query_string и получаю ошибку. - person LearningRoR; 28.08.2012
comment
Итак, я считаю, что блок settings не работает. Не знаю, почему. Мое обновление 2 объясняет больше. - person LearningRoR; 29.08.2012
comment
Я бы попробовал удалить индекс, а затем позволить шине воссоздать его. - person Frederick Cheung; 29.08.2012
comment
Единственный известный мне способ удаления — это rake environment tire:import CLASS='Price' FORCE=true. Я думаю, что у него нет команды rake для удаления. - person LearningRoR; 29.08.2012
comment
Итак, я не думаю, что это настройки, это сопоставление. Я обновил свой вопрос, чтобы отразить это. - person LearningRoR; 29.08.2012
comment
Спасибо за помощь. Вместо этого просто использовал Ransack. Куда проще разобраться. - person LearningRoR; 30.08.2012

Это было очень головной болью, поэтому я пошел к Ransack, что было безумно намного проще понять и использовать.

person LearningRoR    schedule 30.08.2012