如何在ElasticSearch中执行嵌套的AND和OR过滤器?

MHT*_*Tri 14 elasticsearch

我的过滤器按类别分组.我想检索文档可以匹配类别中的任何过滤器的文档,但如果设置了两个(或更多)类别,则文档必须匹配所有类别中的任何过滤器.

如果用伪SQL编写,它将是:

SELECT * FROM Documents WHERE (CategoryA = 'A') AND (CategoryB = 'B' OR CategoryB = 'C')
Run Code Online (Sandbox Code Playgroud)

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

{
    "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"
                        }
                    }]
                }
            }
        }]
    }
}
Run Code Online (Sandbox Code Playgroud)

但显然我不太了解ES语法.这是在正确的轨道上还是我需要使用另一个过滤器?

Gee*_*Jan 10

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

{
   "sort": [
      {
        "orderDate": "desc"
      }
    ],
    "size": 25,
    "query":
    {
        "filtered":
        {
            "filter":
            {
                "and":
                [
                    { "term": { "CategoryA":"A" } },
                    {
                        "or":
                        [
                            { "term": { "CategoryB":"B" } },
                            { "term": { "CategoryB":"C" } }
                        ]
                    }
                ]
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我意识到你并没有提到方面,只是为了完整起见:

您也可以使用a filter作为基础(就像你一样)而不是filtered query(像我一样).得到的json几乎完全相同,区别在于:

  • 过滤后的查询将过滤主要结果以及构面
  • 过滤器只会过滤主要结果而非过滤面.

最后,嵌套过滤器(您尝试使用)与您似乎相信的"嵌套过滤器"无关,但与嵌套文档(父子)的过滤有关


Dio*_*lor 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"
                                            ]
                                        }
                                    }
                                ]
                            }
                        }
                    ]
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是不正确的。“must”和“should”不是“and”和“or”的别名。它们具有不同的功能(尽管概念上有相似之处) (3认同)