技术库 > Java

Elasticsearch 组合过滤器

技术库:tec.5lulu.com

在实际应用中,我们很有可能会过滤多个值或字段。比方说,怎样用 Elasticsearch 来表达下面的 SQL ?
SELECT product
FROM   products
WHERE  (price = 20 OR productID = "XHDK-A-1293-#fJ3")
  AND  (price != 30)

from:tec.5lulu.com

这种情况下,我们需要bool(布尔)过滤器。 这是个 复合过滤器(compound filter) ,它可以接受多个其他过滤器作为参数,并将这些过滤器结合成各式各样的布尔(逻辑)组合。

1 布尔过滤器

一个bool过滤器由三部分组成:

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
   }
}


must所有的语句都 必须(must) 匹配,与AND等价。 must_not所有的语句都 不能(must not) 匹配,与NOT等价。 should至少有一个语句要匹配,与OR等价。

就这么简单! 当我们需要多个过滤器时,只须将它们置入bool过滤器的不同部分即可。

一个bool过滤器的每个部分都是可选的(例如,我们可以只有一个must语句),而且每个部分内部可以只有一个或一组过滤器。

Elasticsearch 来表示本部分开始处的 SQL 例子,将两个term过滤器置入bool过滤器的should语句内,再增加一个语句处理NOT非的条件:

GET /my_store/products/_search
{
   "query" : {
      "filtered" : {①
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, ②
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} ③
              ],
              "must_not" : {
                 "term" : {"price" : 30} ④ 
              }
           }
         }
      }
   }
}


注意,我们仍然需要一个filtered查询将所有的东西包起来。

在should语句块里面的两个term过滤器与bool过滤器是父子关系,两个term条件需要匹配其一。

如果一个产品的价格是30,那么它会自动被排除,因为它处于must_not语句里面。

我们搜索的结果返回了 2 个命中结果,两个文档分别匹配了bool过滤器其中的一个条件:

"hits" : [
    {
        "_id" :     "1",
        "_score" :  1.0,
        "_source" : {
          "price" :     10,
          "productID" : "XHDK-A-1293-#fJ3" ①
        }
    },
    {
        "_id" :     "2",
        "_score" :  1.0,
        "_source" : {
          "price" :     20, ②
          "productID" : "KDKE-B-9947-#kL5"
        }
    }
]


与term过滤器中productID = "XHDK-A-1293-#fJ3"条件匹配

与term过滤器中price = 20条件匹配

2 嵌套布尔过滤器

尽管bool是一个复合的过滤器,可以接受多个子过滤器,需要注意的是bool过滤器本身仍然还只是一个过滤器。 这意味着我们可以将一个bool过滤器置于其他bool过滤器内部,这为我们提供了对任意复杂布尔逻辑进行处理的能力。

对于以下这个 SQL 语句:

SELECT document
FROM   products
WHERE  productID      = "KDKE-B-9947-#kL5"
  OR (     productID = "JODL-X-1937-#pV7"
       AND price     = 30 )
我们将其转换成一组嵌套的bool过滤器:
GET /my_store/products/_search
{
   "query" : {
      "filtered" : {
         "filter" : {
            "bool" : {
              "should" : [
                { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, ①
                { "bool" : { ②
                  "must" : [
                    { "term" : {"productID" : "JODL-X-1937-#pV7"}}, ③
                    { "term" : {"price" : 30}} ④
                  ]
                }}
              ]
           }
         }
      }
   }
} 


因为term和bool过滤器是兄弟关系,他们都处于外层的布尔逻辑should的内部,返回的命中文档至少须匹配其中一个过滤器的条件。

这两个term语句作为兄弟关系,同时处于must语句之中,所以返回的命中文档要必须都能同时匹配这两个条件。

得到的结果有两个文档,它们各匹配should语句中的一个条件:

"hits" : [
    {
        "_id" :     "2",
        "_score" :  1.0,
        "_source" : {
          "price" :     20,
          "productID" : "KDKE-B-9947-#kL5" ①
        }
    },
    {
        "_id" :     "3",
        "_score" :  1.0,
        "_source" : {
          "price" :      30, ②
          "productID" : "JODL-X-1937-#pV7" ③
        }
    }
]


这个productID与外层的bool过滤器should里的唯一一个term匹配。

这两个字段与嵌套的bool过滤器must里的两个term匹配。

这只是个简单的例子,但足以展示布尔过滤器可以用来作为构造复杂逻辑条件的基本构建模块。

Elasticsearch 组合过滤器


标签: 搜索 语句块 组合 hits sql本文链接 http://tec.5lulu.com/detail/110drn2ehyg0c85f8.html

我来评分 :6.1
0

转载注明:转自5lulu技术库

本站遵循:署名-非商业性使用-禁止演绎 3.0 共享协议

www.5lulu.com