【问题标题】:More like this with elasticsearch-rails and mongoid returns nothing更像这样的 elasticsearch-rails 和 mongoid 什么都不返回
【发布时间】:2016-02-11 20:54:25
【问题描述】:

我使用 MongoDB 来存储有关鞋子的信息。每只鞋都有一个标题(字符串)、照片(字符串,这是照片的网址)、链接(字符串,原始网站的网址)、尺寸(字符串数组)、颜色(字符串数组)和价格(字符串) 和性别(字符串)。

在我的 project/app/models/shoe.rb 文件中,我有:

class Shoe
  include Mongoid::Document
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks

  field :title
  field :photo
  field :link
  field :price
  field :gender
  field :sizes, type: Array, default: []
  field :colors, type: Array, default: []

  def as_indexed_json
    as_json({only: [:title, :gender, :colors, :price, :sizes]})
  end

  settings index: { number_of_shards: 1 } do
    mappings dynamic: 'false' do
      indexes :title, analyzer: 'bulgarian'
      indexes :colors, analyzer: 'bulgarian'
      indexes :gender, analyzer: 'bulgarian'
    end
  end

  def self.more_like_this(shoe)
    __elasticsearch__.search(
      {
        query: {
          bool: {
              must: {match_all: { }},
              should: [
                # {
                #   more_like_this: {
                #     fields: ['title'],
                #     like: [
                #       {
                #         _index: 'shoes',
                #         _type: 'shoe',
                #         _id: shoe.id
                #       }
                #     ],
                #     boost: 2.0
                #   }
                # },
                {
                  more_like_this: {
                    fields: ['gender'],
                    like: [
                      {
                        _index: 'shoes',
                        _type: 'shoe',
                        _id: shoe.id
                      }
                    ],
                  }
                }
              ],
              minimum_should_match: 1
          }
        }
      }
    )
  end
end

# Delete the previous shoes index in Elasticsearch
Shoe.__elasticsearch__.client.indices.delete index: Shoe.index_name rescue nil

# Create the new index with the new mapping
Shoe.__elasticsearch__.client.indices.create \
  index: Shoe.index_name,
  body: { settings: Shoe.settings.to_hash, mappings: Shoe.mappings.to_hash }

# Index all shoe records from the DB to Elasticsearch
Shoe.import

在 project/config/initializers/elasticsearch.rb 我有:

config = {
  host: "http://localhost:9200/",
  transport_options: {
    request: { timeout: 5 }
  },
}

if File.exists?("config/elasticsearch.yml")
  config.merge!(YAML.load_file("config/elasticsearch.yml").symbolize_keys)
end

Elasticsearch::Model.client = Elasticsearch::Client.new(config)

unless Shoe.__elasticsearch__.index_exists?
  Shoe.__elasticsearch__.create_index! force: true
  Shoe.import
end

在 project/config/mongoid.yml 我有:

    development:
      # Configure available database clients. (required)
      clients:
        # Defines the default client. (required)
        default:
          # Defines the name of the default database that Mongoid can connect to.
          # (required).
          database: cornersport
          # Provides the hosts the default client can connect to. Must be an array
          # of host:port pairs. (required)
          hosts:
            - localhost:27017
    test:
      clients:
        default:
          database: calceus_test
          hosts:
            - localhost:27017
          options:
            read:
              mode: :primary
            max_pool_size: 1

现在,在运行 elasticsearch 的 Rails 控制台中,我调用了Shoe.more_like_this(some_shoe_object).results.to_a,它返回了[]。首先,我的查询包括注释部分,但是当我没有得到任何结果时,我将其注释掉,尽管数据库中有更多与some_shoe_object 相同性别的记录,但我仍然没有得到任何结果。它不应该返回一些东西吗?我使用弹性搜索错了吗?我是初学者。请帮忙!

【问题讨论】:

    标签: ruby-on-rails elasticsearch morelikethis elasticsearch-rails


    【解决方案1】:

    看起来您的索引是通过初始化文件elasticsearch.rb 创建的,而您还没有指定设置。

    尝试将初始化文件更改为

    config = {
      host: "http://localhost:9200/",
      transport_options: {
        request: { timeout: 5 }
      },
    }
    
    if File.exists?("config/elasticsearch.yml")
      config.merge!(YAML.load_file("config/elasticsearch.yml").symbolize_keys)
    end
    
    Elasticsearch::Model.client = Elasticsearch::Client.new(config)
    
    unless Shoe.__elasticsearch__.index_exists?
      Shoe.__elasticsearch__.client.indices.create index: Shoe.index_name,
       body: { settings: Shoe.settings.to_hash, mappings: Shoe.mappings.to_hash }
      Shoe.import
    end
    

    同样从您的shoe.rb 文件中,最后删除索引创建/删除部分

    # Delete the previous shoes index in Elasticsearch
    Shoe.__elasticsearch__.client.indices.delete index: Shoe.index_name rescue nil
    
    # Create the new index with the new mapping
    Shoe.__elasticsearch__.client.indices.create \
      index: Shoe.index_name,
      body: { settings: Shoe.settings.to_hash, mappings: Shoe.mappings.to_hash }
    
    # Index all shoe records from the DB to Elasticsearch
    Shoe.import
    

    重启你的服务器,ES再试一次!


    更新

    尝试像这样更改您的 more_like_it 子句:

    more_like_this: {
      fields: ['gender'],
        like: [
          {
            _index: 'cornersport',
            _type: 'shoes',
            _id: shoe.id
           },
           shoe.gender
         ]
    }
    

    【讨论】:

    • 我按照你说的做了,仍然得到空数组。
    • 你能换一种方式试试吗,即从initializer/elasticsearch.rb中删除这段创建代码,然后在model中执行?
    • 我将initializer/elasticsearch.rb 代码移至model,但仍然没有任何内容。我想我有某种索引,因为当我删除 unless Shoe.__elasticsearch__.index_exists? 时,它说索引已经存在。而且我认为这个现有索引不会被重新创建。
    • 最好通过head插件或sense手动删除elasticsearch索引,并删除所有别名,然后重试。
    • 问题出在 should 子句中,因为当我删除它时,它会返回所有记录
    【解决方案2】:

    我是这样编辑的:

    def self.more_like_this(shoe)
      __elasticsearch__.search(
        {
          query: {
            bool: {
                must: {match_all: { }},
                should: [
                  {
                    more_like_this: {
                      fields: ['gender'],
                      docs: [
                        {
                          _index: 'shoes',
                          _type: 'shoe',
                          _id: shoe.id
                        }
                      ],
                      ids: [shoe.id]
                    }
                  }
                ],
                minimum_should_match: 1
            }
          }
        }
      )
    end
    

    现在效果很好。只需将like 替换为docs 并添加ids 就像这里解释的那样:https://www.elastic.co/guide/en/elasticsearch/reference/1.4/query-dsl-mlt-query.html 到目前为止,我一直在努力让它按照这里的解释工作: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html

    我正在使用 elasticsearch-2.2.0,所以我不明白 2.2.0 的功能如何不适用于我,而是 1.4 的功能。也许 elasticsearch-rails 适用于 1.4。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-24
      • 1970-01-01
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多