ElasticSearch之结构化搜索

ElasticSearch结构化搜索是指查询包含内部结构的数据。
日期、时间、数字都是格式化的,它们有明确的格式给你执行逻辑操作。
通过结构化搜索,查询结果始终是“是与非”,是否应该属于集合。结构化搜索不关心文档的相关性或者分数,仅仅是简单的包含或者排除。

查找准确值

对于准确值,需要使用过滤器。
过滤器很快,不计算相关性而且容易被缓存。

term过滤器

term过滤器旨在处理数字、布尔值、日期和文本。
term过滤器很简单,接收一个字段名和希望查找的值。
term过滤器本身并不能起作用,搜索API需要得到一个查询语句,而不是一个过滤器。为了使用term过滤器,需要将它包含在一个过滤查询语句中。
过滤器不会执行计分和计算相关性,分值由match_all查询产生。
内部过滤操作
查找匹配文档;
创建字节集(由1和0组成的数组,描述那些文档包含这个词);
缓存字节集(字节集被储存在内存中,从而可以跳过上面的步骤执行过滤)。
当执行filtered查询时,filter会比query早执行,结果字节集被传给query来跳过已经被排除的文档。这就是过滤器提升性能的方式,查询更少的文档从而获得更快的速度。

组合过滤(bool过滤器)

bool过滤器包括三个操作符:must,must_not,should。
bool过滤器的三个操作符都是可选的,而且每个操作符可以包含一个或多个过滤器。

嵌套布尔过滤器

虽然bool过滤器是一个组合过滤器,可以接收子过滤器,但是它仍然是一个过滤器。这意味着可以在bool过滤器中嵌套bool过滤器。

多个准确值

terms过滤器是term过滤器的复数版本。
terms过滤器用起来和term差不多,参数值指定的是一组数值。
term及terms过滤器是包含操作,而不是相等操作。
倒排索引的特性让完全匹配一个字段变得非常困难。
如果真的需要完全匹配这种行为,最好通过添加另外一个字段来实现。新的字段中,索引原字段包含值的个数。

范围

ElasticSearch中有一个range过滤器,可以根据范围进行过滤。
range过滤器既能包含也能排除范围,通过如下操作符:gt,lt,gte,lte。

日期时间范围

range过滤器用于日期时间字段时,支持日期的数学操作。

// 查找最近一个小时的文档
"range" : {
    "timestamp" : {
        "gt" : "now-1h"
    }
}

日期计算也能用于实际的日期,而不仅仅是一个像now一样的占位符。在日期后加上双竖线||,就能使用日期数学表达式了。
日期计算是与日历相关的,所以它知道每个月的天数,每年的天数等等。

"range" : {
    "timestamp" : {
        "gt" : "2014-01-01 00:00:00",
        "lt" : "2014-01-01 00:00:00||+1M" // 加一个月
    }
}

字符串范围

字符串范围根据字典或者字母顺序来计算。
倒排索引中的短语按照字典顺序排序,这也是为什么字符串范围使用这个顺序。
数字和日期字段的索引方式让它们在计算范围的时候比较高效,但是对于字符串来说却不是这样。为了在字符串商执行范围操作,ES会在这个范围内的每个短语执行term操作,这要比日期或者数字的范围操作慢得多。
字符串的范围查询适用于一个基数比较小的字段,一个唯一短语个数较少的字段。

处理NULL值

如果一个字段没有值,那么它是怎么存储到倒排索引中的?
答案是它根本没有存储。
本质上来说,null,[]空数组和[null]是相等的,都不存在于倒排索引中。

exists过滤器

这个过滤器将返回任何包含这个字段的文档。

"filter" : {
    "exists" : { "field" : "tags" }
}

missing过滤器

missing过滤器本质上是exists的反义词,它返回没有特定字段值的文档。

"filter": {
    "missing" : { "field" : "tags" }
}

exists和missing过滤器同样能在内联对象上工作,而不仅仅是核心类型。

缓存

ElasticSearch缓存的核心是用一个字节集来表示哪些文档符合某个过滤器。ElasticSearch主动缓存了这些字节集留作以后使用。
缓存的字节集会增量更新。在索引中增加了新的文档,新文档符合要求会被添加到已存的字节集中,而不是重新计算整个缓存的过滤器。
过滤器和整个系统的其他部分一样是实时的,不需要关心缓存的过期时间。
每个过滤器都被独立计算和缓存,而不管它们在哪里使用。不同的查询使用相同的过滤器,会使用相同的字节集。
大部分直接处理字段的叶子过滤器会被缓存(如term),而组合过滤器不会被缓存(如bool)。
也有一些叶子过滤器默认不被缓存:

  • 脚本过滤器:不透明;
  • Geo过滤器:基于用户地理位置的结果,不太可能重用;
  • 日期范围:使用now方法的日期范围,一般补充用。

过滤顺序

bool条件中过滤器的顺序对于性能有很大影响。

  • 更详细的过滤条件应该被放置在其它过滤器之前,以便更早排除更多文档。
  • 缓存的过滤器非常快,所以要放在不能被缓存的过滤器之前。

猜你喜欢

转载自blog.csdn.net/achang07/article/details/79723462