2013-08-28 51 views
2

今天我一直在用Elasticsearch敲我的頭,試圖修復一個失敗的測試用例。Elasticsearch不適用NOT過濾器

我使用Rails 3.2.14,紅寶石1.9.3,輪胎的寶石和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 

由輪胎所產生的結果搜索查詢的樣子這樣的:

{ 
    "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 
} 

產生的JSON從ElasticSearch:

{ 
    "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的文檔對這個主題很少見,而且我沒有想法。

感謝

回答

0

使用頂級過濾你的方式不過濾查詢的結果 - 它只是過濾的結果,出來的東西像面計數。 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 
+0

您好,我試過,但不幸的是,它似乎並不像這在輪胎寶石支持。該布爾塊沒有在FilteredQuery對象中實現:https://github.com/karmi/tire/blob/04cce99c2b341eb37f60ff6a11fa459d4c073e12/lib/tire/search/query.rb – wildtangent

+0

可能更容易使用「must_not」選項布爾塊?這確實有用,但我想知道它是否會造成性能下降? – wildtangent

+0

我必須承認我沒有嘗試具體的查詢 - 它更多地表明過濾器必須在過濾後的查詢中而不是在頂層。 – Shadwell