因为per-segment search机制,索引和搜索一个文档之间是有延迟的。新的文档会在几分钟内可以搜索,但是这依然不够快。磁盘是瓶颈。提交一个新的段到磁盘需要fsync操作,确保段被物理地写入磁盘,即时电源失效也不会丢失数据。但是fsync是昂贵的,它不能在每个文档被索引的时就触发。所以需要一种更轻量级的方式使新的文档可以被搜索,这意味这移除fsync。
下一个需要解决的问题是如何在保持不可变好处的同时更新倒排索引。答案是,使用多个索引。不是重写整个倒排索引,而是增加额外的索引反映最近的变化。每个倒排索引都可以按顺序查询,从最老的开始,最后把结果聚合。Elasticsearch底层依赖的Lucene,引入了per-segment search的概念。
第一个不得不解决的挑战是如何让文本变得可搜索。在传统的数据库中,一个字段存一个值,但是这对于全文搜索是不足的。想要让文本中的每个单词都可以被搜索,这意味这数据库需要存多个值。支持一个字段多个值的最佳数据结构是倒排索引。倒排索引包含了出现在所有文档中唯一的值或词的有序列表,以及每个词所属的文档列表。 Term | Doc 1 | Doc 2 | Doc 3 | ...
在分布式集群中,我们介绍了分片,把它描述为底层的工作单元。但分片到底是什么,它怎样工作?在这章节,我们将回答这些问题:为什么搜索是近实时的?为什么文档的CRUD操作是实时的?ES怎样保证更新持久化,即使断电也不会丢失?为什么删除文档不会立即释放空间?什么是refresh,flush, optimize API,以及什么时候你该使用它们?
索引别名和零停机时间前面提到的重新索引过程中的问题是必须更新你的应用,来使用另一个索引名。索引别名正是用来解决这个问题的!索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何需要索引名的 API 使用。
重新索引数据虽然你可以给索引添加新的类型,或给类型添加新的字段,但是你不能添加新的分析器或修改已有字段。假如你这样做,已被索引的数据会变得不正确而你的搜索也不会正常工作。修改在已存在的数据最简单的方法是重新索引:创建一个新配置好的索引,然后将所有的文档从旧的索引复制到新的上。
默认映射通常,一个索引中的所有类型具有共享的字段和设置。用 _default_ 映射来指定公用设置会更加方便,而不是每次创建新的类型时重复操作。_default 映射像新类型的模板。所有在 _default_ 映射 之后 的类型将包含所有的默认设置,除非在自己的类型映射中明确覆盖这些配置。
自定义动态索引如果你想在运行时的增加新的字段,你可能会开启动态索引。虽然有时动态映射的 规则 显得不那么智能,幸运的是我们可以通过设置来自定义这些规则。日期检测当 Elasticsearch 遇到一个新的字符串字段时,它会检测这个字段是否包含一个可识别的日期,比如 2014-01-01。
动态映射当 Elasticsearch 处理一个位置的字段时,它通过【动态映射】来确定字段的数据类型且自动将该字段加到类型映射中。有时这是理想的行为,有时却不是。或许你不知道今后会有哪些字段加到文档中,但是你希望它们能自动被索引。或许你仅仅想忽略它们。特别是当你使用 Elasticsearch 作为主数据源时,你希望未知字段能抛出一个异常来警示你。
文档 ID文档唯一标识由四个元数据字段组成:_id:文档的字符串 ID_type:文档的类型名_index:文档所在的索引_uid:_type 和 _id 连接成的 type#id默认情况下,_uid 是被保存(可取回)和索引(可搜索)的。_type 字段被索引但是没有保存,_id 和 _index 字段则既没有索引也没有储存,它们并不是真实存在的。尽管如此,你仍然可以像真实字段一样查询 _id 字段。
元数据:_all 字段在【简单搜索】中,我们介绍了 _all 字段:一个所有其他字段值的特殊字符串字段。query_string 在没有指定字段时默认用 _all 字段查询。
元数据:_source 字段默认情况下,Elasticsearch 用 JSON 字符串来表示文档主体保存在 _source 字段中。像其他保存的字段一样,_source 字段也会在写入硬盘前压缩。
根对象映射的最高一层被称为 根对象,它可能包含下面几项:一个 properties 节点,列出了文档中可能包含的每个字段的映射多个元数据字段,每一个都以下划线开头,例如 _type, _id 和 _source设置项,控制如何动态处理新的字段,例如 analyzer, dynamic_date_formats 和 dynamic_templates。
类型和映射类型 在 Elasticsearch 中表示一组相似的文档。类型 由一个 名称(比如 user 或 blogpost)和一个类似数据库表结构的映射组成,描述了文档中可能包含的每个字段的 属性,数据类型(比如 string, integer 或 date),和是否这些字段需要被 Lucene 索引或储存。
自定义分析器虽然 Elasticsearch 内置了一系列的分析器,但是真正的强大之处在于定制你自己的分析器。你可以通过在配置文件中组合字符过滤器,分词器和标记过滤器,来满足特定数据的需求。在 【分析器介绍】 中,我们提到 分析器 是三个顺序执行的组件的结合(字符过滤器,分词器,标记过滤器)。字符过滤器字符过滤器是让字符串在被分词前变得更加“整洁”。
配置分析器第三个重要的索引设置是 analysis 部分,用来配置已存在的分析器或创建自定义分析器来定制化你的索引。在【分析器介绍】中,我们介绍了一些内置的分析器,用于将全文字符串转换为适合搜索的倒排索引。standard 分析器是用于全文字段的默认分析器,对于大部分西方语系来说是一个不错的选择。它考虑了以下几点:standard 分词器,在词层级上分割输入的文本。
索引设置你可以通过很多种方式来自定义索引行为,你可以阅读Index Modules reference documentation,但是:提示: Elasticsearch 提供了优化好的默认配置。除非你明白这些配置的行为和为什么要这么做,请不要修改这些配置。下面是两个最重要的设置:number_of_shards定义一个索引的主分片个数,默认值是 `5`。这个配置在索引创建后不能修改。
创建索引迄今为止,我们简单的通过添加一个文档的方式创建了一个索引。这个索引使用默认设置,新的属性通过动态映射添加到分类中。现在我们需要对这个过程有更多的控制:我们需要确保索引被创建在适当数量的分片上,在索引数据_之前_设置好分析器和类型映射。
我们已经看到Elasticsearch如何在不需要任何预先计划和设置的情况下,轻松地开发一个新的应用。并且,在你想调整索引和搜索过程来更好地适应你特殊的使用需求前,不会花较长的时间。它包含几乎所有的和索引及类型相关的定制选项。在这一章,将介绍管理索引和类型映射的API以及最重要的设置。
scan(扫描)搜索类型是和scroll(滚屏)API一起使用来从Elasticsearch里高效地取回巨大数量的结果而不需要付出深分页的代价。scroll(滚屏)一个滚屏搜索允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果剩下。这有点像传统数据库里的cursors(游标)。滚屏搜索会及时制作快照。这个快照不会包含任何在初始阶段搜索请求后对index做的修改。
关注时代Java