1

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

Когда пользователь вводит ключевые слова, он должен совпадать, если он найден в двух полях базы данных: Заголовок и Описание. Выпадающий фильтр по статусу и типу.

Вот моя Tire конфигурация поиска:

def self.search(params) 
     tire.search(load: true, page: params[:page], per_page: 25) do 
     query do 
      boolean do 
      should { string "title:#{params[:query]}", default_operator: "OR" } if params[:query].present? 
      should { string "description:#{params[:query]}", default_operator: "OR" } if params[:query].present? 
      must { term :status_id, params[:status_id] } if params[:status_id].present? 
      must { term :type_id, params[:type_id] } if params[:type_id].present? 
      end 
     end 
     sort { by :updated_at, "desc" } if params[:query].blank? 
     facet "status" do 
      terms :status_id 
     end 
     facet "type" do 
      terms :type_id 
     end 
     end 
    end 

Параметры индексирования:

settings :analysis => { 
     :filter => { 
      :my_ngram => { 
       "type" => "nGram", 
       "max_gram" => 10, 
       "min_gram" => 3} 
     }, 
     :analyzer => { 
      :my_analyzer => { 
       "type" => "custom", 
       "tokenizer" => "lowercase", 
       "filter" => ["my_ngram"] 
      } 
     } 
    } do 
    mapping do 
     indexes :title, boost: 10, analyzer: 'my_analyzer' 
     indexes :description, boost: 5, analyzer: 'my_analyzer' 
     indexes :status_id, :type => 'integer' 
     indexes :type_id, :type => 'integer' 
    end 
    end 

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

Каков правильный способ настройки этого параметра? Если выбран статус, он должен возвращать только записи с этим статусом. То же самое следует для типа, и если оба выбраны.

Любая помощь приветствуется.

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

curl -X GET 'http://localhost:9200/projects/project/_search?load=true&size=25&pretty' -d '{"query":{"bool":{"should":[{"query_string":{"query":"title:test","default_operator":"OR"}},{"query_string":{"query":"description:test","default_operator":"OR"}}],"must":[{"term":{"status_id":{"term":"1"}}},{"term":{"type_id":{"term":"1"}}}]}},"facets":{"status":{"terms":{"field":"status_id","size":10,"all_terms":false}},"type":{"terms":{"field":"type_id","size":10,"all_terms":false}}},"size":25}' 

# 2013-08-16 12:08:34:791 [200] (31 msec) 
# 
# {"took":31,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]},"facets":{"status":{"_type":"terms","missing":0,"total":0,"other":0,"terms":[]},"type":{"_type":"terms","missing":0,"total":0,"other":0,"terms":[]}}} 
+0

Вы должны попробовать использовать фильтры, а не дополнительные запросы 'must', если вам не нужна оценка, это будет намного быстрее. Кроме того, какова конкретная проблема, с которой вы сталкиваетесь? Не могли бы вы дать ошибку или список результатов, которые не ожидаются? – ramseykhalaf

+0

Спасибо за ответ. Я обновил свой ответ с результатом поиска. Теперь он не фильтрует по ключевым словам или граням. Может быть, у вас есть пример использования фильтров в отличие от «must» в моем сценарии? Возможно, это тот ответ, который я ищу. – Drew

+0

Я не знаю, если это проблема, но вы уверены, что хотите искать строку «title: test», а не просто «test» в поле 'title'? Также обратите внимание, что при настройке такого анализатора будут установлены анализаторы поиска и индекса времени. – ramseykhalaf

ответ

3

Если бы вы могли создать эквивалент этого, я думаю, вы бы получить желаемые результаты. (Прошу прощения за отсутствие кавычек на клавишах JSON!)

{ 
    query: { 
     multi_match: { 
     query: "test", 
     fields: ["title", "description"] 
     } 
    }, 
    filter: { 
     and: [ 
     { 
      term: { status_id: 123 } 
     }, 
     { 
      term: { type_id: 456 } 
     } 
     ] 
    }, 
    facets: { 
     type: { 
     terms: { 
      field: "type_id", 
      size: 10 
     } 
     }, 
     status: { 
     terms: { 
      field: "status_id", 
      size: 10 
     } 
     } 
    } 
} 

Update

я не знаю, но шина будет пытаться что-то написать!

def self.search(params) 
    tire.search(load: true, page: params[:page], per_page: 25) do 
     query do 
     boolean do 
      should { match :title params[:query] } if params[:query].present? 
      should { match :description params[:query] } if params[:query].present? 
     end 
     end 

     sort { by :updated_at, "desc" } if params[:query].blank? 

     filter :and, { :term => { :status_id => params[:status_id] } } if params[:status_id].present? 
        { :term => { :type_id => params[:type_id] } } if params[:type_id].present? 
    end 
    end 

Возможно, вам придется исправить рубин, но несколько вещей, чтобы отметить. Соответствующие запросы - это рекомендуемый стандартный поиск по строкам, они быстрее, чем query_string (хотя у вас немного меньше контроля). Также

+0

Я ценю, что вы тратите время на изучение этого. Я согласен, что это тот тип результатов, который я ищу, однако я хотел бы знать, как это сделать с Tire. У меня такое чувство, что это будет полезно для других, а также для многих, кто использует ES с Rails, также используют Tire. – Drew

+0

Не беспокойтесь! Могу ли я спросить, какие у вас проблемы с последним методом (редактирование с помощью фильтров верхнего уровня)? – ramseykhalaf

+0

Я добавил еще одно обновление к моему вопросу. – Drew

Смежные вопросы