Подтвердить что ты не робот

Как я могу использовать запрос dll ElasticSearch-Rails для возврата связанных отношений

Я новичок в ElasticSearch, но мне нужно использовать его для возврата списка продуктов. Пожалуйста, не включайте ответы или ссылки на старые ответы, которые ссылаются на устаревшую шину.

Gemfile

ruby '2.2.0'
gem 'rails', '4.0.3'
gem 'elasticsearch-model', '~> 0.1.6'
gem 'elasticsearch-rails', '~> 0.1.6'

У меня есть пара моделей с отношениями. Я включил отношения ниже.

Модели и отношения

product.rb    включить Searchable

  belongs_to :family
  belongs_to :collection
  has_many :benefits_products
  has_many :benefits, :through => :benefits_products

  def as_indexed_json(options={})
    as_json(
        include: {:benefits => { :only => [ :id, :name ] },
                  :categories => { :only => [ :id, :name ] } }
    )
  end

collection.rb

  include Searchable

  has_many :products

  def as_indexed_json(options={})
    as_json(
      include: [:products]
    )
  end

family.rb

  include Searchable

  has_many :products

  def as_indexed_json(options={})
    as_json(
      include: [:products]
    )
  end

benefit.rb

  include Searchable

  has_many :benefits_products
  has_many :products, :through => :benefits_products

  def as_indexed_json(options={})
    as_json(
      include: [:products]
    )
  end

Serachable.rb Это всего лишь проблема, которая включает в себя поиск и обратные вызовы для всех моделей.

module Searchable
  extend ActiveSupport::Concern

  included do
    include Elasticsearch::Model
    include Elasticsearch::Model::Callbacks

    settings index: { number_of_shards: 1, number_of_replicas: 0 } do
      mapping do

        indexes :id, type: 'long'
        indexes :name, type: 'string'
        indexes :family_id, type: 'long'
        indexes :collection_id, type: 'long'
        indexes :created_at, type: 'date'
        indexes :updated_at, type: 'date'

        indexes :benefits, type: 'nested' do
          indexes :id, type: 'long'
          indexes :name, type: 'string'
        end

        indexes :categories, type: 'nested' do
          indexes :id, type: 'long'
          indexes :name, type: 'string'
        end

      end
    end

    def self.search(options={})
      __set_filters = lambda do |key, f|

        @search_definition[:filter][:and] ||= []
        @search_definition[:filter][:and]  |= [f]
      end

      @search_definition = {
        query: {
          filtered: {
            query: {
              match_all: {}
            }
          }
        },
        filter: {}
      }

      if options[:benefits]
        f = { term: { "benefits.id": options[:benefits] } }

        __set_filters.(:collection_id, f)
        __set_filters.(:family_id, f)
        __set_filters.(:categories, f)
      end

      def as_indexed_json(options={})
        as_json(
          include: {:benefits => { :only => [ :id, :name ] },
                    :categories => { :only => [ :id, :name ] } }
        )
      end

      if options[:categories]
        ...
      end

      if options[:collection_id]
        ...
      end

      if options[:family_id]
        ...
      end

      __elasticsearch__.search(@search_definition)
    end

  end
end

ElasticSearch

Я разбил разбитые пули в разные семьи, коллекции и преимущества. Я могу искать продукты с определенной семьей или коллекцией и возвращать правильные результаты. Я также могу вернуть результаты за одно преимущество, но они не кажутся точными. Также поиск нескольких преимуществ дает странные результаты. Я хотел бы, чтобы комбинация "И" всех полей искала, но мой результат, похоже, не является результатом "И" или "ИЛИ". Так что это меня тоже смущает.

Что я передаю методу Product.search для получения желаемых результатов?

Спасибо за любую помощь, которую вы можете предоставить!

Изменить

Теперь я подтвердил, что преимущества индексируются для продуктов. Я использовал curl -XGET 'http://127.0.0.1:9200/products/_search?pretty=1', который вызвал ответ json, который выглядел так:

{
  "id":4,
  "name":"product name"
  "family_id":16
  "collection_id":6
  "created_at":"2015-04-13T12:49:42.000Z"
  "updated_at":"2015-04-13T12:49:42.000Z"
  "benefits":[
    {"id":2,"name":"my benefit 2"},
    {"id":6,"name":"my benefit 6"},
    {"id":7,"name":"my benefit 7"}
  ],
  "categories":[
    {"id":2,"name":"category 2"}
  ]}
},
{...}

Теперь мне просто нужно выяснить, как искать продукт с преимуществами 2,6 и 7 в ElasticSearch, если бы я хотел использовать этот примерный продукт. Я специально ищу синтаксис для отправки в метод elsearchearch #search для получения результатов вложенного запроса "AND", установки/сопоставления вложенных запросов (чтобы убедиться, что я ничего не пропустил, и любую другую соответствующую информацию, которую вы можете думать вы устраняете это.

