es-进阶-深入搜索

1.结构化搜索

结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程。比如日期、时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作。比较常见的操作包括比较数字或时间的范围,或判定两个值的大小。

文本也可以是结构化的。如彩色笔可以有离散的颜色集合: 红(red) 、 绿(green) 、 蓝(blue) 。一个博客可能被标记了关键词 分布式(distributed) 和 搜索(search) 。电商网站上的商品都有 UPCs(通用产品码 Universal Product Codes)或其他的唯一标识,它们都需要遵从严格规定的、结构化的格式。

在结构化查询中,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。

这在逻辑上是能说通的,因为一个数字不能比其他数字 适合存于某个相同范围。结果只能是:存于范围之中,抑或反之。同样,对于结构化文本来说,一个值要么相等,要么不等。没有 更似 这种概念。

a.精确值查找

我们首先来看最为常用的 term 查询, 可以用它处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。

//使用filter查询,不需要评分机制:constant_score,指定固定的分数:boost

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "term": {

         "price": 20

       }

     },

     "boost": 1.2

   }

 }

}

term 查询文本

如本部分开始处提到过的一样 ,使用 term 查询匹配字符串和匹配数字一样容易

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "term": {

         "product_id": "b"

       }

     },

     "boost": 1.2

   }

 }

}

b.组合过滤器

布尔过滤器

  • must 文档必须匹配这些条件才能被包含进来.
  • must_not文档必须不匹配这些条件才能被包含进来.
  • should当文档满足此条件时,会增加其_score值,类似于or语句
  • filter 必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

//不参与计分的bool

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "bool": {

         "should":[

           {"term":{"price":20}},

           {"term":{"product_id":"c"}}

           ],

           "must_not":{

             "term":{"price" : 30}

           }

       }

     },

     "boost": 1.2

   }

 }

}

//部分参与计分的bool

GET products/_search

{

 "query": {

       "bool": {

         "filter": [

           {"term": {

             "product_id": {

               "value": "d"

             }

           }}

         ],

         "should":[

           {"term":{"price":20}},

           {"term":{"product_id":"c"}}

           ],

           "must_not":{

             "term":{"price" : 30}

           }

       }

 }

}

//全部参与计分

//部分参与计分的bool

GET products/_search

{

 "query": {

       "bool": {

         "must": [

           {"term": {

             "product_id": {

               "value": "d"

             }

           }}

         ],

         "should":[

           {"term":{"price":20}},

           {"term":{"product_id":"c"}}

           ],

           "must_not":{

             "term":{"price" : 30}

           }

       }

 }

}

嵌套布尔过滤器

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

GET products/_search

{

 "query": {

       "bool": {

         "filter": [

           {"term": {

             "product_id": {

               "value": "b"

             }

           }},

           {

             "bool":{

               "should":[

           {"term":{"price":20}},

           {"term":{"product_id":"c"}}

           ]

             }

           }

         ],

           "must_not":{

             "term":{"price" : 30}

           }

       }

 }

}

c.查找多个精确值

term 和 terms 是 包含(contains) 操作,而非 等值(equals) (判断)

//同一个字段查询多个值

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "terms": {

         "product_id": ["a","b"]

       }

     },

     "boost": 1.2

   }

 }

}

d.范围

range 查询可同时提供包含(inclusive)和不包含(exclusive)这两种范围表达式,可供组合的选项如下:

  • gt: > 大于(greater than)
  • lt: < 小于(less than)
  • gte: >= 大于或等于(greater than or equal to)
  • lte: <= 小于或等于(less than or equal to)

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "range": {

         "price": {

           "gte":30,

           "lte": 40

         }

       }

     },

     "boost": 1.2

   }

 }

}

日期范围

当使用它处理日期字段时, range 查询支持对 日期计算(date math) 进行操作,比方说,如果我们想查找时间戳在过去一小时内的所有文档:

"range" : {

    "timestamp" : {

        "gt" : "now-1h"

    }

}

这个过滤器会一直查找时间戳在过去一个小时内的所有文档,让过滤器作为一个时间 滑动窗口(sliding window) 来过滤文档。

日期计算还可以被应用到某个具体的时间,并非只能是一个像 now 这样的占位符。只要在某个日期后加上一个双管符号 (||) 并紧跟一个日期数学表达式就能做到:

"range" : {

    "timestamp" : {

        "gt" : "2014-01-01 00:00:00",

        "lt" : "2014-01-01 00:00:00||+1M"

    }

}

早于 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零时)

日期计算是 日历相关(calendar aware) 的,所以它不仅知道每月的具体天数,还知道某年的总天数(闰年)等信息。更详细的内容可以参考: 时间格式参考文档

字符串范围

range 查询同样可以处理字符串字段,字符串范围可采用 字典顺序(lexicographically) 或字母顺序(alphabetically)。例如,下面这些字符串是采用字典序(lexicographically)排序的:

  • 5, 50, 6, B, C, a, ab, abb, abc, b

在倒排索引中的词项就是采取字典顺序(lexicographically)排列的,这也是字符串范围可以使用这个顺序来确定的原因。

注意基数

数字和日期字段的索引方式使高效地范围计算成为可能。但字符串却并非如此,要想对其使用范围过滤,Elasticsearch 实际上是在为范围内的每个词项都执行 term 过滤器,这会比日期或数字的范围过滤慢许多。

字符串范围在过滤 低基数(low cardinality) 字段(即只有少量唯一词项)时可以正常工作,但是唯一词项越多,字符串范围的计算会越慢。

e.处理null值

最终,这也就意味着,null[] (空数组)和 [null] 所有这些都是等价的,它们无法存于倒排索引中

在 Elasticsearch 中,使用 exists 查询的方式 进行判断null

//获取字段product_id中有值的文档

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "exists": {

         "field": "product_id"

       }

     },

     "boost": 1.2

   }

 }

}

缺失查询

这个 missing 查询本质上与 exists 恰好相反:它返回某个特定 值字段的文档(最新版本已经不使用这个关键字)

//查询缺少字段product_id的文档

GET products/_search

{

 "query": {

   "constant_score": {

     "filter": {

       "bool": {

         "must_not":{

           "exists":{

             "field":"product_id"

           }

         }

       }

     },

     "boost": 1.2

   }

 }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值