检索结果可以按跟指定点的距离排序:提示当你可以(can)按距离排序时,按距离打分(scoring-by-distance)通常是一个更好的解决方案。
每一个 经纬度(lat/lon)组合需要占用16个字节的内存。要知道内存可是供不应求的。使用这种占用16字节内存的方式可以得到非常精确的结果。不过就像之前提到的一样,实际应用中几乎都不需要这么精确。你可以通过这种方式来减少内存使用量:设置一个压缩的(compressed)数据字段格式并明确指定你的地理坐标点所需的精度。
因为如下两个原因,地理位置过滤器默认是不被缓存的:地理位置过滤器通常是用于查找用户当前位置附近的东西。但是用户是在移动的,并且没有两个用户的位置完全相同,因此缓存的过滤器基本不会被重复使用到。过滤器是被缓存为比特位集合来表示段(segment)内的文档。假如我们的查询排除了几乎所有文档,只剩一个保存在这个特别的段内。
地理距离过滤器(geo_distance)以给定位置为圆心画一个圆,来找出那些位置落在其中的文档:GET /attractions/restaurant/_search{ "query": { "filtered": { "filter": { "geo_distance": { "distance": "1km", <1> "location": { <2> "lat": 40.715, "lon": -73.
这是目前为止最有效的 地理坐标过滤器了,因为它计算起来非常简单。你指定一个矩形的 顶部(top), 底部(bottom), 左边界(left), 和 右边界(right),然后它只需判断坐标的经度是否在左右边界之间,纬度是否在上下边界之间。
有四种地理坐标点相关的过滤方式可以用来选中或者排除文档:geo_bounding_box::找出落在指定矩形框中的坐标点geo_distance::找出与指定位置在给定距离内的点geo_distance_range::找出与指定点距离在给定最小距离和最大距离之间的点geo_polygon::找出落在多边形中的点。这个过滤器使用代价很大。
地理坐标点(geo-point) 是指地球表面可以用经纬度描述的一个点。地理坐标点可以用来计算两个坐标位置间的距离,或者判断一个点是否在一个区域中。地理坐标点不能被动态映射(dynamic mapping)自动检测,而是需要显式声明对应字段类型为 geo_point 。
过滤顺序在 bool 条件中过滤器的顺序对性能有很大的影响。更详细的过滤条件应该被放置在其他过滤器之前,以便在更早的排除更多的文档。假如条件 A 匹配 1000 万个文档,而 B 只匹配 100 个文档,那么需要将 B 放在 A 前面。缓存的过滤器非常快,所以它们需要被放在不能缓存的过滤器之前。
关于缓存在【内部过滤操作】章节中,我们简单提到过过滤器是怎么计算的。它们的核心是一个字节集来表示哪些文档符合这个过滤器。Elasticsearch 主动缓存了这些字节集留作以后使用。一旦缓存后,当遇到相同的过滤时,这些字节集就可以被重用,而不需要重新运算整个过滤。缓存的字节集很“聪明”:他们会增量更新。
处理 Null 值回到我们早期的示例,在文档中有一个多值的字段 tags,一个文档可能包含一个或多个标签,或根本没有标签。如果一个字段没有值,它是怎么储存在倒排索引中的?这是一个取巧的问题,因为答案是它根本没有存储。让我们从看一下前几节的倒排索引:TokenDocIDsopen_source2search1,2你怎么可能储存一个在数据结构不存在的字段呢?
范围我们到现在只搜索过准确的数字,现实中,通过范围来过滤更为有用。例如,你可能希望找到所有价格高于 20 元而低于 40 元的产品。
包含,而不是相等理解 term 和 terms 是_包含_操作,而不是_相等_操作,这点非常重要。这意味着什么?假如你有一个 term 过滤器 { "term" : { "tags" : "search" } },它将匹配下面两个文档:{ "tags" : ["search"] }{ "tags" : ["search", "open_source"] } <1>
查询多个准确值term 过滤器在查询单个值时很好用,但是你可能经常需要搜索多个值。比如你想寻找 20 或 30 元的文档,该怎么做呢?比起使用多个 term 过滤器,你可以用一个 terms 过滤器。terms 过滤器是 term 过滤器的复数版本。
组合过滤前面的两个例子展示了单个过滤器的使用。现实中,你可能需要过滤多个值或字段,例如,想在 Elasticsearch 中表达这句 SQL 吗?SELECT productFROM productsWHERE (price = 20 OR productID = "XHDK-A-1293-#fJ3") AND (price != 30)这些情况下,你需要 bool 过滤器。这是以其他过滤器作为参数的组合过滤器,将它们结合成多种布尔组合。
查找准确值对于准确值,你需要使用过滤器。过滤器的重要性在于它们非常的快。它们不计算相关性(避过所有计分阶段)而且很容易被缓存。我们今后再来讨论过滤器的性能优势【过滤器缓存】,现在,请先记住尽可能多的使用过滤器。用于数字的 term 过滤器我们下面将介绍 term 过滤器,首先因为你可能经常会用到它,这个过滤器旨在处理数字,布尔值,日期,和文本。
结构化搜索结构化搜索 是指查询包含内部结构的数据。日期,时间,和数字都是结构化的:它们有明确的格式给你执行逻辑操作。一般包括比较数字或日期的范围,或确定两个值哪个大。文本也可以被结构化。一包蜡笔有不同的颜色:红色,绿色,蓝色。一篇博客可能被打上 分布式 和 搜索的标签。电子商务产品有商品统一代码(UPCs) 或其他有着严格格式的标识。
通过每秒自动刷新创建新的段,用不了多久段的数量就爆炸了。有太多的段是一个问题。每个段消费文件句柄,内存,cpu资源。更重要的是,每次搜索请求都需要依次检查每个段。段越多,查询越慢。ES通过后台合并段解决这个问题。小段被合并成大段,再合并成更大的段。这是旧的文档从文件系统删除的时候。旧的段不会再复制到更大的新段中。这个过程你不必做什么。
没用fsync同步文件系统缓存到磁盘,我们不能确保电源失效,甚至正常退出应用后,数据的安全。为了ES的可靠性,需要确保变更持久化到磁盘。我们说过一次全提交同步段到磁盘,写提交点,这会列出所有的已知的段。在重启,或重新打开索引时,ES使用这次提交点决定哪些段属于当前的分片。
关注时代Java