1

我想确保我以正确的方式思考这个问题。我正在尝试使用 Elasticsearch 自动完成嵌套项目。我有一个列表,一个列表有很多项目。我想使用 ES 返回匹配的项目名称,如果它们存在于当前列表中,则通过传递列表名称和项目名称以在 Elasticsearch 中搜索,对它们进行更强烈的加权。

理论上我可以简单地单独索引项目并以这种方式搜索它们,但我宁愿通过列表文档搜索它们,以便我可以控制相关性。

我不知道如何返回与放入的内容几乎匹配的项目。这是我的设置...(使用 Elasticsearch-Rails 和 Elasticsearch-Model 的 Rails)

索引映射:

  settings :index => { :number_of_shards => 1  } do
    mapping :dynamic => 'false' do
      indexes :private, :type => 'boolean'
      indexes :name, :type => 'string'
      indexes :slug, :type => 'string'
      indexes :bookmarks_count , :type => 'integer'
      indexes :item_names, :type => 'string'
      indexes :up_count, :type => 'integer'
      indexes :permalink, :type => 'string'
      indexes :sub_text, :type => 'string'
      indexes :title_text, :type => 'string'
      indexes :creator_name, :type => 'string'
      indexes :creator_avatar, :type => 'string'
      indexes :cover_image, :type => 'string'
      indexes :items, :type => "nested" do
        indexes :name
        indexes :description
        indexes :image_url
        indexes :link
      end
    end
  end

JSON:

  def as_indexed_json(options = {})
    as_json(:include => [:items, :tags],
            :methods => [:permalink, :sub_text, :title_text, :icon_url, :item_names, :creator_name, :creator_avatar, :cover_image]
            )
  end

这是我调用的搜索方法:

  def item_typeahead_search(list_name, search_query, page = 1, per = 5)
     wildcarded_query = "*#{search_query}*"
     ::List.search(item_typeahead_querystring(list_name, wildcarded_query)).per(per).page(page)
   end

  def item_typeahead_querystring(list_name, query_string)
    {
       :query => {
         :bool => {
           :should => [
             { :match => { :name => list_name }},
             {
               :nested => {
                 :path => "items",
                 :score_mode => "max", 
                 :query => {
                   :bool => {
                     :must => [
                       { :match => { "items.name" => query_string }}
                     ]
             }}}}
           ]
     }}}
  end

这是一个示例查询...

results = List.item_typeahead_search("try me", "crazy glue")

这是结果...

=> #<Elasticsearch::Model::Response::Result:0x007fb8f25c5208
 @result=
  {"_index"=>"lists",
   "_type"=>"list",
   "_id"=>"54504855f29a589a2700003b",
   "_score"=>8.652843,
   "_source"=>
    {"_id"=>"54504855f29a589a2700003b",
     "bookmarks_count"=>0,
     "carousel"=>nil,
     "cid"=>"5j18j8aor",
     "content_source_name"=>nil,
     "content_source_url"=>nil,
     "created_at"=>"2014-10-29T01:52:21Z",
     "description"=>nil,
     "down_count"=>0,
     "down_voters"=>[],
     "intralist_id"=>"545057f7692a270e03000266",
     "items"=>
      [{"_id"=>"545048d5f29a589a27000044",
        "created_at"=>"2014-10-29T01:54:29Z",
        "description"=>nil,
        "down_count"=>0,
        "down_voters"=>[],
        "image_small_url"=>nil,
        "image_thumb_url"=>nil,
        "image_url"=>nil,
        "link"=>nil,
        "name"=>"a swiss army knife",
        "order"=>nil,
        "picture"=>nil,
        "up_count"=>0,
        "up_voters"=>[],
        "updated_at"=>"2014-10-29T01:54:29Z",
        "vote_count"=>0},
       {"_id"=>"545048d5f29a589a27000045",
        "created_at"=>"2014-10-29T01:54:29Z",
        "description"=>nil,
        "down_count"=>0,
        "down_voters"=>[],
        "image_small_url"=>nil,
        "image_thumb_url"=>nil,
        "image_url"=>nil,
        "link"=>nil,
        "name"=>"duct tape",
        "order"=>nil,
        "picture"=>nil,
        "up_count"=>0,
        "up_voters"=>[],
        "updated_at"=>"2014-10-29T01:54:29Z",
        "vote_count"=>0},
       {"_id"=>"545048d5f29a589a27000046",
        "created_at"=>"2014-10-29T01:54:29Z",
        "description"=>nil,
        "down_count"=>0,
        "down_voters"=>[],
        "image_small_url"=>nil,
        "image_thumb_url"=>nil,
        "image_url"=>nil,
        "link"=>nil,
        "name"=>"Crazy glue",
        "order"=>nil,
        "picture"=>nil,
        "up_count"=>0,
        "up_voters"=>[],
        "updated_at"=>"2014-10-29T01:54:29Z",
        "vote_count"=>0},
       {"_id"=>"545048d5f29a589a27000047",
        "created_at"=>"2014-10-29T01:54:29Z",
        "description"=>nil,
        "down_count"=>0,
        "down_voters"=>[],
        "image_small_url"=>nil,
        "image_thumb_url"=>nil,
        "image_url"=>nil,
        "link"=>nil,
        "name"=>"a nut",
        "order"=>nil,
        "picture"=>nil,
        "up_count"=>0,
        "up_voters"=>[],
        "updated_at"=>"2014-10-29T01:54:29Z",
        "vote_count"=>0}],
     "name"=>"try me",
     "parent_list_creator"=>nil,
     "parent_list_id"=>nil,
     "private"=>false,
     "promoted"=>false,
     "slug"=>"things-for-fixing-anything",
     "up_count"=>0,
     "up_voters"=>[],
     "updated_at"=>"2014-10-29T02:59:03Z",
     "user_id"=>"543809c4b64c402d6a000003",
     "vote_count"=>0,
     "permalink"=>"/lists/things-for-fixing-anything",
     "sub_text"=>"List - created by: CreepyTimes",
     "title_text"=>"try me",
     "icon_url"=>"",
     "item_names"=>"a swiss army knife duct tape Crazy glue a nut",
     "creator_name"=>"CreepyTimes",
     "creator_avatar"=>"https://blahblah.com/uploads/profile/image/543809c4b64c402d6a000004/thumb__old_",
     "cover_image"=>nil,
     "tags"=>[]}}>

因此,我将“疯狂的胶水”视为列表中的一个项目,但它是众多项目之一 - 当有人开始输入项目名称时,我可以在这里开箱即用地用于自动完成目的

有没有办法使用嵌套查询、过滤器或其他东西来做我想做的事情?对 Elasticsearch 来说相对较新,所以我可以在最终解决方案上使用一些帮助。如果我没有以正确的方式考虑这一点而应该简单地索引项目,我也可以这样做,但只是好奇是否有办法使这项工作!

编辑 - 这是进入 Elasticsearch 的查询:

  #<Elasticsearch::Model::Searching::SearchRequest:0x007fc555032218
   @definition=
    {:index=>"lists",
     :type=>"list",
     :body=>
      {:query=>
        {:bool=>
          {:should=>
            [{:match=>{:name=>"try me"}},
             {:nested=>{:path=>"items", :score_mode=>"max", :query=>{:bool=>{:must=>[{:match=>{"items.name"=>"*crazy glue*"}}]}}}}]}}},
     :size=>5,
     :from=>0},
   @klass=[PROXY] List,
   @options={}>>
4

0 回答 0