Upated

Уязвимость поиска была обновлена, чтобы отразить полученный ответ. Я перевел объект json отображения, чтобы он соответствовал синтаксису модели elasticsearch. Моя оставшаяся путаница возникает, когда я пытаюсь перевести запрос аналогичным образом.

Второе обновление

Я использую основную часть моего поискового запроса .rb пример приложения elasticsearch-rails. Я обновил searchable.rb, чтобы отразить этот код, и пока я получаю результаты, они не являются результатом выполнения "И" . Когда я применяю два преимущества, я получаю результаты от всех продуктов, которые приносят пользу.

4b9b3361

Ответ 1

По умолчанию, если вы используете динамическое сопоставление для загрузки данных, тогда ES создаст вложенные объекты в виде плоских объектов и, следовательно, потеряет связь между различными вложенными свойствами. Чтобы поддерживать правильные отношения, мы можем использовать вложенные объекты или parent-child.

Теперь я буду использовать вложенные объекты для достижения желаемого результата:

Mapping:

PUT /index-3
{
  "mappings": {
    "products":{
      "properties": {
        "id": {
          "type": "long"
        },
        "name":{
          "type": "string"
        },
        "family_id":{
          "type": "long"
        },
        "collection_id":{
          "type": "long"
        },
        "created_at":{
          "type": "date"
        },
        "updated_at":{
          "type": "date"
        },
        "benefits":{
          "type": "nested",
          "include_in_parent": true,
          "properties": {
            "id": {
              "type": "long"
            },
            "name":{
              "type":"string"
            }
          }
        },
        "categories":{
          "type": "nested",
          "include_in_parent": true,
          "properties": {
            "id":{
              "type": "long"
            },
            "name":{
              "type":"string"
            }
          }
        }
      }
    }
  }
}

Если вы наблюдаете, я рассматривал дочерние объекты как вложенное сопоставление и включал в родительский элемент.

Теперь некоторые примеры данных:

PUT /index-3/products/4
{
  "name":"product name 4",
  "family_id":15,
  "collection_id":6,
  "created_at":"2015-04-13T12:49:42.000Z",
  "updated_at":"2015-04-13T12:49:42.000Z",
  "benefits":[
    {"id":2,"name":"my benefit 2"},
    {"id":6,"name":"my benefit 6"},
    {"id":7,"name":"my benefit 7"}
  ],
  "categories":[
    {"id":2,"name":"category 2"}
  ]
}
PUT /index-3/products/5
{
  "name":"product name 5",
  "family_id":16,
  "collection_id":6,
  "created_at":"2015-04-13T12:49:42.000Z",
  "updated_at":"2015-04-13T12:49:42.000Z",
  "benefits":[
    {"id":5,"name":"my benefit 2"},
    {"id":6,"name":"my benefit 6"},
    {"id":7,"name":"my benefit 7"}
  ],
  "categories":[
    {"id":3,"name":"category 2"}
  ]
}
PUT /index-3/products/6
{
  "name":"product name 6",
  "family_id":15,
  "collection_id":5,
  "created_at":"2015-04-13T12:49:42.000Z",
  "updated_at":"2015-04-13T12:49:42.000Z",
  "benefits":[
    {"id":5,"name":"my benefit 2"},
    {"id":55,"name":"my benefit 6"},
    {"id":7,"name":"my benefit 7"}
  ],
  "categories":[
    {"id":3,"name":"category 2"}
  ]
}

И теперь часть запроса:

GET index-3/products/_search
{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "terms": {
          "benefits.id": [
            5,6,7
          ],
          "execution": "and"
        }
      }
    }
  }
}

Что дает следующий результат:

{
   "took": 1,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "index-3",
            "_type": "products",
            "_id": "5",
            "_score": 1,
            "_source": {
               "name": "product name 5",
               "family_id": 16,
               "collection_id": 6,
               "created_at": "2015-04-13T12:49:42.000Z",
               "updated_at": "2015-04-13T12:49:42.000Z",
               "benefits": [
                  {
                     "id": 5,
                     "name": "my benefit 2"
                  },
                  {
                     "id": 6,
                     "name": "my benefit 6"
                  },
                  {
                     "id": 7,
                     "name": "my benefit 7"
                  }
               ],
               "categories": [
                  {
                     "id": 3,
                     "name": "category 2"
                  }
               ]
            }
         }
      ]
   }
}

Во время запроса мы должны использовать фильтр терминов с "и исполнением", чтобы он получал только документы со всеми условиями.