2014-04-02 98 views
11

我的过滤器分组在一起分类。 我想检索文档,其中文档可以匹配任何类别中的任何筛选器,但如果设置了两个(或更多)类别,则文档必须与所有类别中的任何筛选器匹配。如何在ElasticSearch中嵌套AND和OR过滤器?

如果用伪SQL将是:

SELECT * FROM Documents WHERE (CategoryA = 'A') AND (CategoryB = 'B' OR CategoryB = 'C') 

我已经试过像这样的嵌套过滤器:

{ 
    "sort": [{ 
     "orderDate": "desc" 
    }], 
    "size": 25, 
    "query": { 
     "match_all": {} 
    }, 
    "filter": { 
     "and": [{ 
      "nested": { 
       "path":"hits._source", 
       "filter": { 
        "or": [{ 
         "term": { 
          "progress": "incomplete" 
         } 
        }, { 
         "term": { 
          "progress": "completed" 
         } 
        }] 
       } 
      } 
     }, { 
      "nested": { 
       "path":"hits._source", 
       "filter": { 
        "or": [{ 
         "term": { 
          "paid": "yes" 
         } 
        }, { 
         "term": { 
          "paid": "no" 
         } 
        }] 
       } 
      } 
     }] 
    } 
} 

但显然我不太明白ES语法。这是正确的轨道还是我需要使用另一个过滤器?

+0

没有答案过滤这个问题:''或''''term''可以通过[terms]更容易完成(http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-terms- filter.html)。而[bool](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-bool-filter.html)的默认值是''和''。 “filter.bool.must:[{terms:progress:[”incomplete“,”complete“]}}。 {terms:paid:[“yes”,“no”]}]''可能会工作吗? – cfrick

+0

嵌套查询/过滤器用于数组/列表(取决于您熟悉的语言,例如'a = [{'b':1},{'c':2}])''。你能写一个你的文件的例子吗?这将有助于 – Diolor

+0

cfrick带领我走上正确的道路。我在“和”过滤器中嵌入了一堆“条款”过滤器,它似乎满足我的需求。 – MHTri

回答

3

虽然我还没有完全理解你的结构,这可能是你需要的。

你必须树思考。你必须创建一个布尔(=和)完成嵌入布尔。每个嵌入检查该字段是否不存在,否则(在此使用而不是必须)该字段必须(此处的术语)是列表中的值之一。

不知道是否有更好的方法,不知道性能。

{ 
    "sort": [ 
     { 
      "orderDate": "desc" 
     } 
    ], 
    "size": 25, 
    "query": { 
     "query": {   # 
      "match_all": {} # These three lines are not necessary 
     },     # 
     "filtered": { 
      "filter": { 
       "bool": { 
        "must": [ 
         { 
          "bool": { 
           "should": [ 
            { 
             "not": { 
              "exists": { 
               "field": "progress" 
              } 
             } 
            }, 
            { 
             "terms": { 
              "progress": [ 
               "incomplete", 
               "complete" 
              ] 
             } 
            } 
           ] 
          } 
         }, 
         { 
          "bool": { 
           "should": [ 
            { 
             "not": { 
              "exists": { 
               "field": "paid" 
              } 
             } 
            }, 
            { 
             "terms": { 
              "paid": [ 
               "yes", 
               "no" 
              ] 
             } 
            } 
           ] 
          } 
         } 
        ] 
       } 
      } 
     } 
    } 
} 
+2

这是不正确的。 “必须”和“应该”不是''和'和'或'的别名。他们有不同的功能(虽然概念上有相似之处) –

8

这应该是它(从给出的伪SQL翻译)

{ 
    "sort": [ 
     { 
     "orderDate": "desc" 
     } 
    ], 
    "size": 25, 
    "query": 
    { 
     "filtered": 
     { 
      "filter": 
      { 
       "and": 
       [ 
        { "term": { "CategoryA":"A" } }, 
        { 
         "or": 
         [ 
          { "term": { "CategoryB":"B" } }, 
          { "term": { "CategoryB":"C" } } 
         ] 
        } 
       ] 
      } 
     } 
    } 
} 

我知道你不提,但面只是为了完整起见:

您也可以使用一个filter作为基础(像你一样)而不是filtered query(就像我做的那样)。将得到的JSON是,不同之处几乎相同:

  • 一个过滤查询将过滤两者的主要结果以及面
  • 一个过滤器将只过滤NOT主要结果的刻面。

最后,嵌套过滤器(您尝试使用),不涉及“嵌套过滤器”像你似乎相信,但涉及到对嵌套的文档(亲子)