【问题标题】:Elasticsearch doesn't apply the NOT filterElasticsearch 不应用 NOT 过滤器
【发布时间】:2013-08-28 16:06:37
【问题描述】:

我今天一直在用 Elasticsearch 撞墙,试图修复失败的测试用例。

我正在使用 Rails 3.2.14、Ruby 1.9.3、Tire gem 和 ElasticSearch 0.90.2

目标是让查询返回匹配结果排除其中的项目 vid == "ABC123xyz"

Video 模型中的 Ruby 代码如下所示:

def related_videos(count)
  Video.search load: true do
    size(count)
    filter :term, :category_id => self.category_id
    filter :term, :live => true
    filter :term, :public => true
    filter :not, {:term => {:vid => self.vid}}
    query do
      boolean do
        should { text(:_all, self.title, boost: 2) }
        should { text(:_all, self.description) }
        should { terms(:tags, self.tag_list, minimum_match: 1) }
      end  
   end
  end
end

Tire 生成的搜索查询结果如下所示:

{
  "query":{
    "bool":{
      "should":[
        {
          "text":{
            "_all":{
              "query":"Top Gun","boost":2
            }
          }
        },
        {
          "text":{
            "_all":{
              "query":"The macho students of an elite US Flying school for advanced fighter pilots compete to be best in the class, and one romances the teacher."
            }
          }
        },
        {
          "terms":{
            "tags":["top-gun","80s"],
            "minimum_match":1
          }
        }
      ]
    }
  },
  "filter":{
    "and":[
      {
        "term":{
          "category_id":1
        }
      },
      {
        "term":{
          "live":true
        }
      },
      {
        "term":{
          "public":true
        }
      },
      {
        "not":{
          "term":{
            "vid":"ABC123xyz"
          }
        }
      }
    ]
  },
  "size":10
}

来自 ElasticSearch 的结果 JSON:

{
  "took": 7,
  "timed_out": false,
  "_shards":{
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total":1,
    "max_score":0.2667512,
    "hits":[
      {
        "_index":"test_videos",
        "_type":"video",
        "_id":"8",
        "_score":0.2667512,
        "_source":{
          "vid":"ABC123xyz",
          "title":"Top Gun",
          "description":"The macho students of an elite US Flying school for advanced fighter pilots compete to be best in the class, and one romances the teacher.",
          "tags":["top-gun","80s"],
          "category_id":1,
          "live":true,
          "public":true,
          "featured":false,
          "last_video_view_count":0,
          "boost_factor":0.583013698630137,
          "created_at":"2013-08-28T14:24:47Z"
        }
      }
    ]
  }
}

有人可以帮忙吗! Elasticsearch 的文档围绕这个主题很少,我的想法已经不多了。

谢谢

【问题讨论】:

    标签: ruby-on-rails ruby elasticsearch tire


    【解决方案1】:

    按照您的方式使用顶级过滤器不会过滤查询结果 - 它只是过滤掉诸如方面计数之类的结果。在elasticsearch documentation for filter中有更完整的描述。

    您需要做一个稍有不同的filtered query 并过滤查询子句的结果:

    Video.search load: true do
      query do
        filtered do
          boolean do
            should { text(:_all, self.title, boost: 2) }
            should { text(:_all, self.description) }
            should { terms(:tags, self.tag_list, minimum_match: 1) }
          end  
          filter :term, :category_id => self.category_id
          filter :term, :live => true
          filter :term, :public => true
          filter :not, {:term => {:vid => self.vid}}
        end
      end
    end
    

    【讨论】:

    • 嗨,我试过了,但不幸的是,Tire gem 似乎不支持这个。布尔块未在 FilteredQuery 对象中实现:github.com/karmi/tire/blob/…
    • 在布尔块中使用“must_not”选项可能更容易吗?这确实有效,但我想知道它是否会降低性能?
    • 我必须承认我没有尝试特定查询 - 它更多地表明过滤器必须位于过滤后的查询中,而不是位于顶层。
    猜你喜欢
    • 1970-01-01
    • 2019-04-09
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多