• Elasticsearch-8.2(2024/03/26)

    What is Elasticsearch?

    (8.2)link

    You know, for search (and analysis)

      Elasticsearch是Elastic Stack中核心的分布式搜索和分析引擎。Logstash和Beats帮助收集,聚合以及丰富你的数据并存储在Elasticsearch。Kibana使你能够交互式地探索、可视化和分享对数据的见解,并管理和监视stack。Elasticsearch用于索引,查询以及分析。

      Elasticsearch提供对所有类型的数据的近实时搜索(near real-time)和分析。无论是结构化还是非结构化的文本,数值类型的数据,或者地理位置数据,Elasticsearch都能有效的进行存储并以某种方式进行索引来实现快速查询。你可以不仅仅是简单的数据检索而是可以进一步的对信息进行聚合来发现你数据中的趋势和patterns。随着你的数据和查询体量的增大,Elasticsearch的分布式功能使你的部署能够无缝地(seamless)随之增长。

      虽然不是每一个问题都是一个查询问题,Elasticsearch为在各种用例中处理数据提供了速度(speed)和灵活性(flexibility)。

      我们不断的因为用户使用新颖(novel)的搜索方式而感到惊讶(amaze)。但是不管你的使用案例是否类似与这些中的一种,或者你正在使用Elasticsearch解决(tackle)一个新的问题,你在Elasticsearch中处理你数据, 文档以及索引都是一样的。

    Data in documents and indices

    (8.2)link

      Elasticsearch是一个分布式的文档存储。Elasticsearch 存储已序列化为 JSON 文档的复杂数据结构,而不是将信息存储为列式数据行。当你的集群中有多个Elasticsearch节点,存储的文档跨集群分布并能立即从任何节点访问。

      文档在存储之后,它会被索引(index)并且在能在near real time--一秒内完全的用于搜索。Elasticsearch使用了称为倒排表(inverted index)的数据结构,它能够用于快速的全文检索。inverted index列出了出现在所有文档中的每一个unique word并识别出每一个单词所在的所有文档。

      索引(index)可以认为是一个优化后的文档集合,每一篇文档是一个字段(field)的集合,每一个字段是包含数据的一个键值对(key-value pair)。默认情况下,Elasticsearch会索引所有字段中的数据并且每一种索引字段(indexed field)都有专门的优化后的数据结构。例如,text field存储在倒排索引(inverted index)中,numeric和geo field存储在BKD树中。使用每一种字段的数据结构进行组合(assemble)和返回查询结果的能力使得Elasticsearch特别的快。

      Elasticsearch同样有schema-less的能力,意味着不用显示的指定如何处理一篇文档中的不同的字段就可以直接对文档进行索引。当开启dynamic mapping后,Elasticsearch能自动的检测并添加新的字段到索引中。默认的行为使得索引以及探索你的数据变得简单。只需要开始索引文档,Elasticsearch就会进行检测并将booleans,floating point,integer values,dates和strings映射成Elasticsearch中合适的数据类型。

      最终,当你比Elasticsearch更了解自己的数据并且想要按照自己的方式来处理。你可以定义规则来控制dynamic mappings以及显示的(explicit)定义mapping来完全的控制如何对字段进行存储和索引。

      定义你自己的mapping可以让你:

      基于不同的目的,用不同的方式索引同一个字段通常是很有用的。例如你可能想要将一个字符串字段索引为text field用于全文检索以及keyword用于排序、聚合。或者你可能会选择使用多个语言分词器来处理包含用户输入的内容。

      在索引期间应用到full-text字段的analysis chain在查询期间同样需要使用。当你查询一个full-text 字段,在索引中查找term前,它的请求文本(query text)也会经历(undergo)相同的analysis。

    Information out: search and analyze

    (8.2)link

      当使用Elasticsearch作为一个文档存储(document store),检索文档以及文档的元信息(metadata)时,你能够轻松访问全套搜索能力,其能力来源是因为构建在Apache Lucene 搜索引擎库之上。

      Elasticsearch提供了一套简单的,容易理解的(coherent)的REST API,用于管理集群,索引以及查询数据。出于测试的目的,你可以简单的通过命令行或者Kibana中的Developer Console直接提交一个请求。在你的应用中,你可以选择语言并使用Elasticsearch client:Java, JavaScript, Go, .NET, PHP, Perl, Python 或者 Ruby。

    Searching your data

      Elasticsearch REST APIs支持结构化查询(structured query),全文检索,以及复杂的查询,比如query的组合。结构化查询类似你在SQL中构造的查询类型。例如,你可以在employee索引中查询genderage字段并且根据hire_date字段对匹配的结果进行排序。全文检索会找到满足查询条件的所有的文档并且根据相关性(relevance,how good a match they are for your search terms)排序。

      除了查询不同的term,你还可以执行短语查询(phrase search),相似度查询(similarity search),前缀查询(prefix search)以及获得autocomplete suggestions。

      想要查询地理位置或者其他数值类型的数据的话,Elasticsearch将这类非文本的数据索引到一个优化后的数据结构(BKD)使得支持高性能的地址位置和数值查询。

      你可以使用Elasticsearch中JSON风格的查询语言(Query DSL)来访问所有的查询能力。你也可以构造SQL-style query查询/聚合数据,以及使用JDBC和ODBC驱动使得更多的第三方应用通过SQL使用Elasticsearch。

    Analyzing your data

      Elasticsearch的聚合(aggregation)能让你构建复杂的数据汇总并获得关键指标的洞见(insight),模式(pattern)以及趋势(trend)。聚合能让你回答下面的问题,而不是仅仅如谚语中所说的needle in a haystack: Near real-time search

      你可以使用聚合回答更多subtle问题,例如:

      由于聚合使用了查询中使用的相同的数据结构,所以非常的快,使得可以实时的分析以及可视化你的数据。报表跟dashboard可以随着你的数据的变更而更新,使得你可以基于最新的信息采取措施(take action)。

      聚合是跟查询请求一起执行的。你可以在单个请求中对相同的数据进行查询,过滤,以及分析。因为聚合要在某个查询的上下文中计算,你不仅仅能展示70号needle的数量统计,你还能展示满足你的策略的needle:比如说70号的不沾针(non-stick embroidery needles)。

    But wait, there’s more

      想要自动分析你的时序数据吗?你可以使用machine learning功能创建你的数据中普通行为(normal behavior)的准确基线以及识别出异常模式(anomalous pattern)。使用machine learning,你可以检测下面的信息:

      And the best part? 你不需要指定算法,模型或者其他数据科学相关的配置就可以实现上面的功能。

    Scalability and resilience: clusters, nodes, and shards

    (8.2)link

      Elasticsearch总是可用的(available)并且根据你的需要进行扩展。It does this by being distributed by nature。你可以向一个集群中添加服务(节点)来提高承载力(capacity),Elasticsearch可以跨所有可用的节点,自动的分布/查询(distribute/query)数据。不需要overhaul你的应用,Elasticsearch知道如何平衡多个节点的集群来提供扩展以及高可用能力。The more nodes, the merrier。

      Elasticsearch是如何工作的?在底层实现中,一个Elasticsearch index只是一个或多个物理分片(physical shards)的逻辑组合(logical grouping)。每一个分片实际上是一个self-contained index。通过将索引中的文档分布到多个分片,将分片分布到多个节点,Elasticsearch可以确保冗余(ensure redundancy),使得应对硬件故障以及节点添加到集群后,查询能力的提升。随着集群的增长(收缩),Elasticsearch能自动的迁移(migrate)分片来rebalance集群。

      分片的类型有两种:主分片跟副本分片(primary and replica shard)。索引中的每一篇文档属于某一个主分片。一个副本分片是某个主分片的拷贝。副本分片提供了数据的冗余来应对硬件故障以及提高例如查询或者检索一篇文档的读取请求的能力。

      某个索引中的主分片数量在索引创建后就固定了。但是副本分配的数量可以在任何时间内更改,不会影响(interrupt)索引或者查询操作。

    It depends…

      对于分片大小和索引的主分片数量,有很多性能考虑点以及trade off。分片越多,维护这些索引的开销就越大。分片大小越大,当Elasticsearch需要rebalance集群时,移动分片花费的时间越大。

      在很多较小的分片上查询时,在每一个分片上的查询很快,但是分片越多,查询次数就越多,开销就越大,所以在数量较小,体积较大的分片上的查询可能就更快。In short…it depends。

      As a starting point:

      对于你的用例,确定最佳配置的最好方式是通过testing with your own data and queries

    In case of disaster

      集群中的节点之间需要良好的,可靠的连接。若要能提供一个较好的连接,你通常会将节点放在相同的数据中心或者附近的数据中心。然而为了高可用,你同样需要避免单点故障(single point of failure)。某个地区(location)发生停电后,其他地区必须能接管服务。这个问题的答案就是使用CCR(Cross-cluster replication)。

      CCR提供了一种从主集群(primary cluster)自动同步索引到secondary remote cluster的方法,即secondary remote cluster作为一个热备(hot backup)。如果primary cluster发生了故障,secondary cluster可以进行接管。你可以使用CCR创建secondary cluster,给地理上靠近(geo-proximity)这个secondary cluster的用户提供读取请求。

    Care and feeding

      与任何企业系统一样,你需要工具来secure,manage,以及monitor你的Elasticsearch 集群。Security,monitoring,以及administrative features都集成到了Elasticsearch,使得你可以使用Kibana作为控制中心来管理集群。比如data rollupsindex lifecycle management这些功能能帮助你根据时间来管理你的数据。

    Set up Elasticsearch

    link

      这个章节介绍了如何设置Elasticsearch并且使其运行,包含的内容有:

    Supported platforms

      官方给出的操作系统以及JVM的支持列表见Support Matrix.Elasticsearch在这些平台上都经过了测试,但是在列表外的其他平台上还是有可能可以正常工作的。

    Java(JVM)Version

      Elasticsearch使用Java构建,并且每次发布都捆绑了一个OpenJDK,这个OpenJDK由JDK维护者使用GPLv2+CE协议维护。建议使用捆绑的JDK,它位于Elasticsearch home目录中名为jdk的目录中。

      可以通过设置环境变量ES_JAVA_HOME来使用你自己的Java版本。如果你一定要使用一个跟捆绑的JVM不一样的Java版本,我们建议你使用Java的长期支持版本LTS 。如果使用了一个错误Java版本的,Elasticsearch将不会启动。当你使用了自己的JVM后,绑定的JVM目录可能会被删除。

    Use delicated hosts 使用专用的主机

      在生产上,我们建议你在专用的主机或者主服务器上(primary service)运行Elasticsearch。假定Elasticsearch是主机上或者容器上唯一的资源密集型的应用,那么一些Elasticsearch的功能比如自动化分配JVM堆大小就能实现。比如说,你可能同时运行Metribeat跟Elasticsearch来做集群统计,那么就应该将resource-heavy的Logstash部署在它自己的主机上。

    Installing Elasticsearch

    link

    Hosted Elasticsearch

      你可以在自己的设备上运行Elasticsearch或者也可以使用AWS, GCP, and Azure上专用的Elasticsearch服务器

    Installing Elasticsearch Yourself

      Elasticsearch以下列的打包方式呈现:

    Configuration Management Tools

      我们同样提供了下列的配置管理工具有助于大型的部署

    Install Elasticsearch from archive on Linux or MacOS

    link

      在Linux和MacOS平台下,Elasticsearch是作为一个.tar.gz的归档文件。

      这个安装包同时包含了免费和订阅的特性,30天试用可以使用所有的功能。

      Elasticsearch最新的稳定版本可以从这个页面下载,其他版本可以从过去的发布页面下载。

    NOTE: Elasticsearch中捆绑了一个OpenJDK,这个OpenJDK由JDK维护者使用GPLv2+CE协议维护,如果要使用自己的Java版本,

    Download and install archive for Linux

      Linux下Elasticsearch-7.15.2归档文件的下载以及安装如下所示:

      上文第三行Compares the SHA of the downloaded .tar.gz archive and the published checksum,which should output elasticsearch-{version}-linux-x86_64.tar.gz: OK

      上文第五行就是所谓的 $ES_HOME

    Download and install archive for MacOS

      MacOS下Elasticsearch-7.15.2归档文件的下载以及安装如下所示:

      上文第三行Compares the SHA of the downloaded .tar.gz archive and the published checksum,which should output elasticsearch-{version}-linux-x86_64.tar.gz: OK

      上文第五行就是所谓的 $ES_HOME

    Enable automatic creation of system indices

      一些商业功能会自动创建索引。默认情况下,Elasticsearch可以被配置为允许自动创建索引,并且不需要再做额外的步骤。然而,如果你关闭了自动创建索引, 你必须在elasticsearch.yml中配置action.auto_create_index来允许商业功能创建下面的索引:

    IMPORTANT:如果你正在使用Logstash或者Beats,那么你很有可能需要在action.auto_create_index配置额外的索引名,确切的名称取决去你的本地配置。如果你不能保证正确的名称,你可以考虑将索引名设置为*,这样就会自动创建所有的索引

    Running Elasticsearch from the command line

      Elasticsearch可以通过下面的命令行启动:

      如果Elasticsearch keystore有密码保护,你会被提示(be prompted to)输入keystore's的密码,详细内容见安全配置

      默认情况下,Elasticsearch将日志打印到控制台(标准输出)以及日志目录<clustername>.log文件中。Elasticsearch在启动期间会生成一些日志,但一旦初始化完成,它将继续在前台(foreground)运行并且不再生成任何日志直到一些值的记录的信息产生。在Elasticsearch运行期间,你可以通过HTTP接口访问默认的9200端口与Elasticsearch交互。输入Ctrl-c来停止Elasticsearch。

    NOTE:Elasticsearch安装包中的所有脚本要求的Bash版本需要支持arrays并且假定/bin/bash是存在的,同样的,Bash在这个路径是存在的或者能通过动态链接找到

    Checking that Elasticsearch is running

      你能通过HTTP请求访问localhost:9200来测试Elasticsearch节点是否在运行中:

      你应该能收到类似下面的回应(response)

    Running as a daemon

      在命令行指定-d使得Elasticsearch成为一个后台程序,并且通过参数-p生成一个pid文件记录进程号。

      如果Elasticsearch keystore有密码保护,你会被提示(be prompted to)输入keystore's的密码,详细内容见安全配置

      $ES_HOME/logs/目录能找到日志信息。

      通过杀死pid文件中记录的进程号来关闭Elasticsearch。

    NOTE:tar.gz的安装包中不包含systemd组件。如果要把Elasticsearch作为一个服务管理,用RPM或者Debian的安装包进行安装。

    Configuring Elasticsearch on the command line

      Elasticsearch默认装载(load)的配置文件路径为$ES_HOME/config/elasticsearch.yml,这个配置文件中的格式见Configuring Elasticsearch

      在配置文件中可以指定的任何设置(settings)都可以通过命令行的参数指定,使用-E语法:

    TIP:一般来说,任何集群范围(cluster-wide)的配置(比如说 cluster.name)都应该在elasticsearch.yml文件中配置,同时具体节点的任意配置比如说node.name可以通过命令行参数指定

    Directory layout of archives

      归档发行版 (archive distribution)是self-contained(意思就是所有的文件都在同一个目录中,Elasticsearch还有安装包发行版package distribution,通过这种方式安装后,文件会分散在不同的目录中)。所有的文件和目录默认情况下都在$ES_HOME下,$ES_HOME在解压归档后会被创建。

      这是一种非常方便的方式因为你不需要创建任何目录来开始使用Elasticsearch,并且当卸载Elasticsearch时只要简单的移除$ES_HOME。然而我们建议把配置文件目录config directory、数据目录data directory、以及日志目录log directory的位置进行变更,以免在以后重要的数据被删除。

    类型Type描述Description默认位置Default Location设置Setting
    homeElasticsearch home目录或者$ES_HOME解压归档后创建这个目录 
    bin二进制脚本,包含elasticsearch用于启动一个节点以及elasticsearch-plugin用于安装插件$ES_HOME/binES_PATH_CONF
    conf包含elasticsearch.yml的所有配置文件$ES_HOME/config 
    data每一个索引/分片的数据文件的位置$ES_HOME/datapath.data
    logs日志文件位置$ES_HOME/logspath.logs
    plugins插件文件位置。每个插件在一个子目录中$ES_HOME/plugins 
    repoShared file system repository locations. Can hold multiple locations. A file system repository can be placed in to any subdirectory of any directory specified here.NOT_configuredpath.repo
    Next steps

      现在你建好了一个Elasticsearch测试环境。在你开始认真做开发护着进入Elasticsearch的生产环境,你必须做一些额外的设置:

    Install Elasticsearch with Docker

    link

    Configuring Elasticsearch

    (8.2)link

      Elasticsearch附带(ship with)了很好的默认配置并且只需要较小的配置。在一个运行中的集群中,大部分的设置可以通过Cluster update settings API进行更改。

      配置文件应该包含对指定节点(node-specific)的设置,例如node.name以及路径,或者是能让节点加入集群的配置,例如cluster.name以及network.host

    Config files location

      Elasticsearch有三个配置文件:

      这三个文件都在config目录中,它们的默认路径取决于使用哪种方式安装:归档发行版(archive distribution)tar.gz或者zip还是安装包发行版(package distribution)Debian 或者RPM安装包。

      对于归档发行版,config目录位置默认是$ES_HOME/config。config目录的位置能通过ES_PATH_CONFIG这个环境变量进行更改:

      或者,通过在命令行或profile文件中export ES_PATH_CONFIG这个环境变量。

      对于安装包发行版,config目录的位置默认在/etc/elasticsearch,config目录的位置可以通过ES_PATH_CONF这个环境变量变更。注意的是在shell中设置这些是不够的。Instead, this variable is sourced from /etc/default/elasticsearch (for the Debian package) and /etc/sysconfig/elasticsearch (for the RPM package). You will need to edit theES_PATH_CONF=/etc/elasticsearch entry in one of these files accordingly to change the config directory location.

    Config file format

      配置格式是YAML,下面是更改数据和日志目录的例子

      配置也可以进行平铺(flattened)

      在YAML中,你可以格式化non-scalar的值写成序列:

      尽管下面的方式不是很常见(Thought less common),你也可以把non-scala的值写成数组:

    Environment variable substitution

      在配置文件中可以通过使用${...}这类符号的方式引用环境变量:

      环境变量的值必须是简单的String值,用逗号分隔的String值会被Elasticsearch解析成一个list。例如,Elasticsearch将下面的环境变量的String值根据逗号切分到list中。

    Cluster and node setting types

      集群跟节点的设置基于它们是如何被配置可以分类为:

    Dynamic(settings)

      在一个正在运行的集群上,你可以使用cluster update settings API来配置或更新动态设置。你也可以使用elasticsearch.yml对本地未启动或者关闭的节点配置动态设置。

      使用cluster update settings API更新可以是永久的(persistent),即使集群重启也生效,也可以是临时的(transient),集群在重启后就重置了。你也可以通过使用API把配置设置为null也能重置使用persistent或者transient更新过的设置。

      如果你用多种方式配置了一样的设置,那么Elasticsearch会根据下面的优先顺序(order of precedence)来应用设置(apply settings)。

    1. Transient Setting

    2. Persistent Setting

    3. elasticsearch.yml setting

    4. Default setting value

      例如,你可以使用一个transient setting覆盖persistent setting或者elasticsearch.yml。然而,在elasticsearch.yml上的变更不会覆盖定义好的(defined)transient 或者 persistent setting。

    TIP:如果你使用Elasticsearch Service,使用user settings功能来配置所有的设置。这个方法能让Elasticsearch自动的拒绝(reject)掉任何会破坏你集群的设置。 如果你在自己的设备(hardware)上运行Elasticsearch,可以使用cluster update settings API来配置集群动态设置。对于集群或者节点的静态设置只使用elasticsearch.yml来配置。使用API不会要求重启并且保证所有节点都被配置成相同的值。

    WARNING: We no longer recommend using transient cluster settings. Use persistent cluster settings instead. If a cluster becomes unstable, transient settings can clear unexpectedly, resulting in a potentially undesired cluster configuration. See the Transient settings migration guide.

    Static(settings)

      静态设置只能在未启动或者关闭的节点上使用elasticsearch.yml来配置。

      静态配置必须在集群中相关的所有节点上一一配置。

    Important Elasticsearch configuration

    (8.2)link

      Elasticsearch只需要很少的配置就能启动。但是在生产中使用你的集群时必须要考虑这些条目:

      我们的Elastic Cloud service能自动配置这些条目,使得你的集群处在生产就绪状态。

    Path settings

      Elasticsearch把你的索引数据和数据流(data streams)都写到data目录中。

      Elasticsearch本身也会生产应用日志,包含集群健康信息以及集群操作信息,并且写入到logs目录中。

      对于在MacOS和Linux下使用.tar.gz, 以及Windows下使用zip方式安装时,datalogs目录默认是$ES_HOME下的子目录,然而在升级Elasticsearch时,位于$ES_HOME下的文件是存在风险的。

      在生产中,我们强烈建议在elasticsearch.yml中设置path.datapath.logsdatalogs目录放到$ES_HOME以外的位置。其他安装方式(rpm、macOS Homebrew、Windows .msi)默认会把datalogs目录放到$ES_HOME以外的位置。

      支持在不同的平台,path.datapath.logs可以是不同的值:

    WARNING:不要更改data目录中的任何内容(content),也不要运行可能会影响data目录内容的程序。如果Elasticsearch以外的程序更改了data目录的内容,那么Elasticsearch可能会失败,报告损坏或者其他数据不一致性(data inconsistencies)的问题,也可能工作正常但是丢失了一些你的数据。

    Multiple data paths

    WARNING: 在7.13.0版本中废弃了

      如果有这个需要,你可以在path.data中指定多个路径。Elasticsearch会在这些路径上存储节点的数据,但是会在相同的路径上存储同一个shard的数据。

      Elasticsearch不会在多个路径上去平衡shards的写入。在某个路径上的高磁盘使用率会触发整个节点的high disk usage watermark。触发后,Elasticsearch不会在这个节点增加shard,尽管这个节点的在其他路径上有可用的空间。如果你需要额外的磁盘空间,我们建议你增加新的节点而不是增加data的路径。

    Migrate from multiple data paths

      在7.13版本中弃用了多个数据路径的支持,将会在未来的版本中移除。

      作为多个数据路径的替代方案,你可以通过使用硬件虚拟化层(如RAID)或软件虚拟化层(如Linux上的逻辑卷管理器(LVM)或Windows上的存储空间)来创建跨多个磁盘的文件系统。如果你希望在单台机器上使用多个数据路径,则必须为每个数据路径运行一个节点。

      如果你正在一个highly available cluster中使用多个数据路径,你可以无需停机,使用类似rolling restart的方式对一个节点使用单个数据路径来实现迁移:轮流关闭每一个节点,并用一个或多个配置为使用单个数据路径的节点替换它。跟进一步的说,对于每一个当前有多个数据路径的节点来说,你应该按照下面的步骤进行迁移。原则上你可以在升级到8.0版本时执行这类迁移,但是我们建议在升级版本前先完成单个数据路径的迁移工作。

    1. 执行快照防止你的数据出现灾难性的问题

    2. (可选)使用allocation filter将目标节点的数据进行迁移

    你可以使用cat allocation API来跟踪数据迁移的进度。如果某些分片没有迁移,那么cluster allocation explain API会帮助你查明原因。

    1. 按照rolling restart process中的步骤执行,包括关闭目前节点。

    2. 确保你的集群是yellow或者green,使得你的集群中至少有一个节点有每一个分片的拷贝。

    3. 如果执行了上面的第二步,现在需要移除allocation filter。

    1. 通过删除数据路径的方式来丢弃被停掉的节点拥有的数据。

    2. 重新配置你的存储。使用LVM或者Storage Spaces将你的磁盘合并到单个文件系统中。确保你重新配置的存储有足够的空间存储数据

    3. 通过设置elasticsearch.yml文件中的path.data来重新配置你的节点。如果有需要的话,安装更多的节点,并使用它们自己各自的path.data

    4. 启动新的节点并按照rolling restart process中的其他步骤执行

    5. 确保你的集群健康是green,使得所有的分片都已经分配结束

      你也可以在你的集群中增加一些单数据路径的节点,使用allocation filters将你的数据迁移到新的节点中,然后将这些旧的节点从集群中移除。这个方法会临时增大集群中的体积,所以只有你的集群有这个膨胀能力才能使用这个方法。

      如果你目前使用多个数据路径,但你的集群并不具备高可用性,则可以通过拍摄快照、创建具有所需配置的新集群并将快照还原到其中来迁移到非废弃配置。

    Cluster name setting

      在一个集群中,一个节点只有跟集群中的其他节点共享他的cluster.name才能加入到这个集群中。默认的名称是elasticsearch,但是你应该把这个名称改成一个合适的名称,这个名称能描述这个集群的目的。

    IMPORTANT:在不同的环境中不要重复使用相同的集群名,否则节点可能会加入到错误的集群中。

    Node name setting

      Elasticsearch使用node.name作为可读(human-readable)的一个特定的Elasticsearch实例。在很多APIs的返回中(response)会用到。当Elasticsearch启动后,节点名称默认是服务器的hostname,可以在elasticsearch.yml中显示配置:

    Network host setting

      默认清下,Elasticsearch只绑定类似127.0.0.1以及[::1]的回调地址(lookback address)。这样的话能够在单个服务上允许一个集群的多个节点用于开发以及测试。但是一个resilient production cluster必须是包含在其他服务上的节点。尽管还有许多newwork settings,但是通常你只需要配置network.host

    当你提供了network.host的值,Elasticsearch会假设你正在从开发模式转到生产模式,并且会在系统启动时升级warning到exception的检查。见development and production modes的差异。

    Discovery and cluster formation settings(setting)

      在进入生产前配置两个重要的discovery和cluster formation设置,使得这个集群中的节点能互相发现并且选出一个master节点。

    discovery.seed_hosts

      如果没有配置任何网络设置,Elasticsearch会绑定可见的回调地址并且扫描本地的9300到9305端口去连接同一个服务上的其他节点。这种行为提供了一种自动集群体验,而无需进行任何配置。即开箱即用(out of box)。

      当你想要组成(form)一个集群,它包含的节点在其他服务器上时,可以使用静态discovery.seed_hosts设置。这个设置可以提供一个集群中其他节点的list,这些节点是候选的主节点(mater-eligible),并且有可能是live的,并且能在discovery process中作为可以联系的节点来选出种子选手(and contactable to seed the discovery process。翻译能力有限,只可意会,不可言传)。这个设置可以将集群中所有候选的主节点的地址用YAML中的序列或者数组的风格书写。每一个地址可以是IP地址或者hostname,hostname可以通过DNS关联一个或多个IP地址。

    1. 如果IP地址中没有指定端口号,那么就是默认的9300,默认的端口号也可以被override

    2. 如果hostname关联多个IP 地址,那么当前节点会试图发现hostname关联的所有地址上的节点

    3. IPv6地址使用方括号包裹(enclosed in square brackets)

      如果候选的主节点的节点没有固定的名称或者地址,可以使用alternative hosts provider 来动态的找到它们的地址。

    cluster.initial_master_nodes

      当你第一次启动Elasticsearch集群,在cluster bootstrapping阶段确定在第一次参与投票的候选主节点。在development mode中,with no discovery settings configured, this step is performed automatically by the nodes themselves。

      因为auto-bootstrapping是内在不安全的,在生产模式中启动一个新的集群时,你必须显式列出候选的主节点并且它们的投票要被统计在第一轮的选票中。你可以使用cluster.initial_master_nodes设置来列出这些候选的主节点。

    IMPORTANT:当一个新的集群第一次形成之后,从每个节点的配置中移除cluster.initial_master_nodes设置。当重启一个集群或者往已存在的集群中添加一个新的节点时,不要使用该配置。

    1. 通过node.name来确定最初的master节点身份,默认是hostname。要确保cluster.initial_master_nodesnode.name的值是一致的。如果节点的名称使用了全限定域名(fully-qualified domain name),比如master-node-a.example.com,那么你必须在cluster.initial_master_nodes中使用FQDN。相反的,如果只是仅仅使用了hostname而没有尾随的限定符,那么在cluster.initial_master_nodes也不能带尾随的限定符

      bootstrapping a clusterdiscovery and cluster formation settings

    Heap size settings

      默认情况下,Elasticsearch会根据节点的roles跟内存大小来自动的设置JVM堆的大小。我们建议使用默认的大小,它适用于大部分生产环境。

    NOTE:堆大小的自动配置需要bundle JDK,如果使用自定义的JRE位置,需要Java 14以及更新的JRE。

      如果有必要,你可以通过setting the JVM heap size手动覆盖默认值。

    JVM heap dump path setting

      默认情况下,Elasticsearch会配置JVM,使得OOM异常转存(dump)到data目录。在基于ROM跟Debian的安装包中,data目录位于/var/lib/elasticsearch。在Linux、MacOs以及Windows发行版中,data目录位于Elasticsearch安装目录的根目录。

      如果默认的路径用于接受heap dump不是很合适,那么可以通过在文件jvm.options中修改-XX:HeapDumpPath=...

    GC logging settings

      默认情况下,Elasticsearch开启了垃圾回收日志。在jvm.options文件中配置,并且输出到Elasticsearch的logs文件中。默认的配置中,每64M就会轮换一次日志,最多消耗2G的磁盘空间。

      你可以命令行来配置JVM的日志打印,见JEP 158: Unified JVM Logging。除非你直接更改jvm.options文件,Elasticsearch的默认配置会被应用(apply)除了你自己的设置。如果要关闭默认配置,第一步先通过提供参数-Xlog:disable关闭日志打印,然后提供你自己的命令选项。以上操作会关闭所有的JVM日志打印,所以要确定好可用的选项来满足你的需求。

      Enable Logging with the JVM Unified Logging Framework了解更多在原始的JEP(origin JEP)中不包含的虚拟机选项。

    Examples

      下面的例子中创建了$ES_HOME/config/jvm.options.d/gc.options并包含一些虚拟机选项:把默认的GC 日志输出到/opt/my-app/gc.log

      下面的例子中配置一个Elasticsearch Docker container,将GC的debug日志输出到stderr,让容器编排器处理输出。

    Temporary directory settings

      默认情况下,Elasticsearch会使用一个私有的临时目录,它由一个启动脚本创建,并位于系统的临时目录中。

      在一些Linux发行版中,一些系统工具会清楚 /tmp 目录下长时间未被访问的文件。这会导致Elasticsearch的私有临时目录可能会被删除。移除私有的临时目录会导致一些问题,比如一些功能随后会访问这些私有临时目录。

      如果你使用.deb或者.rpm安装的Elasticsearch,并且在systemd下运行,那么Elasticsearch使用的私有临时目录不会被周期性的清除(periodic cleanup)。

      如果你想要在Linux跟MacOS上运行.tar.gz发行版,可以考虑为Elasticsearch创建一个专用的临时目录,并且该目录所在路径中不包含旧的文件或目录,并且这个目录只有Elasticsearch有访问权限。最后在Elasticsearch启动前设置环境变量$ES_TMPDIR

    JVM fatal error log setting

      默认情况下,Elasticsearch会配置JVM将fatal错误日志写到默认的日志目录中。在RPMDebian安装中,目录位置为/var/log/elasticsearch,在Linux、MacOs、Windows发行版中,logs目录位于Elasticsearch的安装目录。

      当遇到一些fatal错误日志,它由JVM产生,比如说段错误(segmentation fault)。如果接受这些日志的路径不是很合适,可以在jvm.options中修改-XX:ErrorFile=...

    Cluster backups

      在发生灾难时,snapshot能防止数据永久丢失。Snapshot lifecycle management是最简单的办法来对集群实现定期备份。见Create a snapshot

    WARNING:快照是唯一可靠并且被支持的方式(supported way)来备份集群。 你不能通过拷贝data目录中的节点数据进行备份。没有一种支持方式(supported way)从文件系统层面的备份来恢复数据。如果你想尝试从这种备份中恢复集群,可能会失败并且Report出corruption或者文件丢失或者其他数据一致性的问题,或者出现成功的悄无声息的丢失一些你的数据

    Secure settings

    (8.2)link

      有些设置是敏感的(sensitive),仅仅依靠文件系统的权限来保护这些值是不够。对于这种情况,Elasticsearch提供了keystore和 elasticsearch-keystore tool 来管理这些设置。

    IMPORTANT:只有一些设置被设计为从keystore中读取。但是keystore没有验证一些不支持的设置。增加不支持的设置会导致Elasticsearch启动失败。

      所有在keystore中的变更只有在Elasticsearch重启后才生效。

      keystore中设置跟配置文件elasticsearch.yml中的普通的设置项一样都需要在每个节点上指定。当前,所有的安全设置都是特定于节点的,即所有的节点上必须设置相同的值。

    Reloadable secure settings

      elasticsearch.yml中的设置值一样,keystore中的内容无法自动的应用(apply)到正在运行的Elasticsearch节点,需要重启。然而有一些安全设置被标记为reloadable,这些设置可以被reload

      对于安全设置的值,不管是否可以reloadable,集群中的所有节点都必须一致。在安全设置变更后,执行bin/elasticsearch-keystore调用下面的请求:

    1. Elasticsearch keystore会对密码进行加密。

      上述API会解密并且重新读取集群中所有节点的整个keystore,但是只有reloadable的安全设置可以被应用(apply)。其他的安全设置不会生效直到下一次重启。一旦API调用返回了,意味着reload完成了,即所以依赖这些设置的内部数据结构都已经发生了变更。Everything should look as if the settings had the new value from the start。

      当更改了多个reloadable安全设置后,在集群中的每一个节点上修改后,随后发起reload_secure_settings的调用,而不用在每一次变更后reload。

      下面是reloadable安全设置

    Auditing security settings

    (8.2)link

      你可以使用audit logging来记录安全相关的事件,比如认证失败,拒绝连接,以及数据访问事件。另外也会记录通过API访问安全配置的操作,例如创建、更新、移除nativebuilt-in users,rolesrole mappings 以及 API keys

    TIP:日志审计只在某些订阅中提供,详细信息见 https://www.elastic.co/subscriptions

      在配置后,集群上的所有节点都需要设置一遍。静态设置,比如说xpack.security.audit.enabled,在每个节点的elasticsearch.yml中都必须配置。对于动态的日志设置,使用cluster update settings API 可以让所有节点的设置一致。

    General Auditing Settings
    xpack.security.audit.enabled

      Static)设置为true来开启。默认值为false。在每个节点上日志事件会被放到一个名为<clustername>_audit.json的专用的文件中。

      如果开启了,集群中的所有节点的elasticsearch.yml都需要配置该设置。

    Audited Event Settings

      日志事件以及其他一些信息比如获取什么样的日志可以通过下面的设置来控制:

    xpack.security.audit.logfile.events.include

      Dynamic)在日志输出中指定事件类型(kind of events),设置为_all会彻底的记录所有的日志事件,但通常不建议这么做因为会非常的verbose。默认值是一个list包含:access_denied, access_granted, anonymous_access_denied, authentication_failed, connection_denied, tampered_request, run_as_denied, run_as_granted, security_config_change

    xpack.security.audit.logfile.events.exclude

      Dynamic)从包含的(kind of events)列表中指定排除部分选项。当xpack.security.audit.logfile.events.include的值设置为_all时,然后用xpack.security.audit.logfile.events.exclude来进行指定选项的排除是不错的方式。默认值是空的list。

    xpack.security.audit.logfile.events.emit_request_body

      Dynamic)用于指定是否将REST请求的请求body作为日志事件的属性,这个设置可以用于audit search queries

      默认是false,那么请求body不会被打印出来。

    IMPORTANT:注意的是,当日志事件中包含请求body时,一些敏感数据可能以明文形式被记录,即使是一些安全相关API,比如修改用户密码,认证信息在开启后有被泄露(filter out)的风险

    Local Node Info Settings
    xpack.security.audit.logfile.emit_node_name

      Dynamic)指定在每一个日志事件中,节点名称node name是否作为其中的一个字段。默认值是false。

    xpack.security.audit.logfile.emit_node_host_address

      Dynamic)指定在每一个日志事件中,节点的地址是否作为其中的一个字段。默认值是false。

    xpack.security.audit.logfile.emit_node_host_name

      Dynamic)指定在每一个日志事件中,节点的主机名是否作为其中的一个字段。默认值是false。

    xpack.security.audit.logfile.emit_node_id

      Dynamic)指定在每一个日志事件中,节点的id是否作为其中的一个字段。不同于node name,管理员可以在配置文件中修改节点id,节点id在集群启动后将不可变更,默认值是true。

    Audit Logfile Event Ignore Policies

      下面的设置会影响ignore policies,它们能更精细的(fine-grained)控制日志事件打印到日志文件中。拥有相同police_name的设置将会组合到一个策略(police)中。如何一个事件匹配到任意一条策略的所有条件,该日志事件将被忽略并不会被打印。大多数的日志事件都遵照(subject to)忽略策略。唯一的例外(sole exception)是security_config_change类型的事件,无法被过滤掉(filter out),除非完全的通过xpack.security.audit.logfile.events.exclude进行exclude。

    xpack.security.audit.logfile.events.ignore_filters.<policy_name>.users

      Dynamic)用户名称列表或者名称通配值(wildcards)。匹配该值的所有用户的日志事件不会打印出来。

    xpack.security.audit.logfile.events.ignore_filters.<policy_name>.realms

      Dynamic)authentication realm的列表或者通配值,匹配该值的所有realm的日志事件不会打印出来。

    xpack.security.audit.logfile.events.ignore_filters.<policy_name>.actions

      Dynamic)action名称的列表或者通配值,action的名称可以在日志事件的action字段中找到, 匹配该值的所有action的日志事件不会打印出来。

    xpack.security.audit.logfile.events.ignore_filters.<policy_name>.roles

      Dynamic)角色列表或者角色通配值(wildcards)。匹配该值并且拥有该角色的所有用户的日志事件不会打印出来。如果用户拥有多个角色,而一些角色没有被策略覆盖到,那么该策略不会覆盖其日志事件。

    xpack.security.audit.logfile.events.ignore_filters.<policy_name>.indices

      Dynamic)索引名称列表或者通配值,日志事件中所有的索引名都匹配后才不会打印。如果事件中涉及(concern)了多条索引,并且一些索引没有被该策略覆盖到,那么该策略不会覆盖日志事件。

    Circuit breaker settings

    (8.2)link

      Elasticsearch包含多种熔断器来防止导致OOM的操作。每一种熔断器指定了内存的使用限制。另外,父级别的熔断器指定了内存的总量,限制子级别的熔断器的内存使用总量。

      除了特别的说明,这些设置能通过cluster-update-settings API在运行中的集群上进行动态的更新。

      关于熔断器提供的报错信息,见Circuit breaker errors

    Parent circuit breaker

      父级别的熔断器可以通过下面的设置进行配置:

    indices.breaker.total.use_real_memory

      Static)如果该值为true,那么父级别的熔断器会考虑实际的内存使用量,否则考虑的是子级别的熔断器预定(reserved)的内存量总和。默认值为true。

    indices.breaker.total.limit

      Dynamic)当indices.breaker.total.use_real_memory为false,并且虚拟机的内存使用量达到70%,或者当indices.breaker.total.use_real_memory为true时,并且虚拟机的内存使用量达到95%,所有的父熔断器开始限制内存使用。

    Field data circuit breaker

      Filed data熔断器会估算把字段filed载入到field data cache所使用的堆内存量。如果载入后会导致缓存超过了先前定义的内存限制值,熔断器将会停止该操作并返回错误。

    indices.breaker.fielddata.limit

      Dynamic)fielddata breaker的限制值,默认是40%的JVM堆内存量。

    indices.breaker.fielddata.overhead

      Dynamic)该配置是一个常量,所有field data的估算值乘以这个常量来计算出最终的估算值。默认是值1.03。

    Request circuit breaker

      Request熔断器允许Elasticsearch防止每一个请求的数据结构(例如,在一次请求中,聚合计算占用的内存量)超过一定量的内存量。

    indices.breaker.request.limit

      Dynamic)Request熔断器的限制值,默认是60%的JVM堆内存量。

    indices.breaker.request.overhead

      Dynamic)该配置是一个常量,所有Request的估算值乘以这个常量来计算出最终的估算值。默认是值1。

    In flight requests circuit breaker

      in flight Request熔断器允许Elasticsearch限制所有在传输或者HTTP层的请求的内存使用量不超过在一个节点上的相对内存总量。内存使用量基于请求本身的content length。This circuit breaker also considers that memory is not only needed for representing the raw request but also as a structured object which is reflected by default overhead。

    network.breaker.inflight_requests.limit

      Dynamic)in flight Request熔断器的限制值,默认是60%的JVM堆内存量。

    network.breaker.inflight_requests.overhead

      Dynamic)该配置是一个常量,所有in flight Request的估算值乘以这个常量来计算出最终的估算值。默认是值2。

    Accounting requests circuit breaker

      accounting熔断器允许Elasticsearch限制某些请求已经结束,但是相关内存还未被释放的内存量。比如说Lucene的段占用的内存。

    indices.breaker.accounting.limit

      Dynamic)accounting熔断器的限制值,默认是100%的JVM堆内存量。这意味着受到父级熔断器的配置限制。

    indices.breaker.accounting.overhead

      Dynamic)该配置是一个常量,所有accounting Request的估算值乘以这个常量来计算出最终的估算值。默认是值1。

    Script compilation circuit breaker

      和上文中的熔断器稍微不同的是,Script compilation熔断器限制了在一个时间周期内inline script compilation的数量。

      scripting 文档中prefer-parameters章节的内容来了解更多。

    script.max_compilations_rate

      Dynamic)Limit for the number of unique dynamic scripts within a certain interval that are allowed to be compiled. Defaults to 150/5m, meaning 150 every 5 minutes。

    Regex circuit breaker

      写的不好的正则表达式会降低(degrade)集群稳定性以及性能。regex熔断器限制了Painless scripts中正则表达式的使用以及复杂性。

    script.painless.regex.enabled

      Static))允许painless脚本中使用正则表达式,该值可以是:

    script.painless.regex.limit-factor

      Static))用来限制painless脚本中正则表达式的字符数量。Elasticsearch通过当前设置的值与脚本输入的值的长度的乘积值作为限制值。

      比如说输入值foobarbaz的长度为9,如果script.painless.regex.limit-factor的值为6,那么基于foobarbaz的正则表达式的长度为54(6 * 9)。如果超过这个限制值,将触发regex熔断器并返回错误。

      只有script.painless.regex.enabledlimited时,Elasticsearch才会使用该限制值。

    Cluster-level shard allocation and routing settings

    (8.2)link

      Shard allocation说的是分配分片到节点的过程。该过程会在initial recovery、副本(replica)分配、rebalancing或者增加或者移除节点时发生。

      master node的其中一个应用是决定如何分配分片到节点,何时在节点之间移动分片来平衡集群。

      以下的一些设置用来控制分配分片的过程:

      除此之外,还有一些其他的配置,见Miscellaneous cluster settings

    Cluster-level shard allocation settings

      你可以使用下面的设置来控制分片的分配以及恢复:

    cluster.routing.allocation.enable

      Dynamic)开启或者关闭某些分片类型的分配:

      在节点重启后,上述的配置不会影响本地主分片的恢复。重启后的节点上的未分配的主分片的allocation id如果匹配了集群状态中的active allocation ids,那么会立即恢复。

    cluster.routing.allocation.node_concurrent_incoming_recoveries

      Dynamic)在一个节点上允许同时进行恢复incoming recoveries的并发数量。incoming recoveries中的分片(大多数是副本分片或者就是分片正在重新分配位置relocating)将被分配到当前节点上。默认值是2。

    cluster.routing.allocation.node_concurrent_outgoing_recoveries

      Dynamic)在一个节点上允许同时进行恢复outgoing recoveries的并发数量。outgoing recoveries中的分片(大多数是当前节点上的主分片或者就是分片正在重新分配位置relocating)将被分配到当前节点上。默认值是2。

    cluster.routing.allocation.node_concurrent_recoveries

      Dynamic)一种快捷方法shortcut来设置cluster.routing.allocation.node_concurrent_incoming_recoveriescluster.routing.allocation.node_concurrent_outgoing_recoveries

    cluster.routing.allocation.node_initial_primaries_recoveries

      Dynamic)在一个节点重启后,副本分片replica的恢复是通过网络实现的,然而一个未分配的主分片unassigned primary则是通过读取本地磁盘数据恢复的。在同一个节点上通过这种本地恢复的方式是很快的,默认值是4。

    cluster.routing.allocation.same_shard.host

      Dynamic)该值允许执行一个检查,防止在单个主机上上分配多个相同的分片,通过主机名以及主机地址来描述一台主机。默认值是false。意味着默认不会进行检查。只有在同一台机器上的多个节点启动后,该值才会应用(apply)。

    Shard rebalancing settings

      当每一个节点上的分片数量是相等并且在任何节点的任何索引上没有集中分片(concentration of shards),那么集群是平衡的。Elasticsearch会运行一个自动程序(automatic process)称为rebalancing,它会在集群中的节点之间移动分片来提高平衡性。rebalancing遵守类似 allocation filteringforced awareness的分片分配规则。这些规则会阻止完全的平衡集群,因此rebalancing会努力(strive to)在你配置的规则下尽可能的去平衡集群。如果你正在使用 data tiers,那么Elasticsearch会自动的应用分配过滤规则将每一个分配放到合适的数据层,这些规则意味着平衡器在每一层中独立工作。

      你可以使用下面的设置在集群中控制分片的平衡:

    cluster.routing.rebalance.enable

      Dynamic)为指定的分片类型开启或关闭rebalancing:

    cluster.routing.allocation.allow_rebalance

      Dynamic)用于指定什么时候允许分片rebalancing

    cluster.routing.allocation.cluster_concurrent_rebalance

      Dynamic)用于控制集群范围(cluster wide)内分片平衡并发数,默认值是2。注意的是这个设置仅仅控制因为集群不平衡导致的分片重定位(shard relocating)的并发数。这个设置不会限制因 allocation filteringforced awareness导致的分片重定位。

    Shard balancing heuristics settings

      基于每个节点上分片的分配情况计算出一个weight来实现rebalancing,并且通过在节点之间移动分片来降低heavier节点的weight并且提高lighter节点的weight。当不存在可能使任何节点的权值与其他节点的权值更接近超过可配置阈值的分片移动时,集群是平衡的。下面的设置允许你控制计算的细节

    cluster.routing.allocation.balance.shard

      Dynamic)为节点上分配的分片总数定义一个weight因子。默认值是0.45f。提高这个值会使集群中所有节点的分片数量趋于均衡。

    cluster.routing.allocation.balance.index

      Dynamic)为每一个索引的分片数量定义一个weight因子。默认值是0.55f。提高这个值会使集群中所有节点上的每一个索引的的分片数量趋于均衡。

    cluster.routing.allocation.balance.threshold

      Dynamic)该值时候一个非负的浮点之后,Minimal optimization value of operations that should be performed。提高这个值将导致集群在优化分片平衡方面不那么积极(leess aggressive)。

    NOTE:无论balancing算法的结果如何,rebalancing可能因为forced awareness或者allocation filtering而无法执行

    Disk-based shard allocation settings

      基于磁盘的分片分配器能保证所有节点都有足够的磁盘空间而不用执行更多的分片移动。它基于一对阈值来分配分片:low wateremark 和 high watermark。主要的目的是保证在每一个节点不会超过high watermark,或者是暂时的超过(overage is temporary)。如果某个节点上超过了high watermark,那么Elasticsearch会通过把分片移动到集群中的其他节点来的方式来解决。

    NOTE:节点上有时(from time to time)出现临时的超过high watermark是正常的

      分配器总是尝试通过禁止往已经超过low watermark的节点分配更多分配的方式来让节点远离(clear of)high watermark。重要的是,如果所有的节点都已经超过了low watermark那么不会有新的分片会被分配并且Elasticsearch不会通过在节点间移动分片的方式来让磁盘使用率低于high watermark。你必须保证在你的集群中有足够的磁盘空间并且总存在一些低于low watermark的节点。

      通过基于磁盘的分片分配器进行的分片移动必须满足(satisfy)其他的分片分配规则,例如 allocation filteringforced awareness。如果这些规则过于严格,它们还可以防止碎片移动,以保持节点的磁盘使用在控制之下。如果你正在使用 data tiers,那么Elasticsearch会自动的应用分配过滤规则将每一个分配放到合适的数据层,这些规则意味着平衡器在每一层中独立工作。

      如果某个节点填满磁盘的速度比Elasticsearch将分片移动到其他地方的速度还要快就会有磁盘被填满的风险。为了防止出现这个问题,万不得已的情况下( as a last resort),一旦磁盘使用达到flood-stage watermark,Elasticsearch会阻塞受到影响的节点上的分片索引的写入。但仍然继续将分片移动到集群中的其他节点。当受到影响的节点上的磁盘使用降到high watermark,Elasticsearch会自动的移除write block。

    TIP:集群中的节点各自使用容量不相同的磁盘空间是正常的。集群的balance取决与每一个节点上分片的数量以及分片中的索引。基于下面的两个理由,集群的balance既不会考虑分片的大小,也不会考虑每一个节点上磁盘可用的空间:

    • 磁盘的使用随着时间发生变化。平衡不同节点的磁盘使用将会有很多更多的分片移动,perhaps even wastefully undoing earlier movements。移动一个分片会消耗例如I/O资源以及网络带宽,并且可能从文件系统缓存中换出(evict)数据。这些资源最好用于你的查询和索引。

    • 集群中每一个节点有相同的磁盘使用在性能上通常没有有不同磁盘使用的性能高,只要所有的磁盘不是太满

      你可以使用下面的设置控制基于磁盘的分配:

    cluster.routing.allocation.disk.threshold_enabled

      Dynamic)默认值为true。设置为false则关闭基于磁盘的分配。

    cluster.routing.allocation.disk.watermark.low

      Dynamic)控制磁盘使用量的水位下限(low watermark)。默认值为85%。意味着Elasticsearch不会将分片分配到磁盘使用超过85%的节点上。该值也可以是一个字节单位的值(例如500mb),使得当磁盘空间小于指定的值时就不让Elasticsearch分配分片到这个节点。这个设置不会影响新创建的索引的主分片,但是会组织副本分配的创建。

    cluster.routing.allocation.disk.watermark.high

      Dynamic)控制磁盘使用量的水位上限。默认值为90%,意味着Elasticsearch将对磁盘使用量超过90%的节点上的分片进行relocate。该值也可以是一个字节单位的值(跟low watermark类似)。使得当磁盘空间小于指定的值时就把该节点上的分片进行relocate。这个设置会影响所有分片的分配,无论之前是否已经分配。

    cluster.routing.allocation.disk.watermark.enable_for_single_data_node

      Static) 在更早的发布中,当做出分配决策时,对于单个数据节点的集群是不会考虑disk watermark的。在7.14之后被值为deprecated并且在8.0移除。现在这个设置唯一合法的值为true。这个设置在未来的发布中移除。

    cluster.routing.allocation.disk.watermark.flood_stage

      Dynamic)控制flood stage watermark。只要至少有一个节点超过该值,分配到这个节点的一个或者分片对应的索引会被Elasticsearch强制置为read-only index block(index.blocks.read_only_allow_delete)。这个设置是防止节点发生磁盘空间不足最后的手段。当磁盘使用量降到high watermark后会自动释放index block。

    NOTE:你不能在设置中混合使用比例值(percentage)和字节值(byte value)。要么所有的值都是比例值,要么都是字节值。这种强制性的要求使得Elasticsearch可以进行一致性的处理。另外要确保low disk threshold要低于high disk threshold,并且high disk threshold要低于flood stage threshold。

      下面的例子中在索引my-index-000001上重新设置read-only index block:

    cluster.routing.allocation.disk.watermark.flood_stage.frozen

      Dynamic)用于专用的frozen node,控制flood stage watermark,默认值为95%

    cluster.routing.allocation.disk.watermark.flood_stage.frozen.max_headroom

      Dynamic)用于专用的frozen node,控制flood stage watermark的head room。当cluster.routing.allocation.disk.watermark.flood_stage.frozen没有显示设置时默认值为20GB。该值限制(cap)了专用的frozen node上磁盘的空闲量。

    cluster.info.update.interval

      Dynamic)Elasticsearch定时检查集群中每一个节点上磁盘使用情况的时间间隔。默认值为30s

    NOTE:比例值说的是(refer to)已使用的磁盘空间,而字节值说的是剩余磁盘空间。这可能会让人疑惑,因为它弄反了高和低的含义。比如,设置low watermark为10GB,high watermark为5GB是合理的,反过来设置的话就不行

      下面的例子讲low watermark的值设置为至少100gb,high watermark的值设置为至少50gb,flood stage watermark的值为10gb,并且每一分钟进行检查:

    Shard allocation awareness

      你可以自定义节点属性作为感知属性(awareness attributes)让Elasticsearch在分配分片时考虑你物理硬件的配置。如果Elasticsearch知道哪些节点在同一台物理机上、同一个机架(rack)、或者同一个区域,使得在发布主分片跟副本分片时能最低限度的降低丢失所有副本分片的风险。

      当使用(Dynamic)的cluster.routing.allocation.awareness.attributes的设置开启awareness attribute后,分片只会被分配到设置了awareness attributes的节点上。当你使用多个awareness attribute时,Elasticsearch在分配分片时会单独地(separately)考虑每一个attribute。

    NOTE: attribute values的数量决定了每一个位置上副本分配的分配数量。如果在每一个位置上的节点数量是unbalanced并且有许多的副本,副本分片可能不会被分配

    Enabling shard allocation awareness

      开启分片的分配awareness,需要:

    1. 使用一个自定义的节点属性来指定每个节点的位置。如果你想要Elasticsearch在不同的机架间发布分片,你可能需要在配置文件elasticsearch.yml上设置一个名为rack_id的属性。

      你也可以在启动的时候设置自定义的属性。

    1. 在每一个master-eligible node的配置文件elasticsearch.yml上设置cluster.routing.allocation.awareness.attributes,告诉Elasticsearch在分配分片的时候要考虑一个或者多个awareness attribute。

      用逗号分隔多个属性。

      你也可以使用cluster-update-settings API来设置或者更新集群的awareness attributes。

      基于上述的配置例子,如果你启动了两个节点并且都设置node.attr.rack_idrack_one并且为每个index设置5个主分片,每个主分片设置一个副本分片,那么这两个节点都包含所有的主分片以及副本分片。

      如果你增加了两个节点并且都设置node.attr.rack_idrack_two,Elasticsearch会把分片移动到新的节点,ensuring(if possible)相同的副本分片不会在相同的机架上。

      如果rack_two失败并关闭了它的两个节点,默认情况下,Elasticsearch会将丢失的副本分片分配给rack_one中的节点。为了防止特定分片的多个副本被分配到相同的位置,可以启用forced awareness。

    Forced awareness

      默认情况下,如果一个位置失败了(one location fails),Elasticsearch将缺失的分片分配到剩余的位置。可能所有的位置都有足够的资源来存放主分片跟副本分片,也有可能某个位置无法存储所有的分片。

      为了防止某个位置因为失败事件(event of failure)而造成负载过高(overload),你可以设置cluster.routing.allocation.awareness.force使得副本分片不会被分配直到其他位置可以被分配。

      比如说,如果你有一个awareness attribute 名为zone并且在两个节点分别配置zone1zone2,那么在只有一个zone可用的情况,你可以使用forced awareness来防止Elasticsearch分配副本分片。

      为awareness attribute指定所有可能的值。

      基于上述的配置例子,如果启动了两个节点并且设置node.attr.zone的值为zone1并且为每个index设置5个分片,每个分片设置一个副本分片,那么Elasticsearch会创建索引并且分配5个主分片但是不会有副本分片。只有某个节点设置node.attr.zone的值为zone2才会分配副本分片。

    Cluster-level shard allocation filtering

      你可以使用cluster-level shard allocation filters来控制Elasticsearch从任何索引分配分片的位置。结合per-index allocation filteringallocation awareness来应用集群级别(cluster wide)的filter。

      Shard allocation filters可以基于自定义的节点属性或者内建的属性:_name, _host_ip, _publish_ip, _ip, _host,_id_tier

      cluster.routing.allocation设置是动态的Dynamic,允许将live indices从一组节点上移动到其他组。只有在不破坏路由约定(routing constraint)下才有可能重新分配分片,比如说不会将主分片和它的副本分片分配到同一个节点上。

      最常用的cluster-level shard allocation filtering用例是当你想要结束(decommission)一个节点。要在关闭节点之前将分片移出节点,您可以创建一个过滤器,通过其 IP 地址排除该节点:

    Cluster routing settings
    cluster.routing.allocation.include.{attribute}

      (Dynamic)将分配分片到一个节点,这个节点的{attribute}至少是用逗号隔开的多个属性中的一个。

    cluster.routing.allocation.require.{attribute}

      (Dynamic)只将分片分配到一个节点,这个节点的{attribute}包含所有用逗号隔开的多个属性。

    cluster.routing.allocation.exclude.{attribute}

      (Dynamic)不将分片分配到一个节点,这个节点的{attribute}包含用逗号隔开的多个属性中的任意一个。

      cluster allocation settings支持下面的内建属性:

    _name根据node name匹配节点
    _host_ip根据host IP 地址(hostname关联的IP)匹配节点
    _publish_ip根据发布的IP地址匹配节点
    _ip根据_host_ip或者_publish_ip匹配节点
    _host根据hostname匹配节点
    _id根据node id匹配节点
    _tier根据节点的data tier角色匹配节点

    NOTE: _tier的过滤基于 node roles,只有部分角色是 data tier 角色,并且generic data role将会匹配任何的tier filtering。a subset of roles that are data tier roles, but the generic data role will match any tier filtering.

      在指定attribute values时可以使用通配符,例如:

    Miscellaneous cluster settings
    Metadata

      通过下面的设置可以将整个集群设置为read-only:

    cluster.blocks.read_only

      (Dynamic) 让整个集群read only(索引不支持写操作),metadata不允许更改(创建或者删除索引)

    cluster.blocks.read_only_allow_delete

      (Dynamic) 与cluster.blocks.read_only一样,但是允许删除索引来释放资源。

    WARNING: 不要依赖这些设置来防止集群发生变更。任何有cluster-update-settings API 访问权限的用户都可以让集群再次read-write

    Cluster shard limit

      基于集群中的节点数量,集群中分片的数量有一个soft limit。这是为了防止可能无意中破坏集群稳定性的操作。

    IMPORTANT:这个限制作为一个安全网(safety net),不是一个推荐的大小。你集群中可以安全的支持准确的分片数量取决于你的硬件配置跟工作负载,但是在大部分case下,这个limit应该还不错,因为默认的limit是非常大的。

      如果一个操作,比如创建新的索引,恢复snapshot index,或者打开一个关闭的索引会导致集群中的分片数量超过限制。那这个操作会失败并且给出shard limit的错误。

      如果由于node membership的变化或者设置的变更使得集群已经超过了限制,所有创建或者打开索引的操作都会失败直到下文中将介绍的提高limit或者关闭删除一些索引使得分片的数量降到了limit以下。

      对于normal indices(non-frozen),每一个non-frozen data node上cluster shard limit的默认值是1000,对于frozen indices,每一个frozen data node上的默认值是3000。所有打开的索引的主分片跟副本分片的数量都会纳入到统计中(count toward the limit),包括未分配的分片。例如5个主分片和2个副本的数量为15个分片。关闭的索引不会参与分片的统计。

      你可以使用下面的方式动态的调整cluster shard limit:

    cluster.max_shards_per_node

      (Dynamic) 限制集群中主分片跟副本分片的总数量。Elasticsearch使用下面的公式统计limit:

      cluster.max_shards_per_node * number of non-frozen data nodes

      关闭的索引不会纳入到统计中。默认是1000。没有data node的集群是没有限制的。

      超过上限后,Elasticsearch会reject创建更多分片的请求。比如集群的cluster.max_shards_per_node的值是100,并且三个data node就有300的分片数量限制。如果集群中已经包含了296个分片,Elasticsearch会reject增加5个或者更多分片数量的请求。

      注意的是frozen shard有它们自己独立的限制。

    cluster.max_shards_per_node.frozen

      (Dynamic) 限制集群中主分片跟replica frozen shard的总数量。Elasticsearch使用下面的公式统计limit:

      cluster.max_shards_per_node * number of frozen data nodes

      关闭的索引不会纳入到统计中。默认是3000。没有frozen data node的集群是没有限制的。

      超过上限后,Elasticsearch会reject创建更多frozen shard的请求。比如集群的cluster.max_shards_per_node.frozen的值是100,并且三个frozen data node就有300的分片数量限制。如果集群中已经包含了296个分片,Elasticsearch会reject增加5个或者更多frozen shard数量的请求。

    NOTE: These setting do not limit shards for individual nodes. 可以使用设置cluster.routing.allocation.total_shards_per_node来限制每一个节点上的分片数量。

    User-defined cluster metadata

      可以通过Cluster Settings API来存储以及查询用户自定义的集群元信息(User-defined cluster metadata)。可以用来存储任意的(arbitrary),很少更改(infrequently-changing)的关于集群的信息,而不需要创建索引来存储这些信息。使用以cluster.metadata为前缀的任意的key来存储信息。例如,在cluster.metadata.administrator这个key下存储管理员的email地址,如下所示:

    IMPORTANT: User-defined cluster metadata不要存储敏感的或者机密信息。任何人都可以通过Cluster Get Settings API访问存储在User-defined cluster metadata的信息,并且会被记录在Elasticsearch日志中。

    Index tombstones

      集群状态(cluster state)维护者index tombstone来显示的告知(denote)被删除的索引。集群状态维护tombstone的数量,通过下面的设置来进行控制:

    cluster.indices.tombstones.size

    Static)当发生删除时,Index tombstones会阻止不属于集群的节点加入集群并重新导入索引,就好像delete was never issued。为了防止增长的太大,我们只保留最新的cluster.indices.tombstones.size数量的删除,默认值是500。You can increase it if you expect nodes to be absent from the cluster and miss more than 500 deletes. We think that is rare, thus the default. Tombstones don’t take up much space, but we also think that a number like 50,000 is probably too big.

      如果 Elasticsearch 遇到当前集群状态中不存在的索引数据,则这些索引被认为是dangling。 例如,如果你在 Elasticsearch 节点离线时删除超过 cluster.indices.tombstones.size 的索引,就会发生这种情况。

      你可以使用Dangling indices API来进行管理。

    Logger

      这个设置用来控制日志,使用logger.为前缀的key来动态的更新。发布下面的请求(issue this request)来提高indices.recovery模块的日志等级为DEBUG

    Persistent tasks allocation

      Plugin可以创建一系列称为persistent task的任务。这些任务通常是long-lived并且存储在cluster state中,并且允许在一次full cluster restart后恢复(revive)这些任务。

      每一次创建一个persistent task时,master node会负责将任务分配到集群中的一个节点。然后被分配的节点会pick up这个任务然后在本地执行。通过下面的设置来控制被分配的persistent task的运行:

    cluster.persistent_tasks.allocation.enable

    (Dynamic)开启或者关闭persistent task的分配:

      这个设置不会影响已经执行的persistent task。只有最新创建的,或者必须要重新被分配的persistent task才会收到这个设置的影响。

    cluster.persistent_tasks.allocation.recheck_interval

    (Dynamic)master node会自动的检查在cluster state发生重大变化(change significantly)后persistent tast是否需要被分配。然而,也会有其他的一些因素,比如说memory usage,这个会影响persistent task能否被分配但这不会引起cluster state的变更。这个设置控制了检查的间隔。默认是30秒。最小允许的时间为10秒。

    Cross-cluster replication settings

    (8.2)link

      可以使用cluster update settings API动态更新集群中的CCR(cross-cluster replication)设置。

    Remote recovery settings

      下面的设置可以用于在remote recoveries中限制数据传输速率:

    ccr.indices.recovery.max_bytes_per_sec (Dynamic)

      用来限制每一个节点上inbound和outbound remote recovery traffic。由于这个设置是应用到每一个节点上,但是可能存在许多的节点并发的执行remote recoveries,remote recovery占用的流量可能比这个限制高。如果这个值设置的太高,那么会存在这么一种风险,即正在进行中的recoveries会过度消费带宽 ,使得集群变得不稳定。这个设置应该同时被leader和follower clusters使用。例如,如果在leader上设置了20mb,leader将只能发送20mb/s到follower,即使follower可以达到60mb/s。默认值为40mb

    Advanced remote recovery settings

      下面的专家级设置(expert settings)用于管理remote recoveries时的资源消费。

    ccr.indices.recovery.max_concurrent_file_chunks (Dynamic)

      控制每个recovery中并发请求文件块(file chunk)的数量。由于多个remote recoveries已经在并发运行,增加这个专家级设置可能只有助于没有达到总的inbound and outbound remote recovery traffic的单个分片的remote recovery,即上文中的ccr.indices.recovery.max_bytes_per_secccr.indices.recovery.max_concurrent_file_chunks的默认值为5。允许最大值为10

    ccr.indices.recovery.chunk_size (Dynamic)

      控制在文件传输时,follower请求的文件块的大小。默认值为1mb

    ccr.indices.recovery.recovery_activity_timeout (Dynamic)

      控制recovery的活跃(activity)超时时间。这个超时时间主要是应用在leader集群上。在处理recovery期间,leader cluster必须打开内存资源提供数据给follower。如果leader在周期时间内没有接收到follower的接收请求,leader会关闭资源。默认值为60s

    ccr.indices.recovery.internal_action_timeout (Dynamic)

      控制在remote recovery处理期间每一个网络请求的超时时间。某个单独的动作(individual action)超时会导致recovery失败。默认值为60s

    Discovery and cluster formation settings

      Discovery and cluster formation受到下面设置的影响:

    discovery.seed_hosts

      Static))提供集群中master-eligible node的地址列表。可以是单个包含地址,用逗号隔开的字符串。每一个地址有host:port或者host的格式。host可以是hostname(可以用DNS解析)、IPv4地址、IPv6地址。IPv6地址必须用{}包裹。如果hostname用DNS解析出多个地址,Elasticsearch会使用所有的地址。DNS基于JVM DNS caching进行查找(lookup)。如果没有指定port,会有序检查下面的设置来找到port

    1. transport.profiles.default.port

    2. transport.port

      如果没有设置上面的配置,则port的默认值为9300discovery.seed_hosts的默认值为["127.0.0.1", "[::1]"]。见discovery.seed_hosts

    discovery.seed_providers

      Static))指定seed hosts provider的类型,用于获取启动发现程序(discovery process)时需要用到的seed nodes地址。默认情况为settings-based seed hosts provider,它包含了discovery.seed_hosts中的seed node 地址。

    discovery.type

      Static))指定Elasticsearch是否形成一个多节点的(multiple-node)的集群,默认值为multi-node,意味着Elasticsearch在形成一个集群时会发现其他节点并且允许其他节点随后加入到这个集群。如果设置为single-node,Elasticsearch会形成一个单节点(single-node)集群并且suppresses the timeout set by cluster.publish.timeout。当你想要使用这个设置的时候,见Single-node discovery了解更多的信息

    cluster.initial_master_nodes

      Static))在全新的集群中初始化master-eligible node集合。默认情况下是空值,意味着这个节点想要加入到一个引导后(bootstrapped)的集群。集群一旦形成后需要移除这个设置。当重启一个节点或者添加一个新的节点到现有的集群中时不要使用这个设置。见cluster.initial_master_nodes

    Expert settings

      Discovery and cluster formation受到下面专家级设置(expert settings)的影响,当然我们不推荐修改这些设置的默认值。

    WARNING:如果你调整了集群中的这些设置,可能会无法正确的形成一个集群或者可能集群变得不稳定,或者无法处理(intolerant)对于一些故障。

    discovery.cluster_formation_warning_timeout

      Static))尝试形成一个集群时,多长时间后仍然没有形成集群,开始记录未形成集群的警告日志的设置。默认值为10s。如果在discovery.cluster_formation_warning_timeout的时间内没有形成一个集群,那节点会记录一个包含master not discovered的warnning message,它描述了当前discovery process当前的状态。

    discovery.find_peers_interval

      Static))一个节点尝试新一轮discovery的时间间隔。默认值为1s

    discovery.probe.connect_timeout

      Static))尝试连接每一个地址的连接等待时间。默认值为30s

    discovery.probe.handshake_timeout

      Static))尝试通过handshake识别remote node的等待时间。默认值为30s

    discovery.request_peers_timeout

      Static))在认为请求失败时,询问其peer后的等待时间。默认值为3s

    discovery.find_peers_warning_timeout

      Static))节点尝试discover它的peers并开始记录为什么尝试连接失败的verbose message的时间。默认值为3m

    discovery.seed_resolver.max_concurrent_resolvers

      Static))DNS并发解析seed node的地址时允许的并发量。默认值为10

    discovery.seed_resolver.timeout

      Static))DNS解析seed note的地址的超时时间。默认值为5s

    cluster.auto_shrink_voting_configuration

      (Dynamic)控制voting configuration是否自动的去除(shed)不能担任voting的节点(departed node),只要它至少还包含3个节点。默认值为true。如果设置为false。voting configuration不会自动的进行收缩,你必须通过voting configuration exclusions API手动的移除不能担任voting的节点(departed node)。

    cluster.election.back_off_time

      Static)) (未完成)

    cluster.election.duration
    cluster.election.initial_timeout

    Field data cache settings

    (8.2)link

      field data cache中包含了field dataglobal ordinals,它们都是用来让某些字段能够用于聚合。由于是on-heap的数据结构,所以很有必要监控缓存的使用情况。

    Cache size

      构建cache中实体(entities)的开销是很昂贵的,所以默认情况下会保留载入到内存的entities。默认的cache大小是没有限制的,cache大小会不断增大直到达到field data circuit breaker设定的上限。这种行为可以配置。

      如果设置了cache大小的上限,cache将会清除cache中最近更新的实体(If the cache size limit is set, the cache will begin clearing the least-recently-updated entries in the cache)。这个设置会自动的避免circuit breaker limit,代价就是需要重新构建cache。

      如果达到了circuit breaker limit,后续会增加cache大小的请求将被阻止。在这种情况下你必须要手动clear the cache

    indices.fielddata.cache.size

      Static)) field data cache的最大值。比如节点堆空间大小的38%,或者是一个absolute value,12GB。默认是没有限制。如果选择设置这个值,这个值应该小于Field data circuit breaker limit

    Monitoring field data

      你可以使用nodes stats APIcat fielddata API来监控filed data的内存使用情况以及 field data circuit breaker。

    Index lifecycle management settings in Elasticsearch

    link

    Index level settings
    index.lifecycle.origination_date
    index.lifecycle.parse_origination_date
    index.lifecycle.step.wait_time_threshold

    Index management settings

    link

    stack.templates.enabled

    Index recovery settings

    link

    Recovery settings

    Indexing buffer settings

    (8.2)link

      indexing buffer用来缓存新添加的文档,当缓冲区满后,缓存中的文档会被写入到一个段中并且存放到磁盘上。Indexing buffer的大小被节点上的所有分片共享。

      下面的设置都是静态的必须在集群中的每一个节点上配置:

    indices.memory.index_buffer_size

      Static)可以是百分比或者是字节单位的数值。默认是10%意味着堆内存的10%会被分配给节点用于Indexing buffer,并且被节点上所有的分片共享。

    indices.memory.min_index_buffer_size

      Static)如果index_buffer_size指定为百分比,那这个设置用来指定为一个绝对最小值(absolute minimum)。默认是是48m

    indices.memory.max_index_buffer_size

      Static)如果index_buffer_size指定为百分比,那这个设置用来指定为一个绝对最大值(absolute maximum)。默认是无限制的。

    License settings

    link

    Local gateway settings

    link

    Dangling indices

      当一个节点加入到集群,如果它发现本地数据目录中存在一些分片,这些分片在集群中的其他节点上不存在,那么就认为这些分片属于"dangling" index。你可以使用Dangling indices API列出,导入或者删除dangling index。

    Logging

    link

    Machine learning settings in Elasticsearch

    link

    Node

    (8.2)link

      任何时候在你启动了一个Elasticsearch的实例时,即你正在启动一个节点(Node)。相互连接的节点集合成为一个集群(cluster)。如果你运行了 一个单个节点的Elasticsearch,那么你拥有一个只有一个节点的集群。

      默认情况下,集群中的每个节点都可以处理 HTTP and transport的传输。transport layer只用来处理节点之间的交互,HTTP layer用于REST clients 。

      所有的节点都知道集群中的其他节点并且可以转发客户端的请求到合适的节点。

    Node roles

      你可以在elasticsearch.yml中设置node.roles来定义一个节点的角色。如果你设置了node.roles,这个节点只会被分配为你指定的角色。如果你不指定node.roles,这个节点会被分配为下面的角色:

    IMPORTANT:如果你设置了node.roles,你要保证你的集群需要你指定的这些角色。每一个集群需要有下面的角色:

    • master

    • (data_content和data_hot) 或者 data

    一些Elastic Stack 功能同样要求指定下面的节点角色:

    • 跨集群搜索(Cross-cluster search)和跨集群副本(Cross-cluster replication)需要remote_cluster_client角色

    • Stack Monitoring和ingest pipeline需要ingest角色

    • Fleet,Elastic Security应用,和transforms需要transform角色。remote_cluster_client角色同样需要用于这些功能中的cross-cluster search

    • Machine learning功能,比如异常检测(anomaly detection)需要ml角色

      随着集群的增长,特别是集群中有大规模的machine learning任务、continuous transforms,我们建议从专用的data node、machine learning node、transform node中分离出master-eligible节点。

    Master-eligible node拥有master角色的节点,使得节点有资格被选举为master node来控制整个集群
    Data node拥有data角色的节点,data node保留数据并且执行相关操作例如CRUD、查询、聚合。一个拥有data角色的节点可以添加任何其他特定的数据节点角色,例如hot 、warm等
    Ingest node拥有ingest角色的节点,ingest node可以对文档进行ingest pipeline使得可以在索引前transform或者丰富文档。对于繁重的ingest,使用专用的ingest node并且让拥有master或者data角色的节点不要有ingest角色
    Remote-eligible node拥有remote_cluster_client角色的节点,使得这个节点有资格成为一个remote client
    Machine learning node拥有ml角色的节点,如果你想要使用machine learning功能,你的集群中至少要有一个machine learning node。见Machine learning settingsMachine learning in the Elastic Stack了解更多信息
    Transform node拥有transform角色的节点。如果想要使用transform,你的集群中至少要有一个transform node。见Transforms settingsTransforming data了解更多信息

    NOTE:Coordinating node 一些像查询请求或者块索引(bulk-indeing)的请求可能涉及不同data node上的数据。一次查询请求,例如,搜索请求分两个阶段执行,由接收客户端请求的节点进行协调 - coordinating node。

    在scatter阶段,coordinating node将请求转发给持有数据的数据节点。 每个数据节点在本地执行请求并将其结果返回给coordinating node。 在收集(gather)阶段,协调节点将每个数据节点的结果减少为单个全局结果集。

    每个节点都隐含的是一个coordinating node。 这意味着通过设置 node.roles 为空的角色列表的节点将作为coordinating node,并且不能被关闭这种设定。 因此,这样的节点需要有足够的内存和 CPU 才能处理收集阶段。

    Master-eligible node

      master node负责轻量级(lightweight)的集群范围(cluster-wide)的一些工作,比如创建、删除一个索引,跟踪哪些节点是集群的一部分以及决定给哪里节点分配分片。稳定的master node对于集群的健康是十分重要的。

      一个不是voting-only的master-eligible node会在master election process中被选为master node。

    IMPORTANT: master node必须有一个path.data目录,其内容在重启后仍然存在,跟data node一样,这个目录中存放了集群的元数据(cluster metadata)。集群元数据描述了如何读取存储在data node上的数据,所以如果丢失了集群元数据就无法读取data node上的数据。

    Dedicated master-eligible node

      满足被选举为master的节点为了能完成它的职责所需要的资源对于集群的健康是十分重要的。如果被选举为master的节点因为其他的工作导致超负荷了,那么集群将无法较好的运行。避免master node工作超负荷最可靠的方法就是将所有master-eligible node只配置为master角色,让它们作为专用的master-eligible node(dedicated master-eligible node),让它们集中做好管理集群的工作。Master-eligible node可以跟coordinating nodes一样将客户端的请求路由到集群中的其他节点,但是你不应该让专用的master-eligible node做这些事情。

      在一些小规模或者轻负载(lightly-loaded)的集群中,如果master-eligible node有其他的角色和职责也可以正常的运行,但是,一旦集群中包含多个节点,通常使用专用的master-eligible node是有意义的。

      通过设置下面的配置来创建一个专用的master-eligible节点:

    Voting-only master-eligible node

      voting-only master-eligible node是会参与master elections的节点,但是不会成为集群的master节点。特别在于一个voting-only node可以成为选举过程中的tiebreaker。

      使用"master-eligible"这个词来描述一个voting-only node看起来有点让人困惑,因为这种节点是完全没资格成为master节点的。使用这个术语是因为历史的原因(This terminology is an unfortunate consequence of history):master-eligible node是那些参与选举、集群状态发布(cluster state publication)期间执行一些任务的节点,而voting-only node有着相同的工作职责(responsibility)只是它们不会被选举为master节点。

      通过添加mastervoting_only角色来配置一个master-eligible node为voting-only node。下面的例子创建了一个voting-onyl data node:

    IMPORTANT:只有拥有master角色的节点才可以标记为拥有voting_only角色。

      高可用(HA:high availability)的集群要求至少有三个master-eligible node,它们中的至少两个节点不是voting-only node。这样的集群才能够在其中一个节点发生故障后选出一个master节点。

      由于voting-only node不会被选举为master节点,所以相较于真正的master node,它们需要较少的堆以及较低性能的CPU。然而所有的master-eligible node,包括voting-only node,相较于集群中的其他节点,它们需要相当快速的持久存储以及一个可靠的低延迟的网络连接,因为它们处于publishing cluster state updates的关键路径(critical path)上。

      Voting-only master-eligible node在集群中可能被分配其他的角色。比如说一个节点同时是data node或者Voting-only master-eligible node。一个专用的voting-only master-eligible node 在集群中是不会有其他的角色的。通过下面的方式来创建一个专用的voting-only master-eligible nodes:

    Data node

      data note保留了你索引的文档的分片。data note处理像CRUD、查询、聚合的操作。这些操作有I/O-, memory-, and CPU-intensive。监控这些资源以及工作负载大后增加更多的data node是非常重要的。

      拥有专用的data node最主要的好处是将master和data角色分开出来。

      通过下面的方式创建一个专用的data node:

      多层部署架构(multi-tier)中,你可以根据为data node分配不同数据层对应的数据角色(data role):data_content,data_hot, data_warm, data_cold, 或者data_frozen。一个节点可以属于多个层,但是已经拥有一个指定数据角色的节点不能有通用的data角色(generic data role)。

    Content data node

      Content data node属于content tier的一部分。存储在content tier上的数据通常是iterm的集合比如说产品目录(product catalog)或者文章归档(article archive)。跟时序数据不同的是,这些内容的价值随着时间的流逝相对保持不变的,所以根据这些数据的寿命(age)将它们移到性能不同的数据层是不合理的。Content data通常有长时间保留(retention)的要求,并且也希望无论这些数据的寿命的长短,总是能很快的检索到。

      Content tier node会为查询性能做优化-优先优化IO吞吐使得可以处理复杂的查询,聚合并且能很快的返回结果。同时这类节点也用来索引,content data通常没有例如log和metric这种时序数据一样高的ingest rate。从弹性的角度(resiliency perspective)看,当前层的索引应该配置为使用一个或者多个副本(replica)。

      Content tier是必须要有的(required)。系统索引以及其他不是data stream的索引都会被自动分配到content tier。

      通过下面的方式创建一个专用的content node:

    Hot data node

      hot data node是 hot tier的一部分。hot tier是Elasticsearch中时序数据的入口点(entry point),并且保留最近,最频繁搜索的时序数据。hot tier节点上的读写速度都需要很快,要求更多的硬件资源和更快的存储(SSDs)。出于弹性目的,hot tier上的索引应该配置一个或多个副本分片。

      hot tier是必须要有的。data stream中新的索引会被自动分配到hot tier。

      通过下面的方式创建一个专用的hot node:

    Warm data node

      warm data node是warm tie的一部分。一旦时序数据的访问频率比最近索引的数据(recently-indexed data)低了,这些数据就可以移到warm tier。warm tier通常保留最近几周的数据。允许更新数据,但是infrequent。warm tier节点不需要像hot tier一样的快。出于弹性目的,warm tier上的索引应该配置一个或多个副本分片。

      通过下面的方式创建一个专用的warm node:

    Cold data node

      cold data node是cold tier的一部分。当你不再经常(regular)搜索时序数据了,那可以将它们从warm tier移到cold tier。数据仍然可以被搜索到,在这一层的通常会被优化成较低的存储开销而不是查询速度。

      为了更好的节省存储(storage saveing),你可以在cold tier保留fully mounted indicessearchable snapshots。跟常规索引(regular index)不同的是,这些fully mounted indices不需要副本分片来满足可靠性(reliability),一旦出现失败事件,可以从底层(underlying)snapshot中恢复。这样可以潜在的减少一般的本地数据存储开销。snapshot仓库要求在cold tier使用fully mounted indices。Fully mounted indices只允许读取,不能修改。

      另外你可以使用cold tier存储常规索引并且使用副本分片的方式,而不是使用searchable snapshot,这样会帮你在较低成本的硬件上存储较老的索引,但是相较于warm tier不会降低磁盘空间。

      通过下面的方式创建一个专用的cold node:

    Frozen data node

      frozen data node是frozen tier的一部分。一旦数据不需要或者很少(rare)被查询,也许就可以将数据从cold tier移到frozen tier,where it stays for the rest of its life。

      frozen tier需要用到snapshot repository。frozen tier使用partially mounted indices的方式存储以及从snapshot repository中载入数据。这样仍然可以让你搜索frozen数据并且可以减少本地储存(local storage)和操作开销(operation cost)。因为Elasticsearch必须有时从snapshot repository中提取(fetch)数据,在frozen tier的查询速度通常比cold tier慢。

    Ingest node

      Ingest node可以执行pre-processing pipelines。由一个或者多个ingest processor组成。基于ingest processor执行的操作类型以及需要的资源,拥有一个专用的ingest node还是有意义的,使得这个节点只运行指定的任务。

      通过下面的方式创建一个专用的Ingest node:

    Coordinating only node

      如果你的节点不需要(take away)处理master职责(duty)、保留数据、pre-process文档的能力,那么你还剩下一个coordinating only node,只能处理路由请求、查询的reduce phase、以及分布式的块索引(bulk Indexing)。本质上coordinating only node表现为像一个智能的负载均衡节点。

      在大规模的集群中将coordinating node角色从data node和master-eligible node中剥离(offload)出来能体现coordinating only nodes的益处。这些节点加入到集群中并且接收完整的cluster state,就像每一个其他的节点一样,它们使用cluster state将请求路由到合适的地方。

    WARNING:集群中添加太多的coordinating only nodes会增加整个集群的负担(burden),因为被选举为master的节点必须等待从每一个节点更新后的cluster state的回应。不能过度夸大(overstate)coordinating only node的益处-data node也可以实现跟coordinating only nodes相同的目的(same purpose)

      通过下面的方式创建一个专用的coordinating node:

    Remote-eligible node

      一个remote-eligible node扮演一个cross-cluster client的角色以及连接remote clusters。一旦连接后,你可以使用cross-cluster search搜索远程的集群。你可以使用cross-cluster replication在集群间同步数据。

    Machine learning node

      Machine learning node运行任务并且处理machine learning API的请求。见Machine learning settings查看更多的信息

      通过下面的方式创建一个专用的machine learning node:

      remote_cluster_client是可选的,但是强烈建议配置进去。否则当使用machine learning jobs 或者 datafeed时,cross-cluster search会失败。如果在你的异常检测任务中使用corss-cluster search,在所有的master-eligible node上同样需要remote_cluster_client这个角色。否则 datafeed无法开始,见Remote-eligible node

    Transform node

      Transform node运行transforms并且处理transform API的请求。见Transforms settings

      通过下面的方式创建一个专用的transform node:

      remote_cluster_client是可选的,但是强烈建议配置进去。否则当使用transforms时,cross-cluster search会失败。见Remote-eligible node

    Changing the role of a node

      每一个data node在磁盘上维护下面的数据:

      同样的,每一个master-eligible node在磁盘上维护下面的数据:

      每一个节点在启动时会检查数据路径的内容。如果发现了非预期(unexpected)的数据,节点将拒绝启动。这样就可以避免导入会导致红色的集群健康的unwanted dangling indices。更准确的说,如果在启动时发现磁盘上有分片数据但是这个节点没有data角色,那么这个节点不会启动。如果在启动时发现磁盘上有索引元数据但是这个节点没有datamaster角色,那么这个节点不会启动。

      可以通过更改elasticsearch.yml然后重启节点来修改节点的角色。这就是众所周知的 repurposing一个节点。为了能满足上文中描述的对非预期的检查,在启动没有data或者master角色的节点前,你必须执行一些额外的步骤来为repurposing做准备。

      如果没有办法按照这些额外的步骤实现你的目的,你可以使用elasticsearch-node repurpose工具来删除阻止节点启动的多余的数据(excess data)。

    Node data path settings
    path.data

      每个data node、master-eligible node都要访问一个数据目录,这个目录中存放了分片、索引和集群元数据。path.data的默认值是$ES_HOME/data但是可以在elasticsearch.yml中配置一个全路径或者一个相对于$ES_HOME的相对路径:

      跟其他的节点设置一样,可以在命令行上指定:

      path.data的内容在启动时必须存在,因为这是你数据存储的位置。Elasticsearch 要求文件系统像由本地磁盘支持一样运行,但这意味着只要远程存储正常运行,它就可以在配置正确的远程块设备(例如 SAN)和远程文件系统(例如 NFS)上正常工作,与本地存储没有什么不同。你可以在同一个文件系统上运行多个Elasticsearch节点,但是每个节点要有自己的数据路径。

      Elasticsearch集群的性能常常受制于底层存储的性能,所以你必须保证你的存储能有可以接受的性能范围内。一些远程存储的性能很差,尤其是在 Elasticsearch 施加(impose)的那种负载下,所以在使用特定的存储架构之前,请确保仔细地对你的系统进行基准测试。

    TIP:如果使用了.zip或者.tar.gz的发行版,path.data的值应该设置到Elasticsearch home目录以外的路径上,这样删除home目录时不会删除你的数据!RPM和Debian发行版已经为你做了这些工作。

    IMPORTANT:不要修改数据目录中的任何东西或者运行可能会影响这个目录中内容的程序。如果一些不是Elasticsearch的操作修改了数据目录的内容,那么Elasticsearch可能会发生故障,报告出corruption或者其他data inconsistencies,或者工作正常但是轻微的丢失了一些你的数据。不要尝试做文件系统级别的数据目录的备份。因为没有可用的方法来恢复这类备份。而是应该用 Snapshot and restore做安全的备份。不要在数据目录做病毒扫描,病毒扫描会使得Elasticsearch不能正确的工作并且可能会修改数据目录的内容。数据目录不包含可执行文件,因此病毒扫描只会发现误报

    Other node settings

      更多的跟节点相关的设置可以在Configuring ElasticsearchImportant Elasticsearch configuration找到,包括:

    Networking

    link

    Commonly used network settings
    Binding and publishing
    Advanced HTTP settings
    http.max_content_length
    Advanced transport settings
    Long-lived idle connections

    Node query cache settings

    (8.2)link

      filter context中的查询结果缓存在node query cache中使得可以快速的查询,这属于每个节点上的查询缓存(query cache),由所有的分片共享。缓存使用了LRU eviction policy:当缓存满了以后,最近最少使用的查询结果会被踢出(evict),为新的查询查询让路。你不能查看(inspect)查询缓存的内容。

      Term query以及在filter context使用外的查询没有缓存资格(eligible)。

      默认情况下,缓存保留最多10000个query,以及占用最多10%的总内存。若要判断某个query是否有资格被缓存,Elasticsearch维护了一个query history来track occurrence。

      缓存在每个段上进行,并且段中至少包含10000篇文档并且每个段中的文档数量至少是分片中文档总数的3%。由于是基于段的缓存,因此段的合并会使缓存的查询失效。

      下面的设置是static并且必须在集群中每个data node上配置:

    indices.queries.cache.size

      Static)为filter cache控制内存大小。可以是一个百分比的值,比如5%或者一个精确值,例如512mb。默认值为10%

    Query cache index settings

      下面的设置属于index setting,可以在每一个索引上配置。只能在索引创建时或者一个closed index上设置。

    index.queries.cache.enabled

      Static)控制是否开启查询缓存。可以是true(默认值)或者false

    Search settings

    (8.2)link

      下面的expert setting用来管理全局的查询和聚合限制。

    indices.query.bool.max_clause_count

      Static integer)一个查询能包含的clause的最大数量。默认值为4096

      这个设置限制了一颗query tree能包含的clause的最大数量。4096这个默认值已经是非常高了,通常来说该值是够用的。这个限制会应用于重写query(rewrite query),所以不仅仅是bool query,所有会重写为bool query的query,例如fuzzy query,都会有较高数量的clause。这个限制的目的是防止查询的范围变得很大,占用过多的CPU和内存。如果你一定要提高这个值,保证你已经竭尽全力尝试了所有其他的选项,否则就不要这么做。较高的值会导致性能降低以及内存问题,特别是在负载高或者资源较少的集群上。

      Elasticsearch提供了一些工具来防止遇到这个clause数量上限的问题,例如在terms query中,它允许查询许多不一样的值,但是它只作为一个clause。或者是带有index_prefixes选项的text字段,它会执行prefix query,这个query会膨胀为较高数量的term,但是只作为一个term query。

    search.max_buckets

      Dynamic,integer)在一次响应中,aggregation buckets 的最大分桶数量。默认值为65535。

      尝试返回超过这个限制的请求会返回一个错误。

    indices.query.bool.max_nested_depth

      Static integer)bool query的最大深度。默认值为20

      这个设置限制了bool query的嵌套深度。深度大的bool query可能会导致stack overflow。

    Security settings in Elasticsearch

    Realm settings
    Kerberos realm settings
    OpenID Connect realm settings

    Shard request cache settings

    (8.2)link

      当一个查询请求运行在一个或者多个索引上时,每一个参与的分片会在本地执行查询然后将结果返回到coordinating note,节点会结合(combine)分片级别(shard-level)的结果到一个"全局的"的结果集中。

      分片层的请求缓存模块会在每一个分片上缓存本地的结果。这允许经常使用(并且可能很重)的搜索请求几乎立即返回结果。请求缓存(request cache)非常适用于日志用例,因为这类数据只有最近的索引会持续更新,从旧的索引中获取的结果可以直接从缓存中返回。

    IMPORTANT:默认情况下,请求缓存在size=0时仅仅缓存查询请求的结果。所以不会缓存hits,但是它会缓存hits.total, aggregations以及suggestions

    大多数使用now(见 Date Math)的请求不能被缓存。

    使用脚本的查询使用了一些不确定的API调用不会被缓存,比如说Math.random() 或者 new Date()

    Cache invalidation

      The cache is smart。它可以跟非缓存的查询一样的近实时查询。

      当分片refresh后文档发生了变更或者当你更新了mapping时,缓存的结果会自动的被废止。换句话说,你总是可以从缓存中获得与未缓存搜索请求相同的结果。

      refresh的间隔时间越长意味着缓存的结果保留时间越长,即使文档已经发生了变化。如果缓存满了,基于LRU(least recently used)机制来丢弃缓存。

      可以通过clear-cache API手动将缓存置为过期的(expired):

    Enabling and disabling caching

      缓存默认开启,可以在创建一个新的索引时来关闭缓存:

      可以通过update-settings API来手动的开启或关闭缓存:

    Enabling and disabling caching per request

      request_cache 这个query-string参数可以用于在每一次请求中来开启或关闭缓存。如果设置了这个参数,会覆盖索引层(index-levele)的设置:

      请求中的size如果大于0的话则不会缓存即使在索引设置中开启了缓存。要缓存这些请求,你需要使用的query-string参数。

    Cache key

      使用完整的JSON计算出的hash值作为cache key。这意味着如果JSON发生了变更,比如说key的先后顺序发生了变化,那么对应的cache key就无法被识别。

    TIP:大多数 JSON 库都支持规范模式(canonical mode),可确保 JSON的key始终以相同的顺序发出。这种规范模式可以在应用程序中使用,以确保始终以相同的方式序列化请求。

    Cache settings

      缓存在节点层进行管理,缓存大小的最大值默认是堆内存的1%。可以通过config/elasticsearch.yml修改:

      同样的你可以使用indices.requests.cache.expire为缓存结果设置一个TTL,但是并没有理由要这么做。因为过时的结果(stale result)会在refresh后自动的废止。这个设置只是为了completeness(This setting is provided for completeness' sake only)。

    Monitoring cache usage

      缓存的大小(字节)和evictions的数量可以通过indices-stats接口来查看:

      或者通过nodes-stats接口查看:

    Snapshot and restore settings

    SLM settings
    slm.history_index_enabled
    slm.retention_schedule
    slm.retention_duration
    repositories.url.allowed_urls

    Transforms settings in Elasticsearch

    link

    Thread pools

    (8.2)link

      一个节点会使用多个线程池来管理内存消费(memory consumption)。许多的线程池使用队列hold住pending中的请求而不是丢弃。

      节点中有很多的线程池,下面介绍主要的几个线程池:

    generic

      用于一般的操作(例如background node discovery)。线程池类型是scaling

      用于count/search/suggest操作。线程池类型是fixed。线程数量为int((# of allocated processors * 3) / 2) + 1。队列大小为1000

    search_throttled

      用于在search_throttled indices上的count/search/suggest/get操作。线程池类型为fixed,线程数量为1,队列大小为100

    search_coordination

      用于轻量级的查询相关的协同操作(search-related coordination)。线程池类型为fixed,线程数量为a max of min(5, (# of allocated processors) / 2),队列大小为1000

    get

      用于get操作,线程池类型为fixed,线程数量为# of allocated processors,队列大小为1000

    analyze

      用于analyzer请求,线程池类型为fixed,线程数量为1,队列大小为16

    write

      用于单篇文档的 index/delete/update以及bulk的请求,线程池类型为fixed,线程数量为# of allocated processors,队列大小为10000。这个线程池的最大值是1 + # of allocated processors

    snapshot

      用于snapshot/restore请求,线程池类型为scaling,keep-alived的值为5m以及a max of min(5, (# of allocated processors) / 2)

    snapshot_meta

      用于读取snapshot repository metadata的请求,线程池类型为scaling,keep-alived的值为5m以及a max of min(50, (# of allocated processors) / 3)

    warmer

      用于segment warm-up的操作,线程池类型为scaling,keep-alived的值为5m以及a max of min(5, (# of allocated processors) / 2)

    refresh

      用于refresh的操作,线程池类型为scaling,keep-alived的值为5m以及a max of min(10, (# of allocated processors) / 2)

    fetch_shard_started

      用于列出分片状态(list shard state)的操作,线程池类型为scaling,keep-alived的值为5m以及a default maximum size of 2 * # of allocated processors

    fetch_shard_store

      用于列出分片存储(list shard store)的操作,线程池类型为scaling,keep-alived的值为5m以及a default maximum size of 2 * # of allocated processors

    flush

      用于flushtranslog fsync的操作,线程池类型为scaling,keep-alived的值为5m以及a max of min(10, (# of allocated processors) / 2)

    force_merge

      用于force merge操作,线程池类型为fixed,线程数量为1,队列大小为unbounded

    management

      用于集群管理,线程池类型为scaling,keep-alived的值为5m以及a default maximum size of 5

    system_read

      用于读取系统索引的操作,线程池类型为fixed,keep-alived的值为5m以及a default max of min(5, (# of allocated processors) / 2)

    system_write

      用于写入系统索引的操作,线程池类型为fixed,keep-alived的值为5m以及a default max of min(5, (# of allocated processors) / 2)

    system_critical_read

      用于读取关键系统索引(critical system indices)的操作,线程池类型为fixed,keep-alived的值为5m以及a default max of min(5, (# of allocated processors) / 2)

    system_critical_write

      用于写入关键系统索引(critical system indices)的操作,线程池类型为fixed,keep-alived的值为5m以及a default max of min(5, (# of allocated processors) / 2)

    watcher

      用于watch executions。线程池类型为fixed,以及a default max of min(5 * (# of allocated processors) , 50),队列大小为50

      线程池的设置是static,通过编辑elasticsearch.yml更改。下面的例子中更改了write线程池中的线程数量:

    Thread pool types

      下文中介绍的是线程池的类型以及对应的参数:

    fixed

      fixed类型的线程池中有固定数量的线程,以及一个队列(通常是有界的),当线程池中没有可用线程时,队列会hold住请求。

      size参数控制了线程的数量。

      queue_size控制了队列中的请求数量,当没有可用线程时,队列会hold住请求。默认情况下,该值为-1意味着队列是无界的。但一个新的请求到来时,如果队列已满则abort这个请求。

    scaling

      scaling类型的线程池中拥有动态数量的线程。线程数量跟工作负载成正比(proportional)。线程数量在参数coremax之间变化。

      keep_alive参数用于决定当线程池中的线程没有任何工作时,呆在线程池中的最大时间。

    Allocated processors setting

      处理器(processor)的数量会被自动的检测。线程池的会基于处理器的数量自动的设置。在有些情况下,覆盖(override)处理器的数量是很有用的。可以显示的(explicit)设置node.processors

      以下的情况要显示的覆盖设置node.processors

    1. If you are running multiple instances of Elasticsearch on the same host but want Elasticsearch to size its thread pools as if it only has a fraction of the CPU, you should override the node.processors setting to the desired fraction, for example, if you’re running two instances of Elasticsearch on a 16-core machine, set node.processors to 8. Note that this is an expert-level use case and there’s a lot more involved than just setting the node.processors setting as there are other considerations like changing the number of garbage collector threads, pinning processes to cores, and so on.

    2. Sometimes the number of processors is wrongly detected and in such cases explicitly setting the node.processors setting will workaround such issues.

      若要检查检查到的处理器的数量,使用nodes info AP带上os这个flag。

    Advanced configuration

    link

    Important system configuration

    link

    Configuring system settings

    (8.2)link

      根据你安装Elasticsearch时使用的安装包,以及你正在使用的操作系统,系统设置的配置位置略有不同。

      当使用.zip或者.tar.gz的安装包时,可以通过下面的方式配置系统设置:

      当使用RPM或者Debian发行版时,大多数的系统设置在system configuration file中设置,然而在使用systemd的系统中,要求在systemd configuration file中指定system limit。

    ulimit

      在linux系统中,ulimit用于临时更改资源限制(resource limit)。Limits通常需要使用root用户进行设置,然后切换到普通用户启动Elasticsearch。例如,将文件句柄(file handler)的最大数量设置为65,536(ulimit -n),你可以按照下面的方式进行设置:

      第1行,切换到root用户   第2行,设置打开的文件最大数量(max number of open files)   第3行,切换到普通用户来启动Elasticsearch   这个新的限制(new limit)只适用于当前会话(current session)   你可以通过ulimit -a查询(consult)当前目前所有的limit

    /etc/security/limits.conf

      在linux系统中,可以通过编辑文件/etc/security/limits.conf为linux的某个系统用户设置persistent limits。如果要为elasticsearch这个系统用户设置可以打开的文件最大数量为65,535,在文件中添加一行下面的内容:

      这个变更只有在elasticsearch这个用户下次打开一个新的session时才会生效。

    NOTE: Ubuntu and limits.conf 在Ubuntu中,由init.d启动的进程会忽略limits.conf文件,如果需要让这个文件生效,可以编辑/etc/pam.d/su然后注释下面这一行的内容:# session required pam_limits.so

    Sysconfig file

      当使用RPM或者Debian安装包时,可以在系统配置文件中指定系统变量:

    RPM/etc/sysconfig/elasticsearch
    Debian/etc/default/elasticsearch

      然而system limits需要通过systemd来指定。

    Systemd configuration

      当在使用systemd的系统上使用RPM或者Debian安装包时,system limits需要通过systemd来指定。

      systemd service file(/usr/lib/systemd/system/elasticsearch.service)中包含了默认的limit。

      你可以新增一个文件名为/etc/systemd/system/elasticsearch.service.d/override.conf(或者你可以执行sudo systemctl edit elasticsearch,它会在默认编辑器中自动打开文件),在这个文件中做如下的变更:

      完成更改后,运行下面的命令来reload units:

    Disable swapping

    (8.2)link

      大多数的操作系统会为文件系统缓存(file system cache)尽可能多的使用内存并且急切的(eagerly)将unused application memory交换出去(swap out)。这会导致部分JVM堆甚至executable page被交换到磁盘上。

      Swapping对性能、节点稳定影响是非常大的,无论如何(at all cost)都要避免。这会导致垃圾回收的时间达到分钟级别而不是毫秒级别,使得节点的响应时间变慢甚至与节点的断开连接。在弹性分布式系统中,让操作系统杀死节点反而更有效。

      有三种方法关闭swapping。较好的方法(prefer option)是完全的关闭swapping。如果不能用这个方法,那么基于你的环境选择最小化swappiness还是内存锁定。

    Disable all swap files

      通常Elasticsearch是一个box中唯一运行的服务,并且通过JVM参数来控制内存的使用,就没有必要开启swapping。

      在linux系统中,你可以运行下面的命令临时关闭swapping:

      这个操作不需要重启Elasticsearch。

      若要永久关闭,你需要编辑文件/etc/fstab,然后将所有包含swap的内容都注释。

      在Windows上,可以通过System Properties → Advanced → Performance → Advanced → Virtual memory达到相同的目的。

    Configure swappiness

      要确保Linux系统上另一个可用的选项:sysctl的vm.swappiness的值是1。这个选项会降低kernel进行swap的趋势,在正常情况下(normal circumstances)不会进行swapping,并且允许在紧急情况下运行将整个系统进行swapping。

    Enable bootstrap.memory_lock

      另一种方式是通过在Linux/Unix系统上使用mlockall或者是Windows系统上的VirtualLock,将进程地址空间锁定到RAM,防止Elasticsearch堆内存被swapping。

    NOTE: 一些平台在使用了memory lock后仍然会swap off-heap memory。为了防止swap off-heap memory,转而尝试disable all swap files

      elasticsearch.yml中设置bootstrap.memory_locktrue来开启memory lock:

    WARNING:如果尝试分配比可用内存更多的内存量,mlockall可能会导致JVM或者shell session退出。

      在启动Elasticsearch之后,你可以通过下面这个请求输出的mlockall的值检查是否应用了设置:

      如果你看到mlockall的值为false,那么意味着mlockall请求失败了。你可以在日志中看到包含Unable to lock JVM Memory的更详细的信息。

      在Linux/Unix系统上最有可能导致失败的原因是运行中的Elasticsearch没有权限来lock memory。可以通过下面的方式授权:

      另一个导致mlockall可能的原因是the JNA temporary directory (usually a sub-directory of /tmp) is mounted with the noexec option,可以使用ES_JAVA_OPTS环境变量为JNA指定一个临时的目录来解决:

      或者在配置文件jvm.options中设置这个JVM标志。

    File Descriptors

    (8.2)link

    NOTE:File Descriptors仅仅适用于Linux以及MacOs,在Windows平台上运行Elasticsearch可以忽略。在 Windows 上,JVM 使用仅受可用资源限制的 API

      Elasticsearch会使用很多file descriptors 或者 file handles。文件描述符用完可能是灾难性的,并且很可能会导致数据丢失。要确保将open files descriptors的数量提高到65,536或者更高用于Elasticsearch的运行。

      对于.zip.tar.gz的安装包,在Elasticsearch启动前使用root用户执行ulimit -n 65535,或者在/etc/security/limits.conf设置nofile的值为65535

      在MacOs平台上,你必须要使用JVM参数-XX:-MaxFDLimit让Elasticsearch使用更高的file descriptors限制。

      RPM和Debian已经默认将file descriptors的最大值设置为65535并且不需要进一步的配置。

      你可以使用Nodes stats API检查每一个节点上的max_file_descriptors

    Virtual memory

    (8.2)link

      Elasticsearch默认使用mmapfs存储索引文件。默认情况下操作系统会将mmap count限制的太低导致OOM的异常。

      在Linux下,你可以使用root通过下面的命令来提高上限:

      可以在/etc/sysctl.conf中更新vm.max_map_count来永久的设置该值。在重启后使用sysctl vm.max_map_count命名来验证刚才的变更。

      RPM跟Debian安装包会自动进行配置。不需要进行额外的配置。

    Number of threads

    (8.2)link

      Elasticsearch会使用线程池用于不同类型的操作。重要的是当有需要时就会创建新的线程。保证Elasticsearch能创建的线程数量至少可以有4096个。

      在启动Elasticsearch前切换到root设置ulimit -u 4096,或者在/etc/security/limits.conf中将nproc设置为4096。

      systemd下运行的service会自动的为Elasticsearch进程设置线程数量。不需要额外的配置。

    DNS cache settings

    link

    Ensure JNA temporary directory permits executables

    link

    TCP retransmission timeout

    link

    Bootstrap Checks

    link

    Development vs. production mode

    Discovery and cluster formation

    (8.2)link

      Discovery and cluster formation负责节点发现,选举master,形成集群,以及每一次发生变更时集群状态的发布。

      下面的processes和settings是discovery and cluster formation的 一部分:

    Discovery

    (8.2)link

      Discovery是cluster formation module发现其他节点并形成一个集群的过程。这个过程发生在当你启动一个Elasticsearch节点或者当一个节点认为master node发生故障并且等到发现master node或者选出新的master node后继续运行时。

      这个过程和上一次已知的集群中的master-eligible node的地址一起,开始于一个或者多个seed hosts providers中提供的seed address列表。这个过程有两个阶段:首先,通过连接每一个地址来尝试明确节点是否连接并且验证是否为master-eligible node。然后如果成功了,它会共享它已知的master-eligible node的remote node并且等待响应。然后该节点探测(prove)它刚刚发现的所有新节点,请求它们的对等节点(peer),等等。

      如果当前节点不是master-eligible node,那它会继续处理直到它发现了被选举为master的node。如果没有发现master node那么这个节点将在discovery.find_peers_interval后重试,默认值是1s

      如果当前节点是master-eligible node,那它会继续处理直到它要么发现了一个master node,要么已经发现了足够多masterless master-eligible node并完成master的选举。如果这两个都没有发生,则在discovery.find_peers_interval后重试,默认值是1s

      一旦一个master被选举出来,通常情况下它会一直是master node,直到它被故意(deliberate)停止。如果falult detection发现集群发生了故障,也有可能作为master并停止。如果一个节点不是master node,它则继续discovery的过程。

    Troubleshooting discovery

      大多数情况下,discovery和选举的过程会很快完成。并且master node在很长的一段时间内都是会master。

      如果你的集群没有一个稳定(stable)的master,许多的功能不能正确工作。那么Elasticsearch会报出错误给客户端并记录日志。你必须在解决其它问题前先处理master node的不稳定问题。master node选举出来之前或者master node稳定前将无法解决其他任何的问题。

      如果你有一个稳定的master node但是一些节点不能发现它或者加入,这些节点会报出错误给客户端并记录日志。在解决其它问题前你必须先解决这些节点无法加入到集群的障碍(obstacle)。节点不能加入集群前将无法解决其他任何问题。

      如果集群在超过好几秒后都没有选举出master,说明master不稳定或者其他节点无法发现或者加入join a stable master。那Elasticsearch会在日志中记录其原因。如果这个问题超过好几分钟还存在,Elasticsearch会在日志中记录额外的日志。若要正确的处理discovery和选举问题,可以收集并分析所有节点上最新的5分钟内的日志。

      下面的内容介绍了一些常见的discovery和选举问题。

    No master is elected

      当一个节点赢的选举,日志中会包含elected-as-master的信息并且所有的节点会记录一条包含master node changed的信息来标识最新赢的选举的master node。

      如果没有选出master node并且没有节点赢得选举,所有的节点会重复的在日志中记录问题:org.elasticsearch.cluster.coordination.ClusterFormationFailureHelper。默认情况下,每10秒发生一次。

      master的选举只会涉及master-eligible node,所以这种情况下集中查看master-eligible node的日志。这些节点的日志会说明master选举的要求,比如用于discovery的相关节点。

      如果日志显示Elasticsearch不能从quorum中发现足够多的节点。你必须解决阻止Elasticsearch发现缺失节点的原因。缺失的节点需要用于重新构造(reconstruct)cluster metadata。没有cluster metadata,你集群中的数据是没有意义的(meaningless)。cluster metadata存储在集群中master-eligible node的子集中。如果不能发现quorum ,那么缺失的节点是拥有cluster metadata的节点。

      保证有足够多的节点来形成quorum并且每个节点能相互通过网络联系到对方。如果选举问题持续了好几分钟,Elasticsearch会额外的报出网络连接的细节。如果你不能启动足够多的节点来形成quorum,那么启动一个新的集群并且从最新的snapshot中恢复数据。参考Quorum-based decision making 了解更多信息。

      如果日志显示Elasticsearch已经发现了 a possible quorum of nodes。那么集群不能选出master的原因通常是其中的节点不能发现quorum。检查其他master-eligible node上的日志并且保证它们已经发现了足够多的节点来形成一个quorum。

    Master is elected but unstable

      当一个节点赢得了选举,它的日志中会包含elected-as-master的信息。如果重复出现这个日志,说明选举出的节点不稳定。在这种情况下,集中在master-eligible node中的日志中查看为什么选举出的胜利者后来又停止成为master并且又触发另一个选举的原因。

    Node cannot discover or join stable master

      如果选举出的master node是一个稳定的节点,但是某个节点不能发现并加入到集群,它会在日志中使用ClusterFormationFailureHelper重复的报出日志。其他受到影响的节点和选举为master的节点上可能会有一些关于这个问题的额外的日志。

    Node joins cluster and leaves again

      如果某个节点加入到了集群但是Elasticsearch认为它出了故障并随后将再次从集群中移除。见Troubleshooting an unstable cluster了解更多信息。

    Seed hosts providers

      默认情况下,cluster formation module提供了两个seed hosts provider来配置seed node列表:settings-basedfile-based。可以扩展为支持云环境以及通过discovery plugins的其他形式的seed hosts provider。seed hosts provider使用discovery.seed_providers进行配置,这个是settings-base 这种provider的默认方式。这个设置接受一个不同的provider的列表,允许你能用多种方式来为你的集群找到seed hosts。

      每一个seed hosts provider提供(yield)seed node的IP地址或者hostname。如果返回的是hostname,那么需要使用DNS来查找对应的IP地址。如果一个hostname对应了对个IP地址,那么Elasticsearch会尝试找到所有的地址。如果hosts provider没有显示的(explicit)给出节点的TCP port,则会隐式的(implicit)使用port range中的第一个:transport.profiles.default.port或者transport.port(如果没有设置transport.profiles.default.port)。通过DSN查找IP地址的并发数量由discovery.seed_resolver.max_concurrent_resolvers控制,默认值是10。超时时间由discovery.seed_resolver.timeout控制,默认值是5s。注意的是DNS查找IP地址受限于JVM DNS caching

    Settings-based seed hosts provider

      Settings-based seed hosts provider使用了节点设置来配置一个静态的seed nodes的地址列表。这些地址可以是hostname或者是IP地址。使用hostname时会在每一次discovery时去查找对应的IP地址。

      下面使用了discovery.seed_hosts静态设置:

      第3行,将默认使用transport.profiles.default.port,如果没有配置transport.profiles.default.port则使用transport.port   第4行,如果这个hostname对应了多个IP地址,Elasticsearch会尝试连接每一个IP地址

    File-based seed hosts provider

      File-based seed hosts provider通过外部的文件来配置hosts列表。这个文件发生变更后,Elasticsearch就会重新加载,所以不需要重启节点就可以使用变更后的seed nodes的地址。例如运行在Docker容器中的Elasticsearch就可以很方便的在节点启动时,如果给定的IP地址无法连接时就可以动态的提供。

      若要开启file-based的discovery,那么在elasticsearch.yml中配置file即可:

      然后按照下面的格式在$ES_PATH_CONF/unicast_hosts.txt中创建一个文件。任何时刻在unicast_hosts.txt文件中发生的变更都会被Elasticsearch捕获并使用新的hosts列表。

      注意的是file-based discovery 插件增强了elasticsearch.yml中的unicast hosts list:如果在discovery.seed_hosts中有合法的seed address,那么Elasticsearch会使用这些地址并额外使用unicast_hosts.txt中的地址。

      unicast_hosts.txt文件中每一行是一个node entry。每一个node entry由host(hostname或者IP地址)和一个可选的transport port 组成。如果指定了port,必须是写在host后面并且用:分隔。如果没有指定port,默认使用transport.profiles.default.port,如果没有配置transport.profiles.default.port则使用transport.port

      例如,下面的unicast_hosts.txt 中有四个node参与discovery,其中一些使用了默认的端口号:

      可以使用hostname来代替IP地址,但是需要上文描述的DNS。IPv6的地址必须要给定端口号。

      你可以在文件中添加注释, 所有的注释必须以#开头

    EC2 hosts provider

      EC2 discovery plugin使用AWSAPI来 查找seed node。

    Azure Classic hosts provider

      Azure Classic discovery plugin使用Azure Classic API来查找seed node。

    Google Compute Engine hosts provider

      GCE discovery plugin 使用GCE API来查找seed node。

    Quorum-based decision making

    (8.2)link

      选举出master node和变更集群状态是两个基本的任务,需要所有的master-eligible node一起工作执行。重要的是即使一些节点发生了故障也要让这些工作具有鲁棒性。Elasticsearch中达到这个鲁棒性的方式是:考虑每一个从quorum中接受到成功的响应。quorum即集群中的master-eligible node集合。只需要一部分节点响应的好处在于在一些节点发生故障后也不会影响集群继续工作。quorum是经过谨慎选择的,这样集群中不会出现裂脑(split brain)的场景:集群被划分为两块,每一块会作出与另一块不一样的决策。

      Elasticsearch允许你向正在运行中的集群添加或者移除master-eligible node。在很多场景中只要按需简单的启动或者节点即可。见Adding and removing nodes

      通过更新集群中的voting configuration使得在添加/移除节点时,Elasticsearch能维护一个最佳的容错能力(Elasticsearch maintains an optimal level of fault tolerance)。voting configuration是master-eligible的集合,它们的响应会被计数用来对选举出新的master和提交(commit)新的集群状态做出决策。只有voting configuration中的超过半数才能做出决策。通常情况下,voting configuration跟当前集群中所有的master-eligible集合是相同的,然而在有些情况下会有不同。

      为了保证集群仍然可用(remain available),你必须不能在同一时间(at the same time)停止一半或者更多的voting configuration中的节点。只要超过一半的voting node是可用的,集群就能正常的工作。例如,如果有3个或者4个master-eligible node,集群可以容忍一个不可用的节点。如果2个或者更少的master-eligible node,它们必须都是可用的。

      一个节点加入/离开集群时,选举为master的节点必须发布(issue)集群状态的更新,调整(adjustment)voting configuration,这个过程可能会花费一点时间。在移除更多节点之前等待调整结束是非常重要的。

    Master elections

      Elasticsearch在启动阶段以及当master node发生故障时使用选举的处理方式来达成一致选出master node。任何的master-eligible都可以开始一个选举,通常来说第一次选举都会成功(normally the first election that takes place will succeed)。只有当两个节点碰巧同时开始选举时,选举才会失败,所以每个节点上的选举都是随机安排的,以降低这种情况发生的概率。节点会重试选举,直到选举出master node。backing off on failure,使得选举会最终的成功。The scheduling of master elections are controlled by the master election settings

    Cluster maintenance, rolling restarts and migrations

      许多的集群维护任务包括临时的关闭一个或者多个节点然后重新启动它们。默认情况下,如果其中一个master-eligible node下线了,Elasticsearch仍然可用。比如在rolling upgrade期间。如果多个节点停止并且再次启动,Elasticsearch会自动的进行恢复,例如在full cluster restart期间。上述说到的场景中,不需要使用APIs来做出额外的措施,because the set of master nodes is not changing permanently。

    Voting configurations

    (8.2)link

      每一个Elasticsearch集群中都有一个voting configuration,通过master-eligible nodes集合的投票计数来作出一些决策,例如选举出新的master或者提交一个新的集群状态。决策只有在voting configuration 中节点大多数都响应后(超过半数)可以通过。

      通常情况下voting configuration和当前集群中所有的master-eligible node集合相同。然而在某些情况下可能会不同。

    IMPORTANT:为了保证集群仍然可用(remain available),你必须不能在同一时间(at the same time)停止一半或者更多的voting configuration中的节点。只要超过一半的voting node是可用的,集群就能正常的工作。例如,如果有3个或者4个master-eligible node,集群可以容忍一个不可用的节点。如果2个或者更少的master-eligible node,它们必须都是可用的。

      在某个节点加入或者离开集群时,Elasticsearch会自动的对voting configuration作出对应的变更来保证集群尽可能的具有弹性(resilient)。非常重要的一点是:你从集群中移除更多节点之前,要等待调整(adjustment)完成,见Adding and removing nodes.

      当前的voting configuration存储在集群状态中,你可以按照以下的方式来查看当前的内容:

    NOTE:当前的voting configuration不需要跟集群中的所有的可用的master-eligible node集合相同。改变(alert)voting configuration会涉及进行投票,所以节点加入或者离开集群时会花一点时间来调整configuration。同样的,也会存在most resilient configuration包含不可用的节点或者不包含可用的节点。在这种情况下,voting configuration就会跟集群中的master-eligible node不相同。

      规模大(large)的voting configuration 通常更具有弹性。所以Elasticsearch更喜欢(prefer to)在master-eligible node加入到集群后把它们添加到voting configuration中。同样的,如果一个在voting configuration中的节点离开了集群并且集群中有另一个不在voting configuration中的master-eligible node,那么会去交换这两个节点。voting configuration的大小没有发生变化但是提高了弹性。

      节点离开集群后,从voting configuration中移除节点不是一件简单的事情。不同的策略有不同的好处跟缺点,所以正确的选择取决于集群如何被使用。你可以通过cluster.auto_shrink_voting_configuration setting来控制voting configuration是否要自动的收缩(shrink)。

    NOTE:如果cluster.auto_shrink_voting_configuration设置为true(默认值,推荐值)。那么集群中会至少有3个master-eligible node。Elasticsearch仍然可以处理集群状态的更新,只要除了其中一个maste-eligible node,其他的所有节点都是健康的。

      在某些情况下,Elasticsearch能够容忍多个节点的丢失, but this is not guaranteed under all sequences of failures。如果cluster.auto_shrink_voting_configuration设置为false。你必须手动的去voting configuration中移除离开集群的节点(departed node)。使用voting exclusions API 来达到想要的弹性等级。

      无论怎么配置,Elasticsearch都不会受到裂脑导致不一致的困扰。cluster.auto_shrink_voting_configuration这个设置只会只会影响在一些节点发生故障后的可用性问题,以及影响节点离开/加入集群时 administrative task的执行。

    Even numbers of master-eligible nodes

      正常来说集群中应该有奇数个master-eligible node。如果是偶数个,Elasticsearch会将其中一个排除在voting configuration以外来保证奇数个。这种omission不会降低集群的容错能力。事实上还有略微提升:如果集群受到网络分区的影响,将其划分为大小相等的两部分,那么其中一部分将包含大多数voting configuration,并能够继续运行。如果所有的master-eligible node的投票都进行了统计,那么任何一方都不会包含严格多数的节点,因此集群将无法做任何处理(make any progress)。

      例如,如果在集群中有4个master-eligible node并且voting configuration包含这四个节点。任何quorum-based的决策都要求至少三个投票。这意味着这个集群可以容忍单个master-eligible node的丢失。如果集群被两等分,没有一半可以获得三个master-eligible node,集群就不会做任何处理。如果voting configuration只有三个master-eligible node,集群仍然可以容忍丢失一个节点,但是quorum-based的决策要求3个投票节点中的2个。即使发生了分裂,其中一半会包含3个投票节点的2个节点,所以这一半仍然是可用的。

    Setting the initial voting configuration

      当一个全新的集群第一次启动,必须选出第一个master node。要完成这个选举,需要知道用于投票计数的master-eligible集合。这个初始化的voting configuration即bootstrap configuration并且在cluster bootstrapping process中设置。

      重要的一点是bootstrap configuration明确指定了在第一次选举中参与的节点。 It is not sufficient to configure each node with an expectation of how many nodes there should be in the cluster. It is also important to note that the bootstrap configuration must come from outside the cluster: there is no safe way for the cluster to determine the bootstrap configuration correctly on its own。

      如果boostrap configuration没有正确设置,当你启动一个全新的集群时,会有形成两个不同集群的风险。这种情况会导致数据丢失:很有可能在你注意到这个问题前已经启动了2个集群并且不可能在随后合并这两个集群。

    NOTE:To illustrate the problem with configuring each node to expect a certain cluster size,想象一下启动一个三个节点的集群,每一个节点知道自己将成为三个节点集群中的一员。三个节点的大多数是2,所以正常情况下前两个启动的节点能发现对方并且形成一个集群,并且第三个节点会在随后很短的时间内加入它们。然而想象下如果错误当启动了四个节点而不是三个。在这种情况下,就会有足够的节点来形成两个集群。当然,如果每一个节点是手动启动的,那不大可能启动太多的节点。如果使用了自动化编排(orchestrator),这当然有可能会发生这种情况。特别是编排器不具备弹性(resilient)而导致网络分区的错误。

      最初的quorum只有在整个集群最开始启动的时候需要。加入到一个已经建立好的集群的节点可以安全的从被选举为master节点上获取所有的信息。注意的是之前作为集群一部分的节点将在重新启动时会将所有需要的信息存储到磁盘中。

    Bootstrapping a cluster

    (8.2)link

      最开始启动Elasticsearch时要求一个集群中的一个或者多个初始化的master-eligible node集合,需要显示的定义,即cluster bootstrapping。仅要求在集群第一次启动时:已经加入到一个集群的节点会将信息存储在它们的数据目录中用于full cluster restart并且新加入到集群的节点会从集群中被选举master的节点上获取信息。

      最初的master-eligible node集合定义在cluster.initial_master_nodes setting中。配置中要包含每一个master-eligible node的下面其中一个条目:

      在你启动一个master-eligible node时,你可以通过命令行或者elasticsearch.yml的方式提供这个设置。集群形成之后,将这个设置从每一个节点中移除。不能对master-ineligible node,已经加入集群的master-eligible node以及重启一个或者多个节点配置这个设置。

      技术上来讲只在集群中的单个master-eligible node上设置cluster.initial_master_nodes就足够了并且只在设置中提及这个单个节点。但是会在集群完全形成前缺乏容错能力。因此最好使用三个master-eligible node进行引导,每一个节点中都配置了包含三个节点的cluster.initial_master_nodes

    WARNING:你必须在每一个节点上设置完全相同的cluster.initial_master_nodes,使得在引导期间只会形成一个集群,避免数据丢失的风险。

      对于拥有三个master-eligible node(node name是 master-a, master-b and master-c)的集群,配置如下:

      跟其他的节点设置一样,也可以通过命令行的方式指定the initial set of master nodes 来启动Elasticsearch:

    Node name formats must match

      cluster.initial_master_nodes列表中使用的node name必须和节点的属性node.name完全一样。默认情况下node name被设置为机器的hostname,这个值在你的系统配置中可能不是fully-qualified。如果每一个node name是fully-qualified domain name,例如master-a.example.com,那你在cluster.initial_master_nodes列表中也必须使用fully-qualified domain name。如果你的node name是bare hostname (without the .example.com suffix) ,那你在cluster.initial_master_nodes列表中也必须使用bare hostname。如果你同时使用了fully-qualified 和 bare hostnames,或者其他无法匹配node.name 和 cluster.initial_master_nodes的值,那集群无法成功形成并会看到下面的日志信息:

      这个消息显示了node name:master-a.example.commaster-b.example.com以及cluster.initial_master_nodes中的值:master-amaster-b。日志中明显的指出它们无法完全匹配。

    Choosing a cluster name

      cluster.name这个设置能让你创建多个彼此相互隔离的集群。节点之间在第一次相互连接时会验证集群名。Elasticsearch只会形成一个所有节点的集群名都相同的集群。默认值是elasticsearch,不过建议修改这个值来体现出集群的逻辑名称。

    Auto-bootstrapping in development mode

      默认情况下,每一个节点在第一次启动时会自动的引导(bootstrap)自己进入一个单节点的集群。如果配置了下面任意的一个设置,自动引导会被替代:

      若要添加一个节点到现有的一个集群中,那么配置discovery.seed_hosts或者其他相关的设置,这样新的节点就可以发现集群中现有的master-eligible节点。若要引导一个多节点的集群,配置上文中section on cluster bootstrapping描述的cluster.initial_master_nodes

    Forming a single cluster

      一旦Elasticsearch的节点加入到一个现有的集群,或者引导出一个集群后,他不会加入到其他的集群。Elasticsearch不会将两个不同的已经形成的集群进行合并,即使你随后尝试配置所有的节点到一个节点中。这是因为没法在不丢失数据的情况下合并不同的集群。你可以通过GET /在每一个节点上获取集群的UUID来检查形成的不同集群。

      如果你想要添加一个节点到现有的集群中而不是引导出不同的单节点集群,那你必须:

    1. 关闭节点

    2. 通过删除data folder的方式来完全擦除(wipe)节点

    3. 配置discovery.seed_hosts或者 discovery.seed_providers以及其他相关的discover 设置

    4. 重启节点并且验证下节点是否加入到集群而不是形成自己的单节点集群

      如果你是要形成一个新的多节点集群而不是引导出多个单节点集群,那你必须

    1. 关闭所有的节点

    2. 通过删除每一个节点的data folder的方式来完全擦除(wipe)所有的节点

    3. 按照上文描述的方式来配置cluster.initial_master_nodes

    4. 配置discovery.seed_hosts或者 discovery.seed_providers以及其他相关的discover 设置

    5. 重启所有的节点并验证它们形成了单个集群

    Publishing the cluster state

    (8.2)link

      master node是集群中唯一可以对集群状态(cluster states)做出变更的节点。master node一次处理一批集群状态的更新。计算变更请求并更新集群状态到集群中的所有节点。每一次的发布开始于master向集群中所有的节点广播更新后的集群状态。每一个节点都响应确认,但未应用最新接收的状态。一旦master收集到足够的来自master-eligible node的确认,这个新的集群状态被认为是提交(commit)了,然后master node广播另一个消息让节点应用提交的集群状态。每一个节点收到这条消息后,应用更新后的状态,然后发送一个确认给master。

      master允许在有限的时间内完成集群状态更改到发布给所有的节点。定义在cluster.publish.timeout设置中,默认值30s。从publication开始算时间。如果在新的集群状态提交前达到了这个时间,集群状态的变更会被reject然后master会认为自己出现了故障。然后开始新的选举。

      如果在达到cluster.publish.timeout之前新的集群状态提交了,master会认为这次变更成功了。master会等待所有节点应用更新状态后的确认或者等待超时,然后开始处理并发布下一次的集群状态更新。如果master没有收到一些确认(比如一些节点还没有确认它们已经应用了当前的更新)这些节点被认为是它们的集群状态落后于master最新的状态。默认值是90s。如果仍然没有成功的应用集群状态更新,那么它会被认为发生了故障并且从集群中移除。

      发布的集群状态的更新内容通常是跟上一次状态的差异,这样能减低时间以及网络带宽。例如为集群状态中部分索引的更新mappings时,只要节点上有上一次的集群状态,那么就可以只发布这些索引更新对应的差异到集群中的节点上。如果一个节点缺失了上一个集群状态,比如说重新加入到了集群,master会发送完整的集群状态到这个节点,使得这个节点后续能接收差异更新。

    NOTE:Elasticsearch是基于点对点的系统,节点之间相互直连。high-throughput的APIs(index,delete,Search)通常不会跟master node交互。master node负责全局的集群状态并且当节点加入或者离开时重新分配分片。每次集群状态发生变化后,最新的状态会被发布到集群中的节点上

    Cluster fault detection

    (8.2)link

      被选举为master的节点会周期性的检查集群中的每个节点来保证它们仍是连接的并且健康的。每一个节点同样周期性的检查master node的健康。这些检查分别被称为follower checksleader checks

      Elasticsearch允许这些检查偶尔的出现失败或者超时的问题并且不采取任何行动。只有在连续多次检查(consecutive check)失败后才会认为这个节点发生了故障。你可以通过cluster.fault_detection.* settings来控制故障检测的行为。

      如果master node检测到某个节点失去了连接,这种情况会被视为立即失败(immediate failure)。master会绕过(bypass)超时和重试这些设置,并将这个节点从集群中移除。同样的,如果某个节点检测到master node失去了连接,这种情况也会被视为立即失败。这个节点会绕过(bypass)超时和重试这些设置,尝试discovery阶段来尝试找到/选举一个新的master。

      另外,每一个节点会周期性的往data path中写入一个小文件然后删除它来验证data path是否健康。如果节点发现它的data path不健康,随后会从集群中移除直到data path恢复。你可以通过monitor.fs.health settings来控制这个行为。

      如果某个节点在一个合理的时间内无法应用更新后的集群状态,master node也会将其从集群中移除。超时时间默认是2分钟,这个时间从更新集群状态开始。参考Publishing the cluster state了解更多信息。

    Troubleshooting an unstable cluster

      一般情况下,节点只有在故意关闭(deliberately shutdown)时才离开集群。如果某个节点意外的(unexpectedly)离开集群,解决这个问题是非常重要的。集群中的节点意外的离开集群会造成集群不稳定并且会产生一些问题。比如说:

      若要解决集群中的问题,首先要保证集群中有一个stable master,优先于其他的问题,集中精力关注意外退出的节点。直到集群中有一个稳定的master node以及稳定的节点成员才有可能解决其他的问题。

      诊断数据(Diagnostics)和统计数据在一个不稳定的集群中通常是没有参考价值的。这些工具只是实时的在某个时间给出集群状态的视图。应该查看一段时间内集群的行为模式(pattern of behavior)。特别要关注master node上的日志,当某个节点离开集群时,master node的日志中会有以下类似的信息(为了可读性添加了换行符)

      这个消息说的是master node(instance-0000000000)上的MasterService正在处理一个node-left的任务。并列出了被移除的节点以及移除的原因。其他的节点可能有类似的日志,但是细节较少:

      集中关注master node上MasterService中抛出的日志,它包含更多的细节。如果你无法查看到来自MasterService的日志,检测下面的内容:

      节点在开始/结束 follow一个master node时会记录包含master node changed的日志,你可以使用这些信息来观察一段时间内的view of the state of the master 。

      节点重启的会先离开集群然后再次加入到集群中。重新加入后,MasterService会记录它正在处理node-join的任务。你可以从master的日志中得知节点重启的信息,因为node-join相关日志描述的是节点的joining after restart。在较老的Elasticsearch版本中,你可以通过查看node-leftnode-join中的"ephemeral" ID来判断节点的重启。每次节点的启动,这个 ephemeral ID各不相同。如果某个节点意外的重启,你需要查看这个节点的日志了解它为什么关闭了。

      如果节点没有重启,你应该在node-left日志中查看节点离开集群(departure)的原因。有下面三个可能的原因:

    Diagnosing disconnected nodes

      Elasticsearch被设计为运行在一个相对可靠的网络上。它在节点间打开一定数量的TCP端口并且期望这些连接一直保持打开。如果连接关闭,Elasticsearch会尝试重新连接。因此要限制偶尔的小故障(occasional blip)对集群的影响,即使是受到影响的节点暂时离开了集群。相反,重复丢失连接会严重影响运行。

      集群中master node和其他节点之间的连接是特别重要的。被选举为master的节点从来不会自发地(spontaneous)关闭跟其他节点的outbound连接。同样的,一旦建立了连接,节点也不会自发地关闭outbound连接,除非节点关闭。

      如果你看到因为disconnected的原因意外的(unexpected)关闭了。可能是Elasticsearch以外的原因导致了连接关闭。一个常见的问题是防火墙配置错误:错误的超时时间(improper timeout),或者策略跟Elasticsearch不兼容。也有可能是由于其他的连接问题,比如由于硬件故障网络阻塞(network congestion)导致包的丢失。如果你是高级用户(advanced user),你可以配置下面的内容来获取更多关于网络异常的信息:

      极端的情况下,你可能需要进行抓包并使用tcpdump对其进行分析,查看节点之间的是否出现丢包或者被网络上的其他设备reject。

    Diagnosing lagging nodes

      Elasticsearch需要每一个节点能合理的快速处理集群状态的更新。节点花费太长的时间来处理集群状态的更新对集群是不利的。master会以lagging的原因将节点移除。参考Discovery and cluster formation settings了解更多的信息。

      通常导致lagging的原因是节点的性能问题。然而也有可能因为严重的网络延迟。若要排除(rule out)网络延迟,确保合理配置了net.ipv4.tcp_retries2。包含warn threshold的日志信息可能会提供更多的根因。

      如果你是高级用户(advance user),你可以通过配置下面的内容获取更多节点被移除时的正在处理的信息:

      当开启这个日志后,Elasticsearch会尝试在发生故障的节点上运行Nodes hot threads 并在master节点的日志里面记录运行结果。

    Diagnosing follower check retry count exceeded nodes

      Elasticsearch需要每一个节点要成功响应网络消息(network message)并且合理的快速响应。如果某个节点reject请求或者完全不响应请求,可能会对集群造成损坏。如果多个连续的检查都失败了,那么Elasticsearch会以follower check retry count exceeded的原因将节点移除。并且在node-left消息中指出多少个连续的不成功的检查以及有多少个请求超时了。参考Discovery and cluster formation settings了解更多的信息。

      超时和失败(timeout and failure)可能是因为网络延迟或者节点的性能问题。确保合理的配置net.ipv4.tcp_retries2来消除可能导致这种不稳定的网络延迟。日志消息中包含warn threshold的日志可能会有导致这种不稳定的原因。

      如果上一次检查失败并抛出了异常,那这个异常会被报出,通常会报出需要解决的问题。如果发生了超时,也许需要理解下成功的检查中涉及到的步骤顺序:

    1. master上运行在线程elasticsearch[master][scheduler][T#1]FollowerChecker告知TransportService往follower节点发送检查请求的消息。

    2. master上运行在线程elasticsearch[master][transport_worker][T#2]TransportService将检查请求消息传给操作系统。

    3. master上的操作系统将消息转化成一个或者多个包通过网络发送出去。

    4. 在master与follower之间的各种的路由,防火墙和设备转发这些包,这个过程中可能有fragmenting或者defragmenting

    5. 在follower节点上的操作系统接收到包并通知Elasticsearch

    6. follower上运行在线程elasticsearch[follower][transport_worker][T#3]TransportService读取了包,然后重新构造并处理了检查请求。通常来说,检查很快就成功。如果是这样,线程马上构造一个响应并传递给操作系统

    7. 如果检查没有马上成功(例如,最近一次选举开始了) a. follower上运行在线程elasticsearch[follower][cluster_coordination][T#4]FollowerChecker处理这次请求。它开始构造响应并告诉TransportService向master发送响应。 b. follower上运行在线程elasticsearch[follower][transport_worker][T#3]TransportService将响应传给操作系统。

    8. follower上的操作系统将响应转化成一个或者多个包通过网络发送出去。

    9. 在master与follower之间的各种的路由,防火墙和设备转发这些包,这个过程中可能有fragmenting或者defragmenting

    10. 在master节点上的操作系统接受到包并通知Elasticsearch

    11. master上运行在线程elasticsearch[master][transport_worker][T#2]TransportService读取了包,重新构造了检查响应,然后进行处理,只要这次检查没有超时。

      存在很多的事情会延缓检查的完成并且导致它超时:

    1. 将检查请求传递给TransportService后可能有long GC或者virtual machine pause。

    2. 可能会长时间的等待transport_worker线程变成可用,或者在将检查请求传递给操作系统前可能有long GC或者virtual machine pause。

    3. master上的系统错误(例如,a broken network card)可能会延缓通过网络发送消息,possibly indefinitely。

    4. 一路上交互的设备可能会延缓,丢弃,或者破坏包。master上的操作系统会等待并根据net.ipv4.tcp_retries2重新发送(retransmit)没有确认的或者被破坏的包。我们建议reducing this value,因为默认值会导致很长的延迟。

    5. follower上的系统错误(例如,a broken network card)可能会延缓通过网络发送的消息,possibly indefinitely。

    6. 可能会长时间的等待transport_worker变成可用,或者在follower上处理请求的过程中可能有long GC或者virtual machine pause。

    7. 可能会长时间的等待cluster_coordination变成可用,可能又要等待transport_worker变成可用。处理请求的过程中可能有long GC或者virtual machine pause。

    8. follower上的系统错误(例如,a broken network card)可能会延缓通过网络发送的响应

    9. 一路上交互的设备可能会延缓,丢弃,或者破坏包导致重发(retransmissions)、

    10. master上的系统错误(例如,a broken network card)可能会延缓通过网络接收响应

    11. 可能会长时间的等待transport_worker变成可用来处理响应,可能有long GC或者virtual machine pause。

      若要确定follower check超时的原因。我们可以根据下面的内容来缩小下(narrow down)原因:

    Add and remove nodes in your cluster

    (8.2)link

      当你启动了一个Elasticsearch的实例就是启动了一个节点。Elasticsearch集群就是一组节点的集合,这些节点有相同的cluster.name的属性。节点加入或者离开节点,集群都会自动的识别并且最终将数据分布到可用的节点上。

      如果你正在运行单个实例的Elasticsearch,你的集群中只有一个节点。所有的主分片在单个节点上。副本分片无法被分配,因此你的集群颜色是黄色的。集群有完整的功能但是在出现故障时有丢失数据的风险。

      向集群中添加节点能提高承载力和可靠性(capacity and reliability)。默认情况下,一个节点既是data node并且又是一个有资格成为master的节点来控制集群。你也可以配置一个新的节点用于特定的目的,例如处理ingest request,见Nodes了解更多信息。

      向集群中添加更多节点后,它会自动的分配副本分片。当所有的主分片和副本分片都可用后(active),集群状态会变更为绿色。

      你可以在你的本地机器上运行多个节点来体验多个节点的集群的行为。若要添加一个节点到一个运行在你本地机器上的集群,你需要:

    1. 启动一个新的Elasticsearch实例

    2. elasticsearch.yml文件中的cluster.name配置中指定集群名称。例如若要将一个节点添加到名为logging-prod的集群中,那么在elasticsearch.yml中添加一行: cluster.name: "logging-prod"

      若要添加一个节点到运行在多个机器上的集群,你必须要set discovery.seed_hosts,使得新的节点可以发现集群中的其他节点。

      更多discover和shard allocation的信息见Discovery and cluster formationCluster-level shard allocation and routing settings

    Master-eligible nodes

      随着节点的添加和移除,Elasticsearch通过自动的更新集群的投票配置(cluster's voting configuration)来保持最佳的容错水平。通过master-eligible nodes的投票计数来作出一些决策,例如选举出新的master或者提交一个新的集群状态。

       建议在集群中设置一个小规模的并且固定数量的master-eligible node,只通过添加或者移除master-ineligible node来扩大或者缩小集群。然而也有一些情况需要将一些master-eligible node 添加到集群,或者从集群中移除。

    Adding master-eligible nodes

      如果你想要在你的集群中添加一些节点,对新节点进行简单配置来找到现有的集群然后启动它们。如果这样做是合适的话( if it is appropriate to do so),Elasticsearch会将新的节点添加到voting configuration中。

      在master选举或者加入到一个现有的已经形成的集群中时,节点会发送一个join request到master,使得正式的添加到集群中。

    Removing master-eligible nodes

      在移除master-eligible node时,非常重要的一点是不要在同一时间移除太多的节点。例如如果当前有七个master-eligiable node,然后你想要降到三个。不是简单的马上将其中四个节点停止就行:这么做将只剩下三个节点,少于voting configuration中的一半,意味着集群不能再执行任何的动作。

      更准确的说,如果在同一时间关闭一半或者更多的master-eligible node,集群通常会变成不可用。可以通过再次启动被移除的节点就可以让集群重新上线(back online)。

      只要集群中至少有3个master-eligible node,作为一般的规则要一个接着一个的去移除节点,给于集群足够的时间自动的调整(adjust)voting configuration,适应新的节点集合对应的容错级别。

      如果只剩下两个master-eligible node,它们都不能被安全的移除因为它们都依靠对方才能进行可靠的运行。若要移除这些节点中的一员,需要通知Elasticsearch让这个节点不再是voting configuration中的一部分。投票权利应该给于其他的节点。这样你就可以让这个节点下线并且不会阻止其他节点的正常运行。排除在voting configuration之外的节点仍然可以正常工作,但是Elasticsearch会尝试将这个节点从voting configuration中移除并不再需要它的投票。重要的是,Elasticsearch不会自动的将排除在voting configuration之外的节点重新回到voting configuration中。一旦节点成功的自动配置为voting configuration之外的节点,它就可以安全的关闭并且不会影响集群master-level的可用性。可以通过Voting configuration exclusions 将节点排除在voting configuration之外:

    Full-cluster restart and rolling restart

    (8.2)link

      可能会存在一些情况where you want to perform a full-cluster restart 或者rolling restart。对于full-cluster restart,需要关闭并重启集群中所有的节点,而对于rolling restart,则是需要在某一时间只关闭一个节点,这样提供的服务就不会停止。

    Full-cluster restart

    1. Disable shard allocation

      当你关闭了一个data node,allocation process将位于该节点上的主分片复制到其他节点前会等待index.unassigned.node_left.delayed_timeout(默认一分钟),因为这会占用很多I/O。由于节点很快就要重启,那这个I/O是没有必要的。你可以在关闭data nodedisabling allocation of replica,免得在超时前没有重启好节点。

    1. Stop indexing and perform a flush

      执行flush加快分片恢复。

      2.1 Temporarily stop the tasks associated with active machine learning jobs and datafeeds(Optional)

      Machine leanring功能需要subscription

      当你关闭一个集群时,你有两个选项来处理machine learning jobs和datafeeds。

      2.2 Shut down all nodes

    1. Perform any needed changes

    2. Restart nodes

      如果你有专用的master node,那可以在处理你的data node前,先启动它们,然后等待它们形成一个集群并选举出一个master。你可以通过日志查看处理进程。

      一旦有足够的master-eligible node相互的发现了对方,它们就会形成一个集群并且选举出master。在这个时候,你可以使用cat healthcat nodes来监控加入到集群的节点。

      _cat/health返回的status列显示了集群中每一个节点的状态: redyellow或者green

    1. Wait for all nodes to join the cluster and report a status of yellow

      当一个节点加入到集群,它开始恢复存储在本地的所有的主分片。_cat/health API最开始会报出值为redstatus,意思是还有主分片没有被分配。

      某个节点一旦恢复了本地的分片,status会切换到yellow,意思是所有的主分片已经恢复,但不意味着所有的副本分片已经分配好。这是意料之中的事,因为你还没有重新开启副本分片的分配。延迟副本分片的分片直到所有的节点的statusyellow,使得master能将副本分片分配到那些已经有本地分片拷贝的节点上。

    1. Re-enable allocation

      当所有的节点加入到集群后,并且恢复好了它们的主分片后,将cluster.routing.allocation.enable恢复到它的默认值来重新开启分配:

      一旦重新开启了分配,集群开始将副本分片分配到data node。在这个时间点恢复索引和查询是安全的,但如果你能等待所有的分片和副本分片成功的分配结束并且所有节点的状态都是green,那你的集群能更快的恢复。

      你可以使用_cat/health _cat/recovery APIs来监控处理进程:

    1. Restart machine learning jobs(Optional)

      如果你临时暂停了machine learning jobs相关的任务,使用set upgrade mode API将它们返回到活跃状态:

      如果你在停止节点前关闭了所有的machine learning jobs,可以在Kibana中打开jobs并开始datafeed或者使用open jobsstart datafeed APIs。

    Rolling restart

    1. Disable shard allocation

      当你关闭了一个data node,allocation process将该节点上的主分片复制到其他节点前会等待index.unassigned.node_left.delayed_timeout(默认一分钟),因为这会占用很多I/O。由于节点很快就要重启,那这个I/O是没有必要的。你可以在关闭data nodedisabling allocation of replica,免得在超时前没有重启好节点。

    1. Stop non-essential indexing and perform a flush(Optional)

      尽管你可以在rolling restart期间继续执行索引操作,但如果你临时的停止没有必要的索引操作并执行flush可以让分片恢复的更快

    1. Temporarily stop the tasks associated with active machine learning jobs and datafeeds (Optional)

      Machine leanring功能需要subscription

      当你关闭一个集群时,你有两个选项来处理machine learning jobs和datafeeds。

    1. Shut down a single node in case of rolling restart

    1. Perform any needed changes

    2. Restart the node you changed

      启动节点后并通过查看日志文件或者提交一个_cat/nodes请求来确认该节点加入到了集群:

    1. Reenable shard allocation

      对于data node,一旦它加入到集群后,就可以移除cluster.routing.allocation.enable这个设置来开启分片分配并开始使用这个节点:

    1. Repeat in case of rolling restart

      当节点恢复后并且集群已经稳定,对每一个需要变更的节点重复这些步骤。

    1. Restart machine learning jobs(Optional)

      如果你临时暂停了machine learning jobs相关的任务,使用set upgrade mode API将它们返回到活跃状态:

      如果你在停止节点前关闭了所有的machine learning jobs,可以在Kibana中打开jobs并开始datafeed或者使用open jobsstart datafeed APIs。

    Remote clusters

    (8.2)link

      你可以将本地集群(local cluster)与其他Elasticsearch集群进行连接,即remote cluster。remote cluster可以位于不同的数据中心或者地理区域,其包含的index和data stream可以被CCR(cross-cluster replication)用于复制或者在一个本地集群使用CCS(cross-cluster search)。

      CCR中,提取(ingest)的是remote cluster上的索引数据。leader index可以被复制(replicate)到你本地集群的一个或者多个只读的follower index上。使用CCR创建一个多集群可以提供灾备(discovery recovery),让数据的地理位置靠近你的用户,或者建立一个中心化的集群用于出报表。

      Cross-cluster search能让你对一个或者多个remote cluster运行一个查询请求。这个能力可以让每一个区域都有一个全局视图的集群。允许你从本地集群执行单个查询请求,并从所有连接的remote cluster中返回数据。

      开启并配置security对本地集群和remote cluster都是很重要的。当本地集群连接到一个remote cluster,本地集群上Elasticsearch的superuser能获取remote cluster上完整的读取权限。为了能安全的使用CCR和CCS,在所有连接的节点上开启enable security并且至少在每一个节点的transport level配置 Transport Layer Security (TLS) 。

      此外,操作系统级别的本地管理员如果能够充分访问Elasticsearch配置文件和私钥,就有可能接管remote cluster。确保你的安全策略中包括在操作系统级别保护本地和remote cluster。

      若要注册一个remote cluster,使用sniff modeproxy mode connect the local cluster和remote cluster中的节点。注册完remote cluster后,为CCR和CCS configure privileges

    Sniff mode

      在sniff mode中,使用名称和seed node list来创建集群。当注册了一个remote cluster后,它的cluster state从seed node中获取并且最多三个gateway nodes作为remote cluster requests的一部分。这个模式要求gateway node 的publish address能被本地集群访问到。

      Sniff模式是默认的连接模式。

      gateway node的选择取决于下面的标准:

    Remote cluster5.0–5.55.66.0–6.66.76.87.07.1–7.167.178.0–8.2
    5.0–5.5×××××××
    5.6××××
    6.0–6.6×××××
    6.7××××
    6.8××
    7.0××××
    7.1–7.16×××××
    7.17××××
    8.0–8.2×××××××

    IMPORTANT:Elastic仅支持在这些配置的一个子集上进行跨集群搜索,见Supported cross-cluster search configurations

    Proxy mode

      在proxy模式中,使用一个名称和单个代理地址来创建一个集群。当你注册了一个remote cluster,数量可配置的socket 连接对代理地址开放。这个proxy要求将这些连接路由到remote cluster。Proxy mode不要求remote cluster node‘有用于访问的publish address。

      proxy模式不是默认的连接模式并且必须要配置。Proxy mode跟sniff mode有相同的版本兼容要求。

    IMPORTANT:Elastic仅支持在这些配置的一个子集上进行跨集群搜索,见Supported cross-cluster search configurations

    Configure remote clusters with security

    link

    Connect to remote clusters

    (8.2)link

      本地集群使用 transport interface建立于remote cluster的连接。本地集群中的coordinating node会跟remote cluster中指定的节点建立long-lived TCP连接。Elasticsearch要求这些连接保持打开,即使连接空闲(idle)了很长一段时间。

    NOTE:你必须要有manage cluster privilege用于跟remote cluster进行连接

      若要在Kibana的Stack Management 中添加一个remote cluster:

    1. 从侧边导航栏选择Remote Clusters

    2. 指定remote cluster(Cluster A)的Elasticsearch endpoint URL,或者IP地址,hostname以及transport端口(默认值9300)。例如cluster.es.eastus2.staging.azure.foundit.no:9400或者192.168.1.1:9300

      或者使用cluster update settings API 添加一个remote cluster。你也可以为本地集群中的每一个node dynamically configure remote cluster。若要对本地集群中不同的节点配置remote cluster,那么在每一个节点的elasticsearch.yml中定义static settings

      连接remote cluster之后,configure roles and users for remote clusters

      下面的请求添加了一个名为cluster_one的remote cluster,cluster alias是一个唯一标识符代表连接的remote cluster用于区分本地和远程的索引。

      第6行,这个remote cluster的cluster aliascluster_one·   第8行,指定remote cluster中seed node 的hostname跟transport port

      你可以使用remote cluster info API 来验证本地集群是否于remote cluster连接成功。

      API的响应指出本地集群跟cluster aliascluster_one的集群连接成功:

      第7行,在remote cluster中,跟本地集群连接的节点数量   第10行,如果通过CCS进行查询时节点不可用,是否要跳过这个集群

    Dynamically configure remote clusters

      使用cluster update settings API动态的配置集群中每一个节点上的remote 设置。下面的请求增加了三个remote cluster:cluster_onecluster_twocluster_three

      参数seed指定了remote cluster中seed node的hostname和transport port(默认值9300

      参数mode决定了连接模式,默认值是sniff。因为cluster_one没有指定mode,所以使用默认值。cluster_twocluster_three都显示的使用了不同的模式:

      你可以在初始化配置后动态的为一个remote cluster更新。下面的请求为cluster_two更新了compress settings,为cluster_three更新 了compress settings 以及ping schedule settings

    NOTE:当compression和ping schedule settings更改后,所有现有的节点连接必须关闭并重新打开,可能会导致正在运行的请求失败。

      你可以通过将每一个remote cluster settings的值赋值为null的方式将一个remote cluster从一个cluster settings中删除。下面的请求将cluster_two从cluster settings中移除,留下了cluster_onecluster_three

    Statically configure remote clusters

      如果你在elasticsearch.yml中指定了设置,带有这些设置的节点才能连接remote cluster并且服务remote cluster的请求。

    NOTE:对于每一个节点,使用cluster update settings API指定的cluster settings优先在elasticsearch.yml中的设置

      在下面的例子中,cluster_one, cluster_two, 和cluster_three是随意的(arbitrary)取的名称(aliases)用来代表连接的集群。这些名称随后用于区分本地和远程的索引。

      第8行,cluster_two中显示的开启了Compression   第9行,cluster_two中失去连接的remote cluster是可选的   第12行,cluster_three中用于连接的代理地址

    Configure roles and users for remote clusters

    (8.2)link

      connecting remote clusters之后,你需要同时在本地和远程集群中创建一个用户角色(user role)并且赋予必要的privilege。这些角色要求可以使用CCR(cross-cluster replication)和CCS(cross-cluster search)。

    IMPORTANT:你必须在本地和远程集群使用相同的角色。例如,下面用于CCR的配置在本地和远程集群上使用了remote-replication角色名。然而,你可以在每一个集群上指定不同的角色定义。

      你可以用Kibana的Stack Management,从侧边导航栏中选择Security > Roles来管理用户和角色。你也可以使用role management APIs动态的添加,更新,移除并且检索角色。当你使用APIs在native realm中管理角色时,角色存储在内部的Elasticsearch index中。

      下面的请求使用了create or update roles API。你必须至少有manage_security 的cluster privilege来使用这个API。

    Configure privileges for cross-cluster replication

      CCR用户在本地集群和remote cluster上要求有不同的 index和cluster privilege。使用下面的请求分别在本地集群和remote cluster上创建不同的角色,然后创建一个用户拥有这些角色。

    Remote cluster

      在包含leader index的remote cluster上,CCR角色需要read_ccr的cluster privilege,以及在leader index上的monitorread privilege

    NOTE:如果请求导致了on behalf of other users,那么用户在remote cluster上必须要有run_as的privilege。

      下面的请求在remote cluster上创建了一个remote-replication的角色:

    Local cluster

      在包含follower index的本地集群上,remote-replication 角色需要manage_ccr的cluster privilege,follower index的monitorreadwrite,和manage_follow_index privilege。

      下面的请求在本地集群上创建了一个remote-replication的角色:

      在每一个集群上创建完remote-replication的角色后,使用create or update users API在本地集群上创建一个用户,并赋予remote-replication的角色。例如,下面的请求赋予一个名为cross-cluster-user的用户remote-replication的角色:

    NOTE:在本地集群上你只需要创建这个用户。

      你可以随后configure cross-cluster replication来跨中心复制你的数据。

      CCS用户在本地集群和remote cluster上要求有不同的 index和cluster privilege。使用下面的请求分别在本地集群和remote cluster上创建不同的角色,然后创建一个用户拥有这些角色。

    Remote cluster

      在remote cluster上,CCS角色要求为目标索引有readread_cross_cluster privilege。

    NOTE:如果请求导致了on behalf of other users,那么用户在remote cluster上必须要有run_as的privilege。

      下面的请求在remote cluster上创建了一个remote-search的角色:

    Local cluster

      在本地集群上,集群用于初始化CCS,用户只需要remote-search角色。role privilege可以是空。

      下面的请求在本地集群上创建了一个remote-search角色:

    NOTE:在本地集群上你只需要创建这个用户。

      remote-search角色的用户随后可以search across clusters

    Configure privileges for cross-cluster search and Kibana

      当使用Kibana跨多个集群搜索时,一个两步骤的赋权过程决定了用户是否可以访问remote cluster上的data streams和index:

      为了保证Kibana用户能访问remote cluster,赋予它们一个在remote cluster上指定索引的 read privilege。你可以在remote cluster中指定data streams和index:<remote_cluster_name>:<target>

      例如,你可能将Logstash data索引到本地集群并且周期性的将older time-based的索引归档到你的remote cluster上。你想要在这两个集群上进行搜索,那你必须在两个集群上同时enable Kibana users。

    Local cluster

      在本地集群上,创建一个logstash-reader的角色,然后在logstash-*上授予(grant)readview_index_metadata的privilege。

    NOTE:如果你将本地集群配置为其他集群的remote cluster,你本地集群上的logstash-reader角色同样需要赋予read_cross_cluster privilege。

      给你的Kibana用户赋予一个角色能access to Kibana以及logstash_reader角色。例如,下面的请求创建了cross-cluster-kibana用户并赋予kibana-accesslogstash-reader的角色。

    Remote cluster

      在remote cluster上,创建一个logstash-reader并赋予read_cross_cluster的privilege以及logstash-*索引的readview_index_metadata的privilege。

    Remote cluster settings

    Sniff mode remote cluster settings

    Index Modules

    (8.2)link

      Index Modules是用于索引创建的模块,控制与索引相关的所有方面。

    Index Settings

      索引层的设置(index level settings)可以根据每一个索引进行配置,索引配置可以划分为:

    static

      只能在索引创建期间或者对一个closed index进行设置。

    dynamic(index modules)

      使用update-index-settings对live index的索引配置进行变更。

    Static index settings

      下面是所有的静态索引设置,这些设置跟任何特定的索引模块都没有关联(associate):

    index.number_of_shards

      一个索引应该拥有的主分片数量。默认值是1。这个设置只能在索引创建期间设置。不能对关闭的索引进行设置。

    index.number_of_routing_shards

      整数值,跟index.number_of_shards一起用来将文档路由到主分片中,见_routing field

      Elasticsearch在对索引进行split时会使用这个值。例如,一个拥有5个分片,并且index.number_of_routing_shards的值设置为30时,那么每个分片可以按照因子2或者3进行划分,换句话说,可以按照下面的方式进行划分:

      默认值取决于索引的主分片数量,默认情况下根据切分因子2进行切分,并且最多切分出1024个分片。

    index.codec

      默认使用LZ4对store data进行压缩,但是可以设置为best_compression,其使用DEFLATE有更高压缩率,代价是降低了存储字段stored filed的性能。如果你更新了压缩类型compression type,新的数据在段合并后会被应用(apply)。可以使用force merge对段进行强制合并。

    index.routing_partition_size

      使用自定义的路由值,路由到一定数量的分片中(区别于路由到某一个分片,这里指的是可以被路由到某个分片集合中,集合的大小即index.routing_partition_size)。默认值是1并且只能在创建索引时设置,该值必须比index.number_of_shards小,除非index.number_of_shards的值就是1。见Routing to an index partition查看如何使用该值。

    index.soft_deletes.enabled

      该值描述了当前索引是否开启soft deletes。Soft deletes只能在创建索引时配置并且只能在Elasticsearch6.5及以后的版本的索引上配置。默认值为true。

    index.soft_deletes.retention_lease.period

      在分片的history retention lease过期之前,保留的最长时间。Shard history retention leases能保证在Lucene层的段合并后soft deletes仍然能被保留(retain)。如果soft deletes在follower节点上生成副本期间被合并了merge away,那么在随后的处理中会因为在leader节点上不完整的history而导致失败。默认值为12h。

    index.load_fixed_bitset_filters_eagerly

      该值描述了cached filters是否为nested queries提前载入了pre-loaded。可选值是true(默认值)和false。

    index.shard.check_on_startup

      Elasticsearch在分片生命周期的不同时刻自动对其内容执行完整性检查。比如当恢复一个副本replica时,会对传输的每一个文件进行校验和的验证或者拍摄快照时(take a snapshot)。当启动一个节点或者完成一个分片的恢复跟重分配时,同样的会在打开一个分片时对重要的文件进行完整性的验证。你可以在对其进行拍摄快照并放到新的仓库中(fresh repository)或者恢复到一个新的节点后,手动的对整个分片进行完整性的校验。

      当前配置用来描述Elasticsearch在打开一个分片时是否要对其进行额外的完整性检查。如果检查出corruption,那么阻止这个分片被打开,该配置接受下面的值:

    Dynamic index settings

      下面列出的是所有的动态索引设置,这些设置与任何特定的index module没有关联。

    index.number_of_replicas

      每个主分片的副本分片(replica)的数量,默认值是1。

    index.auto_expand_replicas

      基于集群中节点的数量自动增加(auto-expand)副本分片的数量。该值可以设置为一个用破折号来区分上下界的值(例如: 0-5),或者使用all作为上界(例如:0-all)。默认值是false。注意的是这种自动增加副本分片数量只会考虑allocation filtering规则,会忽视其他的分配规则例如total shards per node,如果适用的规则(applicable rules)阻止分配所有的副本分片,会导致集群变成yellow

      如果上界是all,那么shard allocation awarenesscluster.routing.allocation.same_shard.host这两个配置在这个索引上会被忽略。

    index.search.idle.after

      某个分片在多久未收到搜索或者请求后被认定为空闲的,默认值是30秒。

    index.refresh_interval

      多久执行一次refresh操作。该操作使得最近的修改能够被搜索到。默认值是1秒。可以被设置为-1来关闭refresh。如果没有显示的(explicit)设置这个值,那么分片在至少index.search.idle.after时间内没有收到搜索请求则不会收到后台刷新,直到分片收到查询请求。搜索时如果遇到某个分片正在进行refresh,那么会等待下一次后台refresh,这种行为的目的是在没有搜索请求时能优化bulk Indexing。为了避免这种行为,应该显式设置1s的值作为刷新间隔。

    index.max_result_window

      当前索引返回的结果最大值,基于from + size,默认值是10000。搜索请求占用的堆内存和时间与from + size成比例。见scrollSearch After ,替换成这些方式来获得更多的搜索结果。

    index.max_inner_result_window

      from + size的最大值,用于索引的inner hits definition以及top hits aggregation。默认值为100。inner hits和top hits aggregation占用堆内存并且跟from + size 的大小成比例,该值用于限制内存的使用。

    index.max_rescore_window

      rescore请求中window_size的最大值。默认值为index.max_result_window,即10000。查询请求会占用堆内存并且跟max(window_size, from + size)的大小成比例,该值用于限制内存的使用。

    index.max_docvalue_fields_search

      某次查询中允许docvalue_fileds数量最大值。默认值为100。查询Doc-value字段有一定的开销因为可能需要查看对每一个字段中的每一个文档。

    index.max_script_fields

      某次查询中允许script_fields数量最大值。默认值为32

    index.max_ngram_diff

      The maximum allowed difference between min_gram and max_gram for NGramTokenizer and NGramTokenFilter。默认值为1

    index.max_shingle_diff

      shingle token filter中max_shingle_size和min_shingle_size之间允许的最大不同。默认值为3

    index.max_refresh_listeners

      索引中每一个分片上的可用的refresh listeners数量最大值。这些listeners用于实现refresh=wait_for

    index.analyze.max_token_count

      使用_analyze API允许生成token数量最大值。默认值为10000

    index.highlight.max_analyzed_offset

      在高亮请求中,允许处理(analyze)的字符数量最大值。这个设置只有在text上请求高亮,并且没有设置offset或者term vectors才会应用。默认值为1000000

    index.max_terms_count

      Terms Query中可以使用的term数量最大值。默认值为65536

    index.max_regex_length

      Regexp Query中可以使用的regex的长度最大值。默认值为1000

    index.query.default_field

      (string or array of strings)通配模版(Wildcard(*) patterns)会匹配到一个或者多个字段。下面的请求类型默认查询这些匹配到的字段:

      默认值为*,意味着匹配所有eligible字段用于term-level queries,除了metadata字段。

    index.routing.allocation.enable

      用于控制索引的分片分配。该参数可以设置为:

    index.gc_deletes

      a deleted document’s version number仍然可用的时长,它用于further versioned operations。默认值为60s

    index.default_pipeline

      用于索引的默认的ingest pipeline。如果设置了默认的pipeline但pipeline不存在,索引请求则会失败。可以使用pipeline参数覆盖默认的pipeline。特定的pipeline名称none意味着不允许任何pipeline 。

    index.final_pipeline

      索引的final ingest pipeline。如果设置了final pipeline并且该pipeline不存在,索引请求则会失败。 final pipeline总是在请求中指定的pipeline以及默认的pipeline之后运行。特定的pipeline名称none意味着不允许任何pipeline 。

    NOTE:你不能使用一个final pipeline修改_index字段,如果pipeline尝试进行修改,索引请求则会失败。

    index.hidden

      该值描述的是索引是否默认隐藏。隐藏的索引不会在匹配到通配表达式到后返回。使用了expand_wildcards参数的请求会受到该参数的控制。可选值为true或者false

    Settings in other index modules

      index module中其他可用的index setting:

      用于定义analyzers, tokenizers, token filters and character filters。

      控制分片如何,何时分配到哪一个节点。

      为索引开启/关闭dynamic mapping。

      控制后台合并处理程序如何对分片进行和并。

      配置自定义的Similarity设置自定义查询结果的打分方式。

      控制如何通过日志记录slow Query和slow fetch。

      配置用于访问分片数据的文件系统。

      控制transaction log以及后台flush操作。

      控制索引的历史操作。

      Configure indexing back pressure limits

    X-Pack index settings

      为索引指定生命周期策略以及rollover alias。

    Analysis

    (8.2)link

      The index analysis module acts as a configurable registry of analyzers用于将一个字符串字段转化为不同的term:

      Text analysis了解配置细节。

    Index Shard Allocation

    (8.2)link

      这个组件提供了per-index settings来控制分片到节点的分配:

    Index-level shard allocation filtering

    (8.2)link

      你可以使用shard allocation filtering来控制Elasticsearch如何为一个指定的索引进行分片的分配。索引层(index-level)的filtering跟 cluster-wide allocation filteringallocation awareness结合应用。

      Shard allocation filtering可以基于节点上自定义的属性或者内置属性例如_name, _host_ip, _publish_ip, _ip, _host, _id, _tier 以及_tier_preferenceIndex lifecycle management使用基于自定义的节点属性的filtering来决定在进行阶段转变时如何重新分配分片。

      设置(setting)cluster.routing.allocation是动态的,使得可以让live index从一些节点移到其他节点。只有在不会破坏其他路由限制(routing constraint)时才会重新分配分片,比如说不会在一台机器上同时分配主分片和副本。

      例如,你可以使用自定义的节点属性来指示(indicate)一个节点的性能属性并且使用shard allocation filtering将指定的索引路由到级别最合适的硬件中(the most appropriate class of hardware)。

    Enabling index-level shard allocation filtering

      基于自定义的节点属性进行过滤(筛选):

    1. 在每一个节点的配置文件elasticsearch.yml中指定过滤节点属性。例如,如果你有small, medium, 和 big三类节点,你可以添加一个size属性,基于节点的大小进行过滤。

      你也可以在节点启动时指定自定义的属性:

    1. 在索引中添加shard allocation filtering信息。index.routing.allocation这个设置支持三种类型的过滤:include, excluderequire。例如,告诉Elasticsearch使用index.routing.allocation.include将索引text的分片在值为big或者medium的节点上进行分配:

      如果你指定多个条件并要求节点同时满足才能在其节点上进行分片的分配:

      例如,将索引text的分片移到机架值为ranck1并且大小为big的节点,你可以这么指定:

    Index allocation filter settings
    index.routing.allocation.include.{attribute}

      将索引分配给一个节点,这个节点的{attribute}属性中至少包含用逗号隔开的值。

    index.routing.allocation.require.{attribute}

      将索引分配给一个节点,这个节点的{attribute}属性中包含所有用逗号隔开的值。

    index.routing.allocation.exclude.{attribute}

      将索引分配给一个节点,这个节点的{attribute}属性中不包含用逗号隔开的值。

      索引的分配设置支持下列的内置属性:

    _name根据节点名称进行匹配
    _host_ip根据host ip进行匹配
    _publish_ip根据发布的IP(publish IP)地址进行匹配
    _ip根据_host_ip或者_publish_ip进行匹配
    _host根据hostname进行匹配
    _id根据节点id进行匹配
    _tier根据data tier角色匹配,见data tier allocation filtering了解更多细节

      _tier这种过滤属性基于node角色,只有部分角色是 data tier角色并且一般的(generic)data role会匹配到任意的tier filtering。

      你可以使用通配符来指定属性值,例如:

    Delaying allocation when a node leaves

    (8.2)link

      无论什么原因,有意为之,或者其他原因导致节点离开集群后,master的反应是:

      这些动作通过尽快的保证每一个分片拥有副本分片的方式来保护集群不会丢失数据。

      尽管我们在node levelcluster level层限制(throttle)了并发恢复(concurrent recovery),但是这个"shard-shuffle"仍然会对集群造成一些额外的负载,如果节点很有可能很快重新加入到节点,那就没有必要做上面的动作了。想象下下面的场景:

      如果master可以等待几分钟,那么缺失的分片就可以以最小的网络代价将分片分配给Node5。已经被自动flush的空闲分片(没有收到索引请求的分片为idle shard)的处理过程会更快。

      因为动态设置index.unassigned.node_left.delayed_timeout,默认值为1m,节点离开集群后,未分配(unassigned)的分配(allocate)时间可能会被延后。

      可以在一个live index(或者所有的索引)上更新这个设置:

      开启延迟分配后,上面的场景就会变成:

    NOTE:This setting will not affect the promotion of replicas to primaries, nor will it affect the assignment of replicas that have not been assigned previously. In particular, delayed allocation does not come into effect after a full cluster restart. Also, in case of a master failover situation, elapsed delay time is forgotten (i.e. reset to the full initial delay).

    Cancellation of shard relocation

      如果延后分配超时,master会将缺失的分片分配给其他的节点并开始恢复。如果缺失的节点重新回到集群,并且它的分片跟主分片有相同的sync-id,shard recovery会被取消并synced shard会用于恢复。

      因为这个理由,默认的timeout只要设置为一分钟:即使shard relocation已经开始,取消恢复而是使用synced shard有更小的代价。

    Monitoring delayed unassigned shards

      因为这个timeout设置导致延后分配的分片数量可以通过cluster health API查看:

      第1行,这个请求会返回一个delayed_unassigned_shards的值。

    Removing a node permanently

      如果某个节点不再回到集群,你可能想让Elasticsearch马上分配缺失的分片,只要将timeout的值更新为0:

      缺失的分片开始恢复后,你就可以重新设置这个值。

    Index recovery prioritization

    (8.2)link

      whenever possible,未分配的索引会根据优先级依次进行恢复。根据下面的条件对索引进行排序:

      这意味着默认情况下,新的索引会先于旧的索引进行恢复。

      使用每一个索引中可自动更新的index.priority来自定义索引的优先顺序。例如:

      在上面的例子中:

      这个设置可以是一个整数,可以通过update indices settings更新。

    Total shards per node

    (8.2)link

      cluster-level的分片分配器(shard allocator)会尝试将一个索引的多个分片尽可能的分布在多个节点上。然而由于你拥有的分片和索引的数量,以及它们的大小,可能没法总是平均的进行分配。

      下面的动态设置允许你在每一个节点上,硬性限制(hard limit)单个索引允许的分片数量:

    index.routing.allocation.total_shards_per_node

      你也可以限制一个节点上的分片总数并且regardless of index:

    cluster.routing.allocation.total_shards_per_node

      Dynamic)每一个节点上允许分配的主分片和副本分片的最大数量。默认值-1(没有限制)。

      Elasticsearch会在分片分配时检查这个值,例如,某个集群的cluster.routing.allocation.total_shards_per_node的值为100,并且三个节点使用下面的分片分配:

      如果Node C发生故障,Elasticsearch会将分片分配到Node B。分配到Node A会超过node A的分片限制。

    WARNING:这些设置强行(impose)设置了限制会导致一些分片无法被分配。使用时需要注意这个问题。

    Index-level data tier allocation filtering

    (8.2)link

      你可以通过index-level的设置_tier_preference来控制将索引分配到哪个data tier 中。

      这个设置对应的data node roles:

    NOTE:date role不是合法的data tier因此不能用于_tier_preference。The frozen tier stores partially mounted indices exclusively

    Data tier allocation settings
    index.routing.allocation.include._tier_preference

      该参数的值是一个list。首先将索引分配到list中第一个data tier中,该节点必须是可用的。防止无法在期望的(prefer)data tier分配索引时导致无法分配这个索引。例如,如果你设置index.routing.allocation.include._tier_preferencedata_warm,data_hot,索引会分配到拥有data_warm角色的节点上,如果在warm tier中没有节点,但是有拥有data_hot角色的节点,那么就分配到这个节点中。Used in conjuction with data tiers

    Index blocks

    link

    Index block settings

    index.blocks.read_only

    Merge

    (8.2)link

      Elasticsearch中的一个分片即Lucene中的索引,Lucene中的索引由一个或多个段(segment)组成。Segment是内部存储单元(internal storage element),用于存储数据,并且是不可改变的(immutable)。小段会周期性的合并到大段中并expunge deletes。

      合并过程使用auto-throttle来平衡合并跟其他行为,例如查询之间的硬件资源的使用。

    Merge scheduling

      merge scheduler(ConcurrentMergeScheduler)控制了在需要进行合并时合并的执行过程。合并在不同的线程中运行,当使用的线程数量达到最大值后,后续的合并需要等待merge thread可用后才继续执行。

      merge scheduler支持下面的动态参数:

    index.merge.scheduler.max_thread_count

      单个分片上可以同时合并的线程数量。默认值为Math.max(1, Math.min(4 <<node.processors, node.processors>> / 2))。这个值在固态硬盘(solid-state-disk)上 work well。如果你的索引工作在spinning platter drives,将这个值降为1

    Similarity module

    link

    Slow log

    (8.2)link

    Search Slow Log

      分片层的慢查询日志(slow search log)允许将慢查询(query and fetch phases)记录到一个指定的日志文件中。

      可以同时为query跟fetch设置阈值,见下面的例子:

      上述的设置都是动态的,可以通过update indices settings设置,例如:

      默认情况下阈值是关闭的(默认值为-1)。

      由于是分片层级别范围,意味着记录的是对于特定分片的查询。日志中不包含全部的查询请求,而是通过广播到每一个分片去执行日志的记录。跟请求级别(request level)相比,这种分片层级别的日志记录的好处是能关联到某个机器上的情况。

      log4j2.properties文件中配置查询慢日志。

    Identifying search slow log origin

      明确是什么导致了慢查询通常是非常有用的。如果在请求的header中带有X-Opaque-ID,那么在查询慢日志(Search Slow log)中会增加一个额外的id字段来描述user ID。

    Index Slow log

      索引慢日志跟查询慢日志是类似的。以_index_indexing_slowlog.json.为后缀的日志以及阈值使用跟查询慢日志相同的配置方式:

      上述的设置都是动态的,可以通过update indices settings设置,例如:

      默认情况下,Elasticsearch会在慢日志(slowlog)中记录_source中前1000个字符。你可以通过index.indexing.slowlog.source更改这个限制。设置为0或者false将不会记录source字段。如果设置为true则会记录完整的_source并且不关心其内容的大小。_source中的内容被格式化(format)过使得可以作为日志中的单独一行。如果不格式化_source的内容是件重要的事情,那么可以通过将index.indexing.slowlog.reformat设置为false来关闭formatting,这样会使得_source中的内容以多行的形式出现在日志中。

      log4j2.properties文件中配置索引慢日志。

    Slow log levels

      可以通过设置查询\索引慢日志日志级别来设置合适的阈值,来关闭(switch off)冗长的(more verbose)设置。例如可以设置index.indexing.slowlog.level: INFO那么我们就可以设置index.indexing.slowlog.threshold.index.debugindex.indexing.slowlog.threshold.index.trace-1

    Store

    (8.2)link

      Store模块允许你控制索引数据在磁盘上的存储和访问方式。

    NOTE:这是一个low-level的设置。一些store的实现有较差的并发性或者没有对堆内存的使用进行优化。我们建议使用默认值(sticking to the defaults)

    File system storage types

      现在有不同的文件系统实现或者存储类型(file system implementations or storage types)。默认情况下,Elasticsearch会基于操作系统环境来选择最佳实现。

      Storage type可以通过在config/elasticsearch.yml文件中配置来显示的为所有的索引进行设置:

    这是一个静态设置,可以在创建索引时基于每个索引进行设置:

    WARNING:这是一个专家(expert-only)设置并且可能在未来的版本中移除。

      下面的内容列出了所有支持的不同类型的存储:

    fs

      默认的文件系统实现。会根据操作系统环境选择最佳的实现方式。目前在所有支持的系统上都是hybridfs,但可能会发生变化。

    simplefs

      deprecated::[7.15, "simplefs已经被弃用并将在8.0中移除",转而用niofs或者其他文件系统。Elasticsearch 7.15 及以后的版本中使用niofs作为simplefs这个存储类型会提供相对于simplefs更好或者相同的性能]

      Simple FS 类型是使用随机访问文件的文件系统存储的简单实现(straightforward implementation)(对应Lucene中的SimpleFsDirectory)。这种实现有较差的并发性能(使用多线程会有瓶颈)并且没有对堆内存的使用进行优化。

    niofs

      NIO FS类型使用NIO将分片索引存储在文件系统上(对应Lucene中的NIOFSDirectory)。他允许多线程并发的读取相同的文件。由于在SUN Java实现中存在一个bug,所以不建议在Windows上使用这个类型并且没有对堆内存的使用进行优化。

    mmapfs

      MMap FS 类型通过将文件映射到内存(mmap)将分片索引存储在文件系统上(对应Lucene中的MMapDirectory)。内存映射占用了进程中的一部分虚拟内存地址空间,等于被映射文件的大小。在使用这个之前确保你拥有大量的virtual address space

    hybridfs

      hybridfs类型是niofsmmapfs的混合类型,基于不同类型的文件的读取访问模式选择最佳的文件系统类型。目前只有Lucene term dictionary,norms和doc values文件是内存映射的。其他的文件使用Lucene的NIOFSDirectory打开。跟mmapfs一样,在使用这个之前确保你拥有大量的virtual address space

      你可以通过node.store.allow_mmap来限制(restrict)mmapfs以及hybridfs的使用。这是一个布尔类型的设置描述是否允许内存映射(memory-mapping)。默认值是允许的。这个设置是很有用的,比如说,如果你处于无法控制创建大量内存映射的环境中,那么你需要禁用使用内存映射的能力。

    Preloading data into the file system cache

    link

    Translog

    (8.2)link

      Lucene中的commit会将更改(changes)持久化到磁盘,这是一种开销很大的操作,所以不能在每次索引或者删除操作后执行commit。如果在索引过程中退出或者硬件错误,那么在一次commit后,下一次commit前这个期间发生的变更会被移除(丢失)。

      Lucene中,每一次单独的变更都执行commit的话其开销是很大的,所以每一个分片都会把写操作(writes operation)写入到事务日志(transaction log)中,即所谓的translog。所有的索引和删除操作在Lucene中建立索引后(未持久化到磁盘)会被添加到translog中,在发生crash时间后,最近被确认的(acknowledge)(已经写入Lucene的内存意味着确认,但未持久化到磁盘)但是不在Lucene commit中的操作,在分片恢复时会使用translog进行恢复。

      Elasticsearch中执行flush即执行Lucene中的commit操作,并且开始一个新的translog generation。flush会在后台自动执行使得不会让translog记录太多操作,这样在恢复期间不会因为重新(replay)执行translog中的操作使得花费很多的时间。也可以通过API来执行flush,但这几乎是没必要的。

     

    Translog settings

      translog中的数据只有在它是fsync并且commit后会持久化到磁盘上。硬件故障的事件或者是操作系统崩溃或者JVm崩溃或者分片失败,上一次commit之后的translog数据都会丢失。

      index.translog.durability默认设置为request意味着在translog在成功fsynced并且commit到主分片以及每一个分配的副本后,Elasticsearch将只报告成功的索引、删除、更新、bulk request给client。如果index.translog.durability设置为async,那么Elasticsearch只会每隔index.translog.sync_interval对translog进行fsynced并且commit,意味着当节点恢复时,任何crash之前的操作可能会丢失。

      下面每个索引的dynamically updatable设置控制translog的行为:

    index.translog.sync_interval

      translog fsynced 到磁盘并且commit的间隔,不考虑写操作,默认时间是5s。不允许设置100ms以下的值。

    index.translog.durability

      translog是否在每一次的index、delete、update或者bulk request都进行fsynced并且commit。可以设置为下面的值:

    request

      (默认值)每一个请求都进行fsynced并且commit。硬件错误事件时,所有确认的写操作已经commit到磁盘。

    async

      每隔index.translog.sync_interval进行fsynced并且commit。在出现失败事件时,上一次自动commit后的所有确认的写操作都会被丢弃

    index.translog.flush_threshold_size

      所有在Lucene中没有安全持久化的操作都会存储在translog中,这个操作对读操作是可见的,在分片被停后并且必须要恢复时,它们用于重新索引操作。这个设置控制了这些操作占用总量的最大值,防止恢复时占用太长的时间。当达到最大值时会触发flush,生成一个新的Lucene commit。默认值是512mb

    History retention

    (8.2)link

      Elasticsearch有时候需要replay在分片上执行的一些操作。例如,如果一个副本分片简单的offline了,相较于从头开始(from scratch)构造这个副本分片,只replay它在offline期间丢失的操作有着更高的效率。同样的,cross-cluster replication的工作方式为:在leader cluster执行操作,然后在follower cluster上replay这些操作。

      Elasticsearch对索引的写操作在Lucene层来说只有两个操作:索引(添加)一篇文档或者删除现有的文档。更新操作的实现方式是先删除旧的文档然后索引一篇新的文档。索引一篇文档到Lucene的操作包含了所有用于replay的信息,但是对于文档的删除不是这样的。为了解决这个问题, Elasticsearch使用了名为软删除soft deletes的功能来保留Lucene索引上最近的删除信息,使得可以用于replay。

      Elasticsearch只保留索引中一些最近删除的文档,是因为软删除的文档仍然占用一些空间。Elasticsearch最终会完全的丢弃这些软删除的文档来释放空间使得索引不会随着时间一直增长。Elasticsearch不需要replay在分片上执行的每一个操作,因为总是有可能在remote cluster执行完整的分片拷贝。然而,复制整个分片可能比replay一些丢失的操作要花费更多的时间,所以Elasticsearch会保留期望在未来用于replay的所有操作。

      Elasticsearch使用了shard history retention leases的机制来追踪期望在未来将用于replay的操作。每一个可能需要用于replay的操作的分片拷贝(shard copy)必须首先为自己创建一个shard history retention leases。例如,this shard copy might be a replica of a shard或者在使用cross-cluster replication时的follower index。每一个retention lease会追踪对应的分片拷贝第一个没有收到的操作的序号,随着分片拷贝收到新的操作,增加retention lease中的序号值,表示不会在未来replay这些操作。一旦soft-deleted operations没有被任何的retention lease占用(hold),Elasticsearch就会丢弃它们。

      如果分片拷贝发生了故障,那它会停止更新它的shard history retention lease。意味着Elasticsearch会保留所有的新的操作,使得在分片拷贝恢复后执行replay操作。然而,retention lease只持续一个有限的时间。如果分片拷贝没有及时的恢复,那retention lease会到期。这可以保护Elasticsearch,防止出现某个分片拷贝永久性的故障后,retention history会永久保留的问题,一旦某个retention lease到期后,Elasticsearch可以开始丢失这些历史信息。如果分片拷贝在retention lease到期后才恢复,那Elasticsearch会回退到拷贝整个索引,因为这时候再也没法简单的replay丢失的操作了。retention lease的过期时间默认是12h,这个时间已经足够长了,适用于大多数的场景。

    History retention settings

    index.soft_deletes.enabled

      索引是否开启soft deletes(Deprecated in 7.6.0)。Soft deletes只能在创建索引时配置并且是Elasticsearch6.5及以后的版本中的索引创建。默认值为true

    index.soft_deletes.retention_lease.period

      在retention lease过期前保留shard history retention lease的最大时间。Shard history retention leases 能保证Lucene在执行段的合并时仍然会保留Soft delete对应的信息。如果soft delete在复制(replicate)到follower之前,在段的合并期间被合并了,那么follower中接下来的操作会因为leader上不完整的历史操作而失败。默认值12h

    Index Sorting

    (8.2)link

      在Elasticsearch中创建一个新的索引时,可以配置每一个分片中的段内文档的排序方式。默认情况下,Lucene不会使用任何的排序。index.sort.*这些设置定义了使用哪些字段用于段中文档的排序。

    WARNING:nested fields are not compatible with index sorting。because they rely on the assumption that nested documents are stored in contiguous doc ids, which can be broken by index sorting。An error will be thrown if index sorting is activated on an index that contains nested fields.

      下面的例子定义如何在单个字段上定义一个排序

      第5行,根据date字段排序   第6行,降序

      也可以使用多个字段进行排序:

      第5行,先根据username字段排序,再根据date字段排序   第6行,根据username字段使用升序,根据date使用降序

      Index Sorting支持下面的设置:

    index.sort.field

      指定用于排序的一个或者多个字段。只允许开启doc_valuesbooleannumericdatekeyword类型的字段。

    index.sort.order

      每一个排序字段的排序规则:

    index.sort.mode

      Elasticsearch支持使用mutil-values的字段用于排序。这个参数描述的是使用哪个值用于文档排序。两个参数值可选:

    index.sort.missing

      这个参数描述的是,如果文档中缺失用于排序的字段该如何对这篇文档进行排序。两个参数值可选:

    WARNING:Index Sorting只有定义在创建索引时。不能对现有的索引添加或者更新排序。Index Sorting在索引期间有一定的开销,因为文档必须在flush和merge时进行排序。你应该在启动这个功能前测试下对你的应用的影响

    Early termination of search request

      默认情况下,Elasticsearch中的一个查询请求需要访问匹配查询的所有文档才能获取到某个排序条件下的TopN的文档。然而当Index sort和查询中指定的排序(Search sort)一致时,每个段中的查询TopN的操作就有可能限制需要访问的文档数量。例如,如果索引中的文档根据timestamp字段排序:

      第6行,索引按照timestamp字段降序排序(most recent first)

      你可以搜索最新的10条事件:

      Elasticsearch会检测到每一个的top doc都已经排序过了,并且将只会对每个段中的TopN的文档进行比较。剩余的满足查询条件的文档用于统计结果的数量以及构造aggregation。

      如果你只是想要查找最新的10条事件并且对于满足查询条件的文档的数量不感兴趣,那么你可以将track_total_hits设置为false

      第4行,Index sort将用于top documents并且每个段都会在收集了前10篇文档后就提前退出。

      这次Elasticsearch不会去统计满足查询条件的文档的数量,并且能在每一个段收集了N篇文档后就提前退出。

      第3行,由于提前退出了,所以不知道满足查询条件的文档数量。

    NOTE:聚合操作会收集所有满足查询条件的文档,无视track_total_hits的值。

    Use index sorting to speed up conjunctions

    (8.2)link

      Index sorting对organize Lucene doc id(不要跟_id混淆(conflate))非常有用,使得conjunction更加高效(a AND b AND ...)。如果任意一个clause没有匹配到,那么整个conjunction都不会匹配,conjunction可以变的非常高效。通过使用Index sorting,我们可以把没有匹配的文档放一起,有助于在范围很大的ID区间内进行跳跃,跳过那些不匹配的文档。

      这个trick只能在low-cardinality的字段上工作。A rule of thumb,你首先应该将拥有low-cardinality以及经常用于过滤的字段作为排序字段。The sort order (asc or desc) does not matter as we only care about putting values that would match the same clauses close to each other。

      例如,如果你正在索引汽车用于销售,你应该根据fuel type, body type, make, year of registration and finally mileage进行排序。

    Indexing pressure

    (8.2)link

      索引文档到Elasticsearch会引入系统的内存和CPU的负载。每一个索引操作,包含了coordinating, primary和replica这几个阶段。这些阶段在集群中的多个节点上运行。

      Indexing pressure可以由外部的索引请求或者内部的,例如恢复,跨集群副本分片(cross-cluster replication)引起。如果系统中有过多的索引工作,集群会达到饱和(saturated)。这会对其他操作造成不好的(adversely)影响,例如查询,cluster coordination以及background processing。

      为了防止出现这个问题,Elasticsearch内部会监控索引负载。当负载超过一定的限制,新的索引操作会被reject。

    Indexing stages

      外部的索引操作(external indexing operation)会经历三个阶段:coordinating,primary以及replica。见Basic write model

    Memory limits

      节点设置indexing_pressure.memory.limit严格限制了未完成(outstanding)索引请求的可用的字节数量。这个设置默认值是堆内存的10%。

      每一个索引阶段(indexing stage)的开头,Elasticsearch会统计一个索引请求占用的字节数。在索引阶段的结尾才会释放这个统计。意味着上游的阶段会统计请求开销直到所有的下游都完成。例如,coordinating请求会保留统计直到primary和replica阶段完成,primary请求会保留统计直到每一个同步的replica返回响应,如果有需要的话开启replica重试。

      当未完成的coordinating, primary和 replica的索引占用字节超过配置的值后,节点会在coordinating或者primary阶段reject这个新的索引请求。

      当未完成的replica阶段的索引字节超过配置限制的1.5倍后,节点会在replicate阶段reject这个索引请求。这种设计意味着由于indexing pressure应用于节点,它会天然的在发生未完成的replica工作时会停止coordinating和primary工作。

      indexing_pressure.memory.limit的默认为10%。你应该深思熟虑后再去修改它。这个设置只应用于索引请求。这意味着其他的索引开销(buffers,listener,等等)同样需要堆内存。Elasticsearch的其他组件同样需要内存,这个值设置的太高会影响其他有内存操作(memory operation)的操作和组件。

    Monitoring

      你可以使用node stats API查询indexing pressure metrics。

    Indexing pressure settings

    indexing_pressure.memory.limit

      索引请求可能需要消费的字节数。当达到或者超过这个限制后,节点会reject新的coordinating和primary操作。当replica操作消费超过1.5倍,节点会reject新的replicate请求。默认值是堆内存的10%。

    Mapping

    (8.2)link

      Mapping是定义一篇文档中的字段(field)如何存储以及索引的过程。

      每篇文档都是字段的集合,每个字段都有自己的date type。在mapping你的数据时,你要创建一个mapping定义,定义中包含的字段的集合跟文档相关(pertinent)。mapping的定义同样包括了metadata fields。比如_source字段,它自定义了文档相关metadata的处理方式。

      使用dynamic mappingexplicit mapping来定义你的数据。每一种方式在你使用数据过程中有不同的好处。例如,显示的对字段进行映射使得不按照默认方式进行处理,或者你想要获得对字段的创建有更多的控制,随后你可以允许Elasticsearch对其他的字段进行动态映射。

    NOTE:在7.0.0之前,mapping的定义包含一个类型名(type name)。Elasticsearch 7.0.0以及之后的版本再也不接受一个默认的mapping。见Removal of mapping types

    Experiment with mapping options

      使用Define runtime fields in a search request来体验不同的mapping options,同时还可以在查询请求中通过覆盖mapping中字段值的方式来解决你的Index mapping中的错误。

    Dynamic mapping(overview)

      Dynamic mapping适合你刚开始接触Elasticsearch/Mapping时体验数据的探索。Elasticsearch会自动的增加新的字段,你只需要索引文档就可以了。你可以添加字段到top-level mapping中,以及inner objectnested字段中。

      使用dynamic templates自定义mappings,根据满足的条件动态的添加字段。

    Explicit mapping(overview)

      Explicit mapping允许你精确的选择并定义mapping definition,例如:

      在不需要reindex的前提下,使用runtime fields作出策略变更。runtime field和indexed field配合使用来平衡资源使用和性能。索引文件体积会更小,但是会降低查询性能。

    Settings to prevent mapping explosion

      在一个索引中定义太多的字段会导致mapping explosion,引起OOM的错误以及难以恢复的情况。

      想象这么一种场景,每一篇新的文档都会引入新的字段,比如使用了dynamic mapping。每一个字段添加到Index mapping中,随着mapping中字段的数量的增长便成长为了问题。

      使用mapping limit settings限制mapping(手动或者动态创建)中字段的数量,防止因为文档导致mapping explosion。

    Dynamic mapping

    (8.2)link

      Elasticsearch最重要的一个功能就是能够让你快速的去探索数据。索引一篇文档,你不需要首先创建一个索引,然后定义好mapping,接着定义每一个字段,你只需要直接对一篇文档进行索引,索引名、类型、字段都会自动的配置好。

      第1行,创建一个名为data的索引,以及_doc类型的mapping,和一个字段名为count,数据类型为long的字段。

      这种自动检测并且添加(addition of)一个新字段的机制称为动态索引dynamic mapping。可以基于下列方法来自定义你的动态索引规则:

    TIP:Index templates允许你为新的索引配置默认的mapping,settings 以及aliases ,不管是自动还是显示创建索引。

    Dynamic field mapping

    (8.2)link

      当Elasticsearch检测到文档中有一个新字段,会默认将它添加到mapping中。参数dynamic控制了其行为方式。

      你可以设置参数dynamic的值为true或者runtime来显示的指引Elasticsearch对于即将到来的文档动态的创建字段。当开启了dynamic field mapping ,Elasticsearch会根据下表中的规则决定如何映射为不同类型的字段。

    NOTE:Elasticsearch仅支持下表中字段的数据类型(field data type)的自动检测,你必须显式的指定其他数据类型。

    JSON data type"dynamic":"true""dynamic":"runtime"
    nullNo field addedNo field added
    true or falsebooleanboolean
    doublefloatdouble
    longlonglong
    objectobjectNo field added
    arrayDepends on the first non-null value in the arrayDepends on the first non-null value in the array
    string that passes date detectiondatedate
    string that passes numeric detectionfloat or longdouble or long
    string that doesn’t pass datedetection or numeric detectiontext with a .keywordsub-fieldkeyword

      你可以同时在文档层或者object层来关闭动态mapping。将参数dynamic设置为false来忽略新的字段,设置为strict来当Elasticsearch遇到一个未知的字段时就reject这个文档。

    TIP:可以通过update mapping API来对现有的字段的参数dynamic的值进行更新。

      你可以为Date detectionNumeric detection自定义dynamic field mapping的规则。你可以使用dynamic_templates来自定义个性化的mapping规则并应用到额外的dynamic fields。

    Date detection

      如果开启了date_detection(默认开启),新来的string类型的字段会被检测是否其字段值能够被dynamic_date_formats中指定的日期模板匹配到。如果匹配到了,就添加对应的新的date字段。

      dynamic_date_formats的默认值是:

      例如:

      第6行,create_date字段以"yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"这种format作为date被添加。

    Disabling date detection

      可以将date_detection的值设置为false来关闭date detection。

      第8行,create_date被添加为text字段。

    Customizing detected date formats

      另外,dynamic_date_formats也能定制为你自己的formats):

    Numeric detection

      JSON原生支持浮点型以及整数的数据类型,但是有些应用或者语言有时会将数值类型作为(render)字符串类型。通常正确的解决办法是显示的映射这些字段。但是numeric detection能使得自动实现(默认关闭):

      第10行,my_float被添加为float字段   第11行,my_integer被添加为integer字段

    Dynamic templates

    (8.2)link

      Dynamic template能让你在默认的dynamic field mapping rules之外,更好的控制Elasticsearch如何映射你的数据。通过设置dynamic参数的值为true或者runtime来开启dynamic mapping。然后你就可以基于下面的匹配条件使用dynamic template来自定义mapping,动态的应用(apply)到字段:

      使用{name}{dynamic_type}这些template variables作为mapping中的占位符。

    IMPORTANT:只有当某个字段包含一个具体的值才能添加Dynamic field mappings。当字段中包含null或者空的数组时,Elasticsearch不会添加一个dynamic field mapping。如果在dynamic_template中使用了null_value选项,只有在一篇有具体的值的文档索引后才能应用这个选项。

      Dynamic template由一组带名称的object数组组成:

      第3行,模板的名称可以是任意的string value   第4行,匹配条件可以包含: match_mapping_type, match, match_pattern, unmatch, path_match, path_unmatch   第5行,匹配到的字段应该使用的mapping

    Validating dynamic templates

      如果提供的mapping中包含了一个非法的mapping 片段(snippet),则返回一个validation error。Validation会在索引期间应用dynamic template时发生,并且在大多数情况下发生在dynamic template更新后。提供一个非法的mapping片段可能会因为下面的一些条件导致更新或者dynamic template的校验失败:

      模版是有序处理的,使用匹配到的第一个模板。当通过update mapping API更新新的dynamic template后,所有现有的模板会被覆盖。这使得最开始添加的模板可以被重新排序或者被删除。

    Mapping runtime fields in a dynamic template

      如果你想要Elasticsearch动态映射某些类型的新字段作为runtime field,那么在索引mapping中设置"dynamic":"runtime"。这些字段不会被索引,在查询期间从_source中获取。

      或者你可以使用默认的动态mapping规则,然后创建dynamic模版将指定的字段映射为runtime field。你可以在索引mapping中设置"dynamic":"true"然后创建一个dynamic template将某些类型的新字段映射为runtime field。

      比如说你的数据中的每一个字段的字段名都是以ip_开始的。基于dynamic mapping rules,Elasticsearch将通过了numeric检测的字段映射为float或者long,然而你可以创建一个dynamic template将string类型的值映射为runtime filed并且字段的类型为ip

      下面的请求中定义了一个名为strings_as_ip的dynamic template。当Elasticsearch检测到新的字段值为字符串字段匹配到了ip*这个pattern,它就会将这些字段映射为runtime field并且字段的类型为ip。因为ip字段没有动态映射,你可以使用带"dynamic":"true"或者"dynamic":"runtime"的模版。

      this template来了解如何使用dynamic template将字符串字段映射为indexed filed或者runtime field。

    match_mapping_type

      match_mapping_type是数据类型,用于JSON parser。由于JSON不能区分integerlongdoublefloat,浮点型数值都被认为是double的JSON数据类型,integer数值都被认为是long

    NOTE:在dynamic mappings中,Elasticsearch总是选择wider data type。唯一特例是float,它需要比double更少的存储空间并且对于大多数应用来说精度是足够的。Runtime field不支持float,这就是为什么"dynamic":"runtime"使用的是double

      Elasticsearch会自动检测下面的数据类型:

    JSON data type"dynamic":"true""dynamic":"runtime"
    null不增加字段不增加字段
    true/falsebooleanBoolean
    doublefloatdouble
    longlonglong
    objectobject不增加字段
    array取决于数组中第一个不是null的值取决于数组中第一个不是null的值
    string(通过了Numeric detection的解析)float或者longdouble或者long
    string(通过了date detection的解析)datedate
    string没有通过date或者numeric的解析text以及.keyword的子字段keyword

      使用通配符(*)匹配所有的数据类型。

      例如,如果想要将数值类型的字段都映射为integer而不是long,并且所有的字符串字段映射为textkeyword,我们可以使用下面的模板:

      第33行,my_integer字段映射为一个integer   第34行,my_string字段映射为text以及一个keyword(见multi-field

    match and unmatch

      match参数使用pattern来匹配字段名(field name),同时unmatch使用pattern排除match参数匹配到的字段。

      match_pattern参数调整了match参数的行为,支持Java regular expression来匹配字段名而不是使用简单的通配符,例如:

      下面的例子匹配了所有字段名以long_开头的字段,但是排除了以_text结尾的字段,并将它们的字段值映射为long

      第21行,long_num字段映射为long   第22行,long_text使用了默认的string映射

    path_match and path_unmatch

      path_matchpath_unmatch参数的工作方式跟matchunmatch是一样的,不同的是,它们是应用在full dotted path上,而不是final name,比如:some_object.*.some_filed

      下面的例子将object类型的字段name中的除了middle的所有字段都copy to顶层的full_name中:

      注意的是path_matchpathc_match除了匹配leaf filed(上图中的firstmiddlelast就是leaf field)还会匹配object path(下图中的name.tittle就是object path)。例如,索引下面的文档会报错因为path_match这个设置同样会匹配到name.tille,这个字段是个object不能映射为text:

    Template variables

      {name}{dynamic_type}是mapping中的占位符,它们分别用字段名和检测到的动态类型(detected dynamic type)进行值的替换。下面的例子中将所有字段值为字符串的字段名作为analyzer的值,并且关闭所有不是字符串类型的字段的doc_values

      第30行,因为字段名为english的字段值是string类型,那么它的字段名将作为anlyzer参数的值   第31行,因为count的字段值是个数值,所以它会被动态映射为long类型并且关闭doc_values

    Dynamic template examples

      下面是一些可能比较有用的dynamic template:

      当你设置了"dynamic":"true",Elasticsearch会将字符串字段映射为text字段以及keyword的子字段。如果你只要索引结构化的内容并且对不需要全文检索,你可以让Elasticsearch只映射为keyword字段。然而,你在查询那些被索引的字段时,你必须提供精确的关键字。

    text-only mappings for strings

      与上一个例子相反的(contrary)是,如果你只关心字符串字段上的全文检索并且不计划使用聚合,排序或者精确(exact )查询,你可以让Elasticsearch映射为text了:

      或者你可以创建一个dynamic template将你的字符串字段在mapping的runtime块映射为keyword字段。当Elasticsearch检测到string类型的字段,会将这些字段创建为runtime field并且字段的类型为keyword

      尽管你的字符串字段不会被索引,但是它们的值会存储在_source中并且可以用于查询请求,聚合,过滤和排序。

      例如下面的请求创建了一个dynamic template将字符串字段映射为runtime field并且字段的类型为keyword,尽管runtime的定义是空白的。但是基于Elasticsearch用于添加字段的类型到mapping的dynamic mapping rules,新的字符串字段会被映射为runtime field并且字段的类型为keyword。所有没有通过date detection和numeric detection的string都会被自动的映射为keyword

      你可以索引一篇简单的文档:

      当你查看mapping时,你会看到english字段是一个runtime field并且字段的类型为keyword

    Disabled norms

      Norms是索引期间(index-time)的打分因子。如果你不关心打分,那你就不能根据文档分数对文档进行排序,你可以禁用索引中的打分因子的存储来节省一些空间。

      模版中出现的keyword字段是dynamic mappings中默认存在的。当然如果你不需要在这个字段上执行精确查询或者聚合,你可以不需要它们,你可以正如上文中描述的那样来移除它们。

    Time series

      当在Elasticsearch中处理时序数据时,通常有很多的数值类型的字段,你会经常使用它们用于聚合但是从来不用于过滤。在这种场景下,你可以不索引这些字段来节省磁盘空间并且能获得一些索引速度的提升:

      第18行,正如默认的dynamic mapping rules,double会被映射为float,因为通常来说精确是足够的,并且只要一半的磁盘空间。

    Explicit mapping

    (8.2)link

      相较于Elasticsearch猜测你的数据类型,如果你更了解数据类型,你可能想要指定自己的显示的mapping(explicit mapping)。

      你可以在create an index 或者add fields to an existing index时创建字段的mapping(field mapping)。

    Create an index with an explicit mapping

      你可以使用create index API创建一个explicit mapping的新的索引。

      第5行,创建一个名为age,类型为integer的字段   第6行,创建一个名为email,类型为keyword的字段   第7行,创建一个名为name,类型为text的字段

    Add a field to an existing mapping

      你可以使用update mapping API在一个现有的(existing)索引中增加一个或者多个字段。

      下面的例子中创建了一个名为employee-id,类型为keyword,mapping参数为index的字段。这意味着employee-id字段的字段值会被存储但是不会被索引,即无法用于查询。

    Update the mapping of a field

      除了支持更新mapping parameters,你不能对现有的字段更改mapping或者字段的类型。更改一个现有的字段会invalidate已经写入到索引文件中的数据。

      如果你更改data stream的backing index中字段的类型,见Change mappings and settings for a data stream

      如果你需要在其他索引中更改字段的mapping,那么使用正确的mapping创建一个新的索引,然后reindex你的数据到那个索引中。

      重命名一个字段会invalidate使用旧的字段名索引的数据,你可以增加一个alias字段创建一个替换的字段名。

    View the mapping of an index

      你可以使用get mapping API查看现有的索引的mapping。

      下面的API返回下面的响应:

    View the mapping of specific fields

      如果你只想指定一个或者多个字段并查看它们的mapping,你可以使用get field mapping API。

      如果你的索引包含很多的字段或者你不需要完整的索引的mapping,这个接口是很有用的。

      下面的请求展示了employee-id字段的mapping。

      这个API返回下面的响应:

    Runtime fields

    (8.2)link

      runtime field是在查询阶段计算出来的字段,可以让你用于:

      你可以通过search API访问runtime field,就像访问其他字段一样,Elasticsearch不会对runtime field区别对待。你可以在index mapping或者search request中定义runtime field,提供不同的方式体现了runtime field内部的灵活性。

      _search API上使用fields参数来 retrieve the values of runtime fields,runtime filed不会在_source中展示,但是fields API可以在所有字段上使用,即使这些字段不在_source中。

      Runtime fields用于处理日志数据(log data)时候特别好用(见例子),特别是当你不确定数据结构时。尽管查询性能会降低,但是你能更快的索引日志数据,并且索引体积较小。

    Benefits

      由于runtime fiels没有被索引,所以新增的runtime field不会增加索引大小。你直接在索引mapping中定义runtime fields来节省存储开销以及提高提取(ingestion)速度。你能够更快的把数据提取到Elastic Stack并可以正确的访问。当你定义了一个runtime field,你可以在在查询请求中使用它用于聚合、过滤、和排序。

      如果你让一个runtime field成为一个索引字段(indexed field),你不需要修改任何请求来指定runtime filed。甚至你可以指定某个字段在某些索引中是runtime field,同时在某个索引中是一个索引字段。你可以灵活的选择哪些字段作为索引字段还是runtime field。

      Runtime fileds最核心、最重要的好处就是它提供了在提取(ingest)文档后可以在这篇文档中添加字段的能力。这种能力简化了mapping的设计,因为你不需要提前决定用哪种数据类型进行解析,可以在任何时候修改。使用runtime field使得有更小的索引和更快的提取时间,这将使用更少的资源并降低你的操作成本。

    Incentives

      使用脚本的_search API中的很多方法可以用runtime field替代。runtime field的使用会受到runtime field中定义的脚本需要处理的文档数量的影响。例如,如果你在_search API上使用fields参数来retrieve the values of a runtime field,脚本跟script fields 一样,都只会对top hits进行处理。

      你可以使用script fields访问_source中的值并且返回基于脚本计算出的值。runtime fields有相同的能力,但是能提供更好的灵活性,因为在查询请求中可以对runtime fields进行查询以及聚合。Script field只能获取数据。

      同样的,你可以在查询请求中基于脚本写一个script query来过滤文档。runtime field提供一个类似的功能并且更加灵活。你编写一个脚本来创建字段值,它们能在任何地方都可见,比如fieldsall queries以及aggregation

      你可以使用脚本来sort search results,但使用runtime field可以完成完全相同的工作。

      如果你将查询请求中所有的脚本替换为runtime field,性能是差不多的,因为它们计算的文档数量是一样的。这个功能的性能很大程度上取决于脚本需要计算的文档数量。

    Compromises

      Runtime fields使用更少的磁盘空间并且在查询你的数据上提供灵活性,但是会因为runtime脚本中定义的计算而影响查询性能。

      若要平衡性能和灵活性,将那些你常用于查询,过滤,例如timestamp这类字段,对这些字段进行索引。在执行查询时,Elasticsearch会自动的使用这些索引字段(indexed field)在很快的响应时间内获得结果。随后你可以使用runtime fields来限制Elasticsearch需要用于计算的字段的数量。索引字段和runtime field的配合使用,可以提供数据弹性以及如何为其他的字段定义查询。

      使用asynchronous search API用于执行包含runtime field的查询。这种查询方法可以抵偿计算每一篇包含runtime field的文档的性能影响。如果query不能同步返回数据集,你将在这些结果变得可见后异步获取到。

    IMPORTANT:对runtime field的查询是昂贵的,如果search.allow_expensive_queries设置为false,Elasticsearch不允许昂贵的查询并且reject所有对runtime field的查询。

    Map a runtime field

    (8.2)link

      通过在mapping中定义一个runtime section以及一个Painless script就可以映射到runtime fileds。这个脚本可以访问所在文档中所有的内容,包括可以通过params._source来读取到_source的内容以及任何字段加上字段值。在查询时,查询条件中包含了这个scripted field(下文中的day_of_week),脚本会运行并且生成结果给scripted field。

    当定义了一个脚本用于runtime fields时,脚本中必须使用 emit method来输出计算的值。

      下面例子的脚本中,将根据@timestamp的字段值计算出的结果赋值给day of the weekday of the week是一个data类型:

      runtime中可以是以下的类型:

      date类型的runtime fileds的字段值格式跟date字段接受的format是一致的。

      lookup类型的runtime fileds允许从关联的索引中检索字段的信息,见retrieve fields from related indices

      如果开启了dynamic field mapping,并且dynamic参数设置了参数值runtime,新的字段会作为runtime自动添加到索引mapping中。

    Define runtime fields without a script

      Runtime fileds通常使用脚本来管理数据,然后有些情况下可以不使用脚本来使用runtime fileds。比如你想从_source中检索出某个字段的字段值并不作任何的改变,那你不需要提供脚本,你只需要创建一个不带脚本的runtime fileds:

      当没有提供脚本时,在查询期间,Elasticsearch会从_source中查找到跟runtime fields字段名一样的字段,如果存在的话就返回该字段值。如果不存在,那么在response中不会包含runtime fields的任何值。

      在大多数情况下,会优先从doc_values中读取。由于在Lucene中不同的存储方式,相较于从_source中检索,通过doc_values的方式读取速度更快。

      但是有些场景下需要从_source中检索字段的信息。比如说由于text类型默认情况下不会有doc_values,所以不得不从_source中读取,在其他情况下,可以选择禁用特定字段上的doc_values。

    NOTE:你可以在params._source中添加前缀来检索想要的数据(比如params._source.day_of_week),为了简单起见,定义runtime fields时,建议尽可能在mapping定义中不使用脚本。

    Updating and removing runtime fields

      你可以在任何时候更新或者移除runtime fileds。添加一个相同名称的runtime files就可以覆盖现在有的runtime files,通过设置为null来移除现在有的runtime files:

    Downstream impacts

      更新或者移除runtime files可能会使得正在查询的请求返回的数据不一致。由于mapping的变更可能会影响到每一个分片会访问到不同版本的脚本。

    WARNING:如果你对runtime fileds进行变更或者移除,依赖runtime fileds的Existing queries or visualizations in Kibana可能会出现失败的情况,比如可视化的图表使用runtime field类型的ip被改为boolean,或者被移除后会导致出错。

    Define runtime fields in a search request

    (8.2)link

      你可以在查询请求中指定一个runtime_mappings区域/块(section)来创建runtime fields,它只属于这次的请求。你指定了一个脚本作为runtime_mappings的一部分跟adding a runtime field to the mappings是一样的。

      在查询请求中定义一个runtime field跟在index mapping中使用的格式是一样的,所以只需要把查询请求中runtime_mappings区域中的内容直接拷贝到index mapping的runtime区域中。

      下面的查询请求添加了day_of_week字段到runtime_mappings区域中,这个字段的字段值将被自动的计算出来并且只处于这次查询请求的上下文中(only within the context of this search request)。

    Create runtime fields that use other runtime fields

      你甚至可以在查询请求中定义runtime field,并且它的字段值可以从其他的runtime field中计算出来。比如你批量索引了传感器的数据:

      你意识到你将数值类型numeric type索引成了text类型,你想要在measures.start以及measures.end字段上进行聚合操作却无法实现,因为你不能在text类型上进行聚合。Runtime fields to the rescue!。你可以添加runtime fileds,跟索引字段index field(即measures.start和measures.end)的字段名保持一致并且修改字段的类型:

      Runtime field的优先级(take precedence over)比相同字段名的索引字段高。这种灵活性使得你可以投影(shadow)现有的字段(existing fields)并且计算出新值而不用修改字段本身的信息。如果你在索引数据的时候犯错了,那么你可以使用runtime field在查询阶段重新计算,将获得的值进行override values

      现在你可以很容易的在measures.startmeasures.end字段上执行average aggregation

      响应中返回了聚合结果并且没有改变 the underlying data(指的是measures.start跟measures.end):

      另外你还可以定义一个runtime field作为查询请求中的一部分来计算出一个值,在相同的query(基于上文中介绍的query)中对这个runtime field进行stats aggregation

      duration这个runtime field不在 index mapping中,当我们仍然可以使用这个字段进行查询和聚合计算。下面的请求将返回经过计算的duration的值并且从用于聚合的文档中基于数值类型的数据执行stats aggregation来计算统计值(即count、min、max、avg、sum):

      尽管 duration这个runtime field只在这次查询请求的上下文中存在,你也可以对该字段进行搜索和聚合。灵活性十分的强大,它可以弥补(rectify)你在index mapping中犯的错误并且在单个查询请求中动态的完成计算。

     

    Override field values at query time

    (8.2)link

      如果您创建的runtime field与mapping已经存在的字段具有相同的名称,则runtime field会将对mapping filed进行投影(shadow)。在查询时,Elasticsearch计算runtime field,根据脚本计算一个值,并将该值作为查询的一部分返回。因为runtime field会对mapping field进行投影(shadow),所以你可以覆盖搜索中返回的值,而不需要修改mapping field。

      例如你在索引my-index-000001中添加了以下的文档:

      你后来意识到HG537PU传感器并没有报告它们的真实电压。索引值应该是报告值的1.7倍。你可以在_search请求的runtime_mappings部分定义一个脚本,来投影(shadow)电压场,并在查询时计算一个新值,而不是重新索引数据。

      如果你想要查询 model number是HG537PU的文档:

      相应中包含了model number是HG537PU的索引值:

      下面的请求中定义了一个runtime field,它的脚本中将估算字段值为HG537PUmodel_number字段,会对于每一个满足条件的voltage的字段值乘以1.7。

      通过在_serach API中使用field参数,你可以检索measures.voltage field,满足查询请求中的文档会根据脚本对该字段值进行计算。

      我们从结果中可以看到,经过计算的measures.voltage的字段值分别是7.146.8。That’s more like it!。runtime field作为查询请求的一部分进行字段值计算,而不修改索引值,索引值仍然在响应中返回:

    Retrieve a runtime field

    (8.2)link

      _search API中使用参数fields来检索runtime fields的字段值。_source中不会展示runtime fields的信息,但是fields可以展示所有字段的信息,即使有些字段不是_source中的一部分。

    Define a runtime field to calculate the day of week

      例如下面的请求中增加了一个名为day_of_week的runtime filed。这个runtime filed中包含了一个根据@timestamp字段计算星期的脚本。请求中定义了"dynamic":"runtime"使得新添加的字段在mapping中将作为runtime fileds。

    Ingest some data

      我们ingest一些样本数据,有两个索引字段@timestampmessage

    Search for the calculated day of week

      下面的请求使用 search API检索day_of_week字段,这个字段在mapping定义为runtime field。这个字段的字段值在查询期间动态的生成,并不需要重新对数据索引,也不需要索引这个字段。这种灵活性使得不需要更改索引字段的情况下改变映射:

      上述请求会为每一个匹配的文档返回一个day_of_week字段。我们可以定义另一个名为client_ip的runtime filed,对message字段进行操作来获取它的字段值来完善接下来的查询。

      使用字段名为client_ip的runtime filed,指定一个字段值来进行查询:

      这次查询的响应中命中2条,day_of_weeksunday)的值会在查询中使用mapping中定义的脚本计算获得。结果中包含了IP address的值为211.11.9.0的文档:

    WARNING:这个功能属于技术预览(technical preview ),可能在未来的发行版中变更或者移除。

      _serach API中的fields参数可以用来检索类型为lookup的runtime fileds,它的字段值可以从其他索引中获取。

      第24行,定义了类型为lookup的runtime field,从目标索引中使用term查询获得的结果作为runtime field的字段值   第25行,ip_location即目标索引   第26行,host字段的字段值将作为term查询条件中的字段值   第27行,ip字段的字段名将作为term查询条件中的字段名   第28行,要求从目标索引ip_location中返回的字段,见fields   上述的查询将从ip_location索引中为返回的搜索命中的每个ip地址返回country和city。

      在返回的结果中,每一个结果中单独的包含了一个从目标索引中获取的数据,这些数据分组展示(JSON中的array)。每一个结果中最多展示一条从目标索引中获取的数据,如果上文中的term查询获取了多个结果,那么就随机返回一条。

    Index a runtime field

    (8.2)link

      Runtime fields在运行时的上下文中定义,你可以在search query 的上下文定义runtime field或者在index mapping中定义一个runtime区域(section)。如果你决定将runtime field写入到索引来获得较好的性能,你只要把完整的runtime filed的定义(包括脚本)都移动到 index mapping的上下文中。Elasticsearch会自动的使用这些索引字段来驱动查询,获得更快的响应时间。这种能力使得只需要你写一次脚本并应用到任何支持runtime field的上文中。

    NOTE:目前不支持索引composite runtime field。

      你可以使用runtime filed来限制Elasticsearch需要计算的字段的数量。将索引字段与runtime filed结合使用可以为你索引的数据以及如何为其他字段定义查询方式提供灵活性。

    IMPORTANT:当你把runtime field写入到索引中,你不能更新其包含的脚本。如果你需要更新脚本,那么使用这个更新后的脚本并且创建一个新的字段。

      比如你的公司想要替换一些旧的压力值。已经连接的传感器只能报告真实读数的一小部分。相较于使用新的传感器来得到新的压力值,你决定基于现有的读数进行计算。基于现有的报告值,你可以为在索引my-index-000001中定义下列的mapping:

      你批量写入了传感器的一些样本数据,包括了从每一个传感器中的voltage的读数:

      在跟一些网页工程师沟通后,你们意识到传感器应该报告2倍于现在的压力值,并且有可能更高。你创建了一个名为voltage_corrected的runtime filed,然后检索当前的voltage的值并且乘以2:

      _search API上使用fields参数来检索计算后的值:

      在审查了传感器数据以及运行了一些测试后,对于报告的传感器数据,multiplier的值应该是4。为了获得更高的性能,你决定把voltage_corrected字段写入到索引中,并且使用新的multiplier参数:

      只要在一个新的名为my-index-000001索引中,把名为voltage_corrected的runtime field中的所有定义直接复制到新索引的mappings中,就是这么简单。你可以额外定义一个参数on_script_error来控制在索引期间当脚本抛出异常时是否要reject整个文档。

      第19行,在索引期间当脚本抛出异常时文档会被reject,将on_script_error的值置为ignore使得将voltage_corrected注册到_ignored的metadata filed中然后继续索引(索引当前文档的其他字段)。

      批量写入传感器的数据到my-index-000001中:

      你现在可以搜索查询中检索计算后的值,并且找到精确数值的文档。下面的范围查询返回voltage_corrected的值大于等于16并且小于等于20的所有文档。这里重申一遍,在_search API上使用fields参数来检索你想要查询的字段:

      响应中返回了满足范围查询的包含voltage_corrected字段的文档,voltage_corrected的值基于脚本中计算出的值:

    Explore your data with runtime fields

    (8.2)link

      假设你从一个数据量很大的日志数据中提取字段。数据的索引非常的耗时,并且使用大量的磁盘空间,并且你想要在不提前给出一个策略(mapping)前就能探索其数据结构(Date structure)。

      已知日志数据中包含了你想要提取的字段(field)。在这个例子中,我们集中关注@timestampmessage字段。通过使用running fields,你可以定义脚本,并在查询期间计算这些字段的值。

    Define indexed fields as a starting point

      你可以先从一个简单的例子开始,将@timestampmessage添加到名为my-index-000001的索引的mapping中,作为indexed filed。To remain flexible,使用wildcard作为message的字段类型:

    Ingest some data

      在添加了用于检索的字段的mapping后,开始将你的日志数据索引到Elasticsearch中。下面的请求使用了bulk API将原始日志数据索引到my-index-000001中。你可以先用一小部分样例数据来体验runtime field而不是使用所有的日志数据。

      The final document is not a valid Apache log format, but we can account for that scenario in our script。

      现在你可以查看Elasticsearch是如何存储你的原始数据的。

      下面的mapping包含了两个字段:@timestampmessage

    Define a runtime field with a grok pattern

      如果你想要检索结果中包含clientip,你可以在mapping中添加这个字段并且作为runtime field。下面的runtime script定义了一个grok pattern,它从单个文本(single text)的文档中提取出结构化的字段。grok pattern类似与正则表达式支持aliased expressions。

      脚本会匹配%{COMMONAPACHELOG} log pattern,它能处理Apache日志结构。如果pattern匹配到(clientip != null),脚本会emit匹配到的IP地址。如果没有匹配到,脚本直接退出而不是报错。

      第8行,这个条件保证pattern没有匹配到也不会报错。

      或者你可以在查询请求时定义相同的runtime field。runtime的定义以及脚本和之前在index mapping中的定义是完全一样。只要将定义拷贝到查询请求中的runtime_mappings块中以及一个匹配runtime field的query。这个query返回的结果跟你在index mapping中定义http.clientip runtime field返回的结果是一样的。前提是你在查询中指定了这个runtime field:

    Define a composite runtime field

      你可以定义一个composite runtime filed从单个脚本中emit多个字段。你可以定义类型化的子字段(typed subfields)集合然后emit多个值。在查询期间,每一个子字段会检索出跟它们名称相关的值。意味着你只需要指定一次grok pattern然后就能返回多个值:

    Search for a specific IP address

      使用http.clientip runtime field,你可以定义单个query用于查询指定的IP地址并返回所有相关的字段。

      上面的API会返回下面的结果。由于http是一个composite runtime field,响应中的fields会包括每一个子字段以及匹配到这个query相关的结果。不用提前构建你的数据结构,你就可以查询并以某种方式展示你的数据来体验以及决定索引哪些字段。

      还记得脚本中的if声明吗?

      如果脚本没有包含这个条件,当某个分片上没有匹配到pattern,query会失败。在包含这个条件后,query会跳过没有匹配到grok pattern的数据。

    Search for documents in a specific range

      你也可以在timestamp字段上执行一个range query。下面的请求会返回大于等于2020-04-30T14:31:27-05:00的文档。

      响应中会包含日志格式不匹配的文档,但是timestamp在定义的范围中。

    Define a runtime field with a dissect pattern

      如果你不需要正则表达式的强大功能,你也可以使用dissect patterns而不是grok patterns。Dissect patterns匹配固定的分隔符,但通常来说比grok快。

      你可以使用dissect解析Apache log并且达到跟grok pattern一样的结果。相较于log pattern,它会包含你想要丢弃的string。特别的注意下你想要丢弃的string,能帮助你成功构建dissect patterns。

      同样的,你可以定义一个dissect pattern来提取HTTP response code

      随后你可以使用http.responses runtime field执行一个query来检索指定的HTTP response。在_search请求中使用fields参数指明想要检索的字段:

      下面的响应包含了HTTP response为304的文档。

    Field data types

    (8.2)link

      每个字段都有一个field data type或者field type。这个类型指明(indicate)了这个字段中包含的数据种类(kind),比如一个string或者boolean值以及预期用途(intended use)。例如,你可以同时将String索引为textkeyword字段。然而text字段会被analyzed用于全文检索,同时keyword用于过滤和排序。

      字段的类型(Field type)根据家族(family)分组。同一个家族的类型有完全一样的查询行为,但是在空间使用(space usage)或者性能属性(performance characteristic)上有差别。

      当前有两个类型家族(type family),keywordtext。其他的type family只有单个字段的类型。例如boolean类型家族由一个字段的类型: boolean组成。

    Common types
    类型描述
    binaryBinary值编码为一个Base64的字符串
    booleantrue以及false
    Keywordskeyword家族,包括kewwordconstant_keyword以及wildcard
    Numbers数值类型,例如longdouble,用来表示为数量
    Dates时间类型,包括datedate_nanos
    alias为现有的字段定义一个别名
    Objects and relational types
    类型描述
    object一个JSON对象
    flattened整个JSON对象作为单个字段值
    nested一个JSON对象,保留了子字段(subfield)间的关系
    join在同一个索引中定义文档间的父子关系
    Structured data types
    类型描述
    Range范围类型,例如long_range, double_range, date_range, and ip_range
    ipIPv4和IPv6地址
    version软件版本。支持[Semantic Versioning precedence rules
    murmur3计算以及存储哈希值
    Aggregate data types
    类型描述
    aggregate_metric_double预先聚合(pre-aggregated)的指标数据
    histogram预先聚合的histogram格式的数值
    Text search tpyes
    类型描述
    text_fieldstext家族,包括textmatch_only_text。分词的,无结构的文本
    annotated-textText containing special markup. Used for identifying named entities
    completion用于auto-complete suggestion
    search_as_you_typetext-like type for as-you-type completion
    token_count文本中token的统计
    Document ranking types
    类型描述
    dense_vectorRecords dense vectors of float values
    rank_featureRecords a numeric feature to boost hits at query time.
    rank_featuresRecords numeric features to boost hits at query time
    Spatial data types
    类型描述
    geo_point经纬度点数据(point)
    geo_shape复杂的形状,例如多边形(polygon)
    point笛卡尔坐标(Arbitrary cartesian points)
    shape笛卡尔几何(Arbitrary cartesian geometries)
    Other types
    类型描述
    percolatorQuery DSL中的query进行索引
    Arrays

      在Elasticsearch中,数组不要求一个专用的字段的数据类型。默认情况下每一个字段可能包含0个或多个值。然而数组中所有的值必须是相同的字段类型。见Arrays

    Multi-fields

      通常来说对同一个字段使用不同方式索引时很有用的。例如,一个字符串字段可以映射为text字段用于全文检索,映射为keyword用于排序或者聚合。你还可以索引一个text字段时,使用standard analyzerenglish analyzer以及french analyzer

      这就是multi-fields的目的。大多数的字段类型通过fields参数来支持multi-fields。

    Aggregate metric field type

    (8.2)link

      metric aggregations存储预先聚合(pre-aggregated)的数值类型的值。aggregate_metric_double类型的字段包含了一个或多个这些指标子字段(metric sub-field):minmaxsumvalue_count

      当你在aggregate_metric_double字段上运行指标聚合时,会使用到对应的指标字段值。例如,在aggregate_metric_double字段执行min aggregation时会返回所有aggregate_metric_double的子字段min中的最小值。

    IMPORTANT:aggregate_metric_double字段中为每一个指标子字段使用doc value存储一个数值类型的字段值。不支持Array。minmaxsum的值是doulbe类型。value_countlong类型的正数。

     

    Parameters for aggregate_metric_double fields
    metrics

      (Required, array of strings)存储指标子字段的数组。每一个数组元素都对应于metric aggregation。合法的数组元素是minmaxsum以及value_count。你必须至少指定一个值。

    default_metric

      (Required, string)默认用于query,script以及聚合的指标子字段,该字段必须是metrics数组中的某个元素。

    time_series_metric(预览功能)

      该字段只用于Elastic内部使用。将字段作为一个Time series metric。这个值是指标类型(metric type)。默认是null(不是一个时间序列指标)。

      对于aggregate_metric_double字段,这个参数只可以是countergauge以及summary。不能对现有的字段更新这个参数。

    Uses

      设计aggregate_metric_double字段是为了用于下面的聚合:

      如果将aggregate_metric_double字段用于其他的聚合操作,那么将会使用default_metric,相当于一个doulbe类型的字段。default_metric同样可以用于Script以及下面的query中:

    Example

      下面的create indexAPI创建了一个名为agg_metricaggregate_metric_double字段。并且max作为default_metric。:

      下面的index API请求在agg_metric字段中添加了预先聚合的数据。

      你可以在agg_metric字段上运行minmaxsumvalue_count以及avg聚合。

      聚合结果基于对应的指标子字段的字段值:

      aggregate_metric_double查询会默认使用default_metric中定义的字段。

      上述查询返回下列的命中结果。default_metric字段的字段值匹配请求中的值(702.30)。

    Alias field type

    (8.2)link

      alias可以给索引中某个字段定义一个别名(alternate)。在search请求以及像 field capabilities API中可以用来替代为目标字段(target filed)。

      第10行,目标字段的路径。注意的是必须是全路径,包括所有的parent objects(比如:object1.object2.field)。

      几乎所有的查询请求都可以使用alias field。特别是可以用于查询、聚合、以及排序字段,同时还有docvalue_fields, stored_fields, suggestions, and highlights。脚本同样支持alias来访问它的字段值。见unsupported APIs了解一些不支持的情况。

      有些search请求以及像 field capabilities API中可以使用field wildcard patterns,这个wildcard patterns可以匹配到具体的filed alias:

    Alias targets

      对于alias的目标字段有一些要求限制:

      另外,alias只能对应一个目标字段。意味着不可能使用一个alias在single clause(一个query属于一个clause)中查询多个目标字段。

      可以通过更新mapping来更改alias指向(refer to)的目标字段。已知的一个限制是如果任何已经存储的percolator query包含了alias,它们仍然指向原先的目标。更多信息见percolator documentation

    Unsupported APIs

      不支持往alias中写入字段值:尝试在索引或者更新alias字段会产生一个错误。同样的,alias不能作为多个字段的copy_to的目标。

      因为alias的名称没有在输入文档中呈现,所以不能通过用于source filtering。例如下面的请求会返回一个空结果:

      目前只有search请求以及像 field capabilities API中可以接受alias。像term vectors就不能使用alias。

      Finally, some queries, such as terms, geo_shape, and more_like_this, allow for fetching query information from an indexed document. Because field aliases aren’t supported when fetching documents, the part of the query that specifies the lookup path cannot refer to a field by its alias。

    Arrays(field Type)

    (8.2)link

      Elasticsearch中没有专门的array data type。默认情况下任意一个字段可以包含零个或者多个值 。然而,在数组中的字段值必须是相同的数据类型。例如:

    NOTE:Arrays of objects对象数组 对象数组可能无法按照你的期望工作:不能独立于数组中的其他对象来查询每个对象。如果你需要能够这样做,那么应该使用嵌套(nested)数据类型,而不是对象(object)数据类型

      当动态的添加一个字段时,数组中的第一个值决定了数组元素的类型。随后所有的值都必须是相同的数据类型或者可以强转(coerce)为相同的数据类型。

      数组中有不同的数据类型是不支持的: [ 10, "some string" ]。

      数组中可以包含null,可以被null_value(如果配置的话)替换或者跳过。空的数组[]被认为是缺失字段(missing field)-某个字段没有字段值。

      不需要在文档中有任何预先配置就可以使用数组,这个开箱支持的功能:

      第4行,tags字段自动添加为字符串字段(string field)。   第5行,lists字段自动添加为object字段。   第17行,第二篇文档没有包含数组,但是会被索引成相同的字段。   第31行,这个query在tags字段中查找elasticsearch,并且匹配到这两篇文档。

    Binary field type

    (8.2)link

      binary类型用于存储使用Base64编码的二进制值,默认情况下,这个字段不会存储并且无法用于搜索:

      第18行,二进制值中不能有换行符\n

    Parameters for binary fields

      binary字段可以有以下参数:

    Boolean field type

    (8.2)link

      boolean字段的值可以是JSON种的truefalse,也可以是可以被解释为true或者false的字符串。

      例如

      第14行,索引了一篇文档,is_published字段的字段值是一个字符串的true,它会被解释为true   第21行,使用JSON种的true查询文档

      terms aggregation中使用10用于key的值,并且"true""false"用于key_as_string的值。在Script中使用Boolean字段时,会返回true false

    Parameters for boolean fields

      boolean字段有以下参数:

    Date field type

    (8.2)link

      JSON没有日期(dates)类型,所以在Elasticsearch中日期字段可以是:

    NOTE:milliseconds-since-the-epoch的值必须是非负的,使用格式化后的值来表示1970前的日期

      源码中,日期会被转化为UTC(如果指定了时区),存储为一个long类型的数值来表示milliseconds-since-the-epoch。

      日期类型的查询会被表示为一个long类型的范围查询,聚合的结果和stored field会根据该字段对应的date format被转回到一个字符串。

    NOTE:日期总是会被表示为字符串,即使在JSON中是long类型

      时间格式data format可以自定义,如果format没有指定,会使用下面默认值:

      上述默认值意味着接受的可选时间戳有milliseconds-since-the-epoch或者strict_date_optional_time支持的格式。

      例如

      第6行将会使用默认的format   第13行使用纯日期   第16行包含时间   第19行使用milliseconds-since-the-epoch   第23行,返回的sort的值将是milliseconds-since-the-epoch

    WARNING:日期将会接受类似{"date": 1618249875.123456}的带小数点的数值,但目前我们会丢失一定的精度,见这个issue

    Multiple date formats

      可以使用||作为分隔符来指定multiple formats,这些format都被依次进行匹配直到找到对应的format。下面第一个format会将milliseconds-since-the-epoch的值转化为一个字符串。

    Parameters for date fields

      下面列出的参数可以用于date字段

    doc_values是否以列式存储在磁盘上,使得可以用于排序、聚合、脚本处理,该值可以是true(默认值)或者false
    format用于对日期进行解析,默认值strict_date_optional_time||epoch_millis
    locale解析日期时使用的区域设置,因为在所有语言中,月份没有相同的名称和/或缩写。默认是 ROOT locale
    ignore_malformed如果是true,格式错误的数字会被忽略。如果是false,格式错误的数字会抛出异常并且整个文档会被丢弃。注意的是如果使用了参数script,当前参数不会被设置。
    index是否需要被快速的搜索到?该值可以是true(默认值)或者false。日期字段date field只有开启doc_values才能进行查询,尽管查询速度较慢
    null_value可以设置一个满足format的值,用来替代空值。默认值是null,意味这是一个缺失值。注意的是如果使用了参数script,当前参数不会被设置。
    on_script_error该值描述了通过参数script定义的脚本在索引期间发生错误后的行为。可以设置为false(默认值),那么整个文档会被reject。或者设置为continue,会通过ignored field来进行索引并继续进行索引。这个参数只有参数script被设置后才能被设置
    script如果设置了该值,将会索引这个脚本生成的值,而不是直接读取source(输入文档中这个字段的字段值)。如果输入的文档中已经设置了这个字段的值,那么这个脚本会被reject并报错。脚本的格式跟runtime equivalent一致,并且应该输出long类型的时间戳。
    store是否要额外存储字段值并且可以被检索,不仅仅存储在_source 字段中,该值可以是true或者false(默认值)
    meta这个字段的Metadata

     

    Epoch seconds

      如果你需要传输seconds-since-the-epoch,那么保证在format中列出epoch_second

      会收到下面的日期数据:

    Date nanoseconds field type

    (8.2)link

      这个时间类型是date数据类型的补充。然而它们之间有一个很重要的不同。现有的date数据类型存储毫秒级分辨率的时间,而date_nanos则是纳秒级分辨率,严格限制了从1970到2262这个时间范围,因为日期仍然以代表自纪元(epoch)以来纳秒数的long类型存储。

      内部处理纳秒时会将其转化为long类型的数值,聚合和存储的结果会被转回成一个字符串,字符串的值区间于Date format。

      可以自定义Date format,如果不指定则会使用默认的format:

      例如:

      第6行,date字段使用默认的date format   第14行,这篇文档使用一个plain Date   第16行,这篇文档包含一个时间   第18行,这个文档使用了milliseconds-since-the-epoch   第22行,注意的是sort的值在返回的结果中使用milliseconds-since-the-epoch   第26行,在脚本中使用了.nano返回纳米级别的时间   第32行,在获取数据时,你可以使用fields parameter来指定Date format。如果不使用strict_date_optional_time_nanos 你会获取一个四舍五入的结果。

      你也可以通过||指定多个Date format。Date nanoseconds field type可以跟Date field type有相同的可用的参数。

    WARNING:Date nanoseconds可以是一个类似{"date": 1618249875.123456}的带有小数点的数字。在某些情况下(#70085),我们会丢失这些日期的精度,因此应该避免使用这种格式

    Limitations

      即使使用了date_nanos字段,也只能在毫秒级分辨率上聚合。这个局限性同样影响transforms

    Dense vector field type

    link

      

    Flattened field type

    (8.2)link

      默认情况下,对象中每一个子字段(sub-field)都单独映射和索引。如果子字段的类型或者名称无法提前知晓,那么它们会被自动映射(mapped dynamically)。

      flattened提供另外一种方法,它将整个对象映射为单个字段。flattened会解析出leaf value并且将它们作为keyword索引到一个字段中。对象的内容随后可以通过query和aggregation查询。

      对于很大的或者有未知数量键的对象,使用flattened就很有用。只要创建一个字段的类型来处理整个JSON对象,有助于防止因太多不同的字段的类型导致mappings explosion

      另外,flattened在搜索功能存在一种折衷。只允许一些基本的查询,不支持数值类型的范围查询以及高亮。更多的一些局限性见Supported operations

    NOTE:flattened不应该用于索引整个文档的内容,因为它会将所有的值作为keyword,不能提供全文检索功能。默认每一个子字段在mapping中有自己的entry,大多数的用例中工作都正常。

      flattened字段可以通过下面的方式创建:

      在索引期间,JSON对象中的每一个leaf value都会创建token。索引为keywords类型,不会分词,也不会为数值或者日期进行特别的处理。

      查询最顶层flattened字段(mapping中定义的那个字段)会搜索所有的leaf values:

      若要查询flattened object中某个key,则通过点路径:

    Supported operations

      由于索引的方式很类似,所以flattened字段跟keyword字段一样有许多相同的mapping和查询功能。

      目前,flattened字段可以用于下面的query类型:

      查询时,不能使用wildcards,比如:{ "term": {"labels.time*": 1541457010}}。注意的事,所有的查询,包括range,都是将值当成string类型。flattened字段不支持高亮。

      可以将flattened字段用于排序,就是类似terms中执行简单keyword风格的聚合。与查询一样,这里没有对数字的特殊支持——JSON 对象中的所有值都被视为keyword。在排序时,这意味着值会按字典顺序进行比较。

      目前不能存储flattened字段。不能在mapping中指定store

    Retrieving flattened fields

      字段值以及固定子字段可以通过fields parameter.content检索。由于flattened将整个对象(以及对象中的子字段)映射为一个字段,响应中的_source包含了未更改的结构。

      获取单个子字段可以在请求中显示的指定。只能对有固定路径的生效,但不能使用wildcards:

      你可以使用Painless script读取flattened字段的子字段的字段值。相比较doc['<field_name>'].value。在你的Script中,使用doc['<field_name>.<sub-field_name>'].value。例如如果你有一个名为label的flattened字段以及一个release的子字段。你的Painless Script中应该是doc['labels.release'].value

      例如,比如说你的mapping中包含两个字段,其中一个是flattened类型:

      索引一些包含你mapping中的字段的文档。labels字段有三个子字段:

      因为labels是一个flattened字段,所以整个对象映射到一个字段中。若要在一个Painless Script中检索子字段,那么使用doc['<field_name>.<sub-field_name>'].value

    Parameters for flattened object fields

      可以使用下面的参数:

    Geopoint field type

    (8.2)link

      geo_point字段可以接受经度纬度对,可以用于:

      有五种方式来指定地理点,如下所示:

      第15行,地理点用一个对象表示,对象中有latlon两个key   第24行,地理点用一个字符串类型的format表示:lat,lon   第30行,地理点用GeoHash表示   第36行,地理点用数组类型的format表示:[lon, lat]   第42行,地理点用 Well-Known Text POINT的format表示:"POINT(lon lat)"   第48行,一个geo-bounding_box query,用来找到在地理位置范围内所有的地理点。

    IMPORTANT:Geopoints expressed as an array or string 注意的使string类型的地理点的经纬度先后顺序为 lat lon,然而数组类型的地理点的经纬度先后顺序为lon``lat

    原先这两种类型的地理点都是lat lon的先后顺序,但是数组类型的地理点为了符合GeoJSON的格式做出了更改

    NOTE:一个point可以用geohash表示,是将纬度和经度的比特交错后,用 base32 编码成字符串。geohash的每一个字符增加额外的 5 个比特精度。因此,哈希越长,其精度就越高。为了索引目的,geohash被转换成纬度-经度对。在这个过程中,只使用前 12 个字符,所以在geohash指定超过 12 个字符并不会增加精度。这 12 个字符提供了 60 个比特,应该能将可能的误差减少到不到 2 厘米。

    Parameters for geo_point fields

    geo_point字段可以有下面的参数:

    Using geopoints in scripts

      在script中访问地理点时,地理点是一个GeoPoint对象,可以分别访问latlon的值。

      出于性能考虑,最好直接访问经纬度值:

    Geoshape field type

    link

    Histogram field type

    (8.2)link

      用来存放预先聚合、数值类型的数据来代表一个直方图的字段。使用下面的成对的两个数组:

      因为value array中的元素对应在count array中相同数组下标的元素,所以这两个数组的长度必须要相同。

    IMPORTANT:每一篇文档中,一个histogram字段只能存储单个valuescount的数组对。不支持nested arrays。 histogram字段不支持排序。

    Parameters
    time_series_metric(预览功能)

      将字段作为一个Time series metric。这个值是指标类型(metric type)。默认是null(不是一个时间序列指标)。

      对于histogram字段,这个参数接收histogram。你不能对现有的字段更新这个参数

    Uses

      使用histogram字段的主要目的是聚合。为了使其更容易被聚合访问,直方图字段数据被存储为二进制文档值并且不被索引。其以字节为单位的大小最多为 13 * numValues,其中 numValues 是提供的数组的长度。

      因为没有索引数据,你可以在下面的聚合和查询中使用histogram字段:

    Building a histogram

      当使用histogram作为聚合的一部分时,聚合结果的准确性取决于如何构建的。percentiles aggregation mode中需要重点关注:

      The histogram field is "algorithm agnostic" and does not store data specific to either T-Digest or HDRHistogram. While this means the field can technically be aggregated with either algorithm, in practice the user should chose one algorithm and index data in that manner (e.g. centroids for T-Digest or intervals for HDRHistogram) to ensure best accuracy.

    Examples

      下面的create index API请求创建了一个新的索引,mapping中有两个字段:

      下面的index API请求为两个直方图:histogram_1histogram_2存储预先聚合的数据。

      第5、14行:Values for each bucket. Values in the array are treated as doubles and must be given in increasing order. For T-Digest histograms this value represents the mean value. In case of HDR histograms this represents the value iterated to.   第6、15行:Count for each bucket. Values in the arrays are treated as integers and must be positive or zero. Negative values will be rejected. The relation between a bucket and a count is given by the position in the array.

    IP field type

    (8.2)link

      ip字段可以用来索引/存储IPV4或者IPV6地址:

    NOTE:你可以使用ip_range data type在单个字段中存储ip ranges。

    Parameters for ip fields

      ip字段接受下列的参数:

    Querying ip fields

      最常用查询IP的方式就是使用 CIDR

      或者

      注意的是,冒号是query_string查询的特殊字符,因此ipv6地址需要转义。最简单的方法是在搜索值两边加双引号:

    Join field type

    (8.2)link

      join数据类型是一个特殊的字段,用来创建同一个索引中文档间的父子关系。relations定义了文档之间的关系,它也定义了父文档的名称以及子文档的名称。

    WARNING:不要使用多级父子关系来模拟关系型数据库模型。每增加一级关系,都会在查询时增加内存和计算的开销。为了获得更好的搜索性能,建议denormalize你的数据。

      通过以下方式定义父子关系:

      第8行,字段的名字   第11行,定义了单个关系,questionanswer的父级(parent)

      若要使用join索引一篇文档,需要在_source中提供关系的名称和父级文档(可选)。例如下面的例子创建了在question的上下文中定义了两个parent文档:

      第6行,这篇文档时question文档。

      当索引父级文档(parent document)时,你可以选择快捷的只指定关系的名称,而不是使用对象进行封装:

      第5行,直接使用关系的名称。

      当索引一篇子文档(child parent)时,必须在_source中添加关系的名称以及父文档的文档ID(_id).

    WARNING:要求将父子关系索引到同一个分片上,因此你必须使用父级文档ID来路由

      例如下面的例子中展示了如何索引两篇child文档:

      第1行,路由值是强制要有的,因为父/子文档必须索引到同一个分片上   第6行,answer是这个文档的join 名称   第7行,这个子文档的父级文档的文档ID

    Parent-join and performance

      在Elasticsearch中,不应将join字段用作关系数据库中的连接操作。为了保持良好的性能,关键是将数据反规范化(de-normalize)成文档。每个join字段、has_childhas_parent查询都会显著增加查询性能的负担,并可能触发global ordinals的构建。

      只有在数据包含一对多关系,其中一个实体数量显著多于另一个实体的情况下,使用join字段才有意义。例如,产品和这些产品的优惠就是这样的用例,如果优惠的数量远多于产品的数量,那么将产品模型化为父文档,将优惠模型化为子文档是有意义的。

    Parent-join restrictions
    Searching with parent-join

      在Elasticsearch中使用父子连接(parent-join)搜索时,该功能创建一个字段来索引文档内关系的名称(例如my_parent, my_child等)。

      对于每个父/子关系,它还会创建一个字段,该字段名称由join字段的名称加上#和关系中父项的名称组成。例如,对于my_parent[my_child, another_child]关系,join字段会创建一个额外的名为my_join_field#my_parent的字段。

      如果文档是子文档(my_child或another_child),此字段包含文档链接到的父_id;如果是父文档(my_parent),则包含文档的_id。搜索包含join字段的索引时,这两个字段总是返回在搜索响应中。

      当查询一个包含join于的索引时,这两个字段总是会返回:

      返回:

      第17行,这个文档是question   第30行,这个文档是question   第45行,这个文档是answer   第46行,子文档链接的父文档ID

    Parent-join queries and aggregations

      查看has_childhas_parent Query、child aggregation以及inner hits了解更多信息。

    &emspjoin字段的字段值可以在聚合根脚本中访问,可以使用parent_id query查询。

      第4行,查询parent_id字段(见has_parent query has_child query)   第12行,在parent_id上聚合(见children aggregation   第21行,在脚本中访问parent_id

    Global ordinals

      join字段使用全局序号(global ordinals)来加速连接操作。每当分片发生变化后,全局序号需要重建。分片中存储的父ID值越多,重建join字段的全局序号所需时间就越长;

      默认情况下,全局序号会积极(eagerly)构建:如果索引发生变化,join字段的全局序号会作为刷新的一部分被重建。这可能会显著增加刷新时间。然而,大多数情况下这是正确的权衡,否则在首次使用父子连接查询或聚合时,全局序号会被重建,这可能会为用户引入显著的延迟峰值。

      join字段使用不频繁且频繁写入时,可能有必要禁用积极加载。

      可以通过下面的方式查看每一个parent relation对应的全局序号的内存使用量:

    Multiple children per parent

      也可以为单个parent定义多个child:

      第8行,questionanswercomment的parent

    Multiple levels of parent join

    WARNING:不要使用多级父子关系来模拟关系型数据库模型。每增加一级关系,都会在查询时增加内存和计算的开销。为了获得更好的搜索性能,建议denormalize你的数据。

      Multiple levels of parent/child:

      第7行,questionanswercomment的parent   第8行,voteanswer的parent

      上面的mapping意思就是:

      索引一个grandchild文档需要跟grand-parent一样的路由值(the greater parent of the lineage)

      第1行,必须跟parent、grand-parent在相同的分片上   第6行,这个文档的父级文档的文档ID(必须指向answer文档)

    Keyword type family

    (8.2)link

      keyword家族包含下面的字段类型:

      keyword常用于sortingaggregation以及term-level queries,例如term

    TIP:若要全文检索,请不要使用keyword。而是使用text类型。

    Keyword field type

      下面是keyword字段的mapping:

    TIP:Mapping numeric identifiers 不是所有的数值类型的数据都应该映射为一个numeric数据类型。Elasticsearch会为数值类型的字段,比如integerlong针对range查询优化。然而,keyword字段更适合于term以及其他term-level Query。 比如一些标识符,ISBN或者产品ID,很少用于range query,但是常用于term-level query。 如果有以下的场景,可以考虑将数值类型的标识符映射为keyword

    • 你不打算将标识符类型的数据用于range query

    • 快速的检索对你来说很重要的话,那么相较于数值类型的字段,在keyword字段上进行term query通常更快。

    如果你不确定该使用哪种类型,那么可以通过multi-field来同时使用keyword跟数值类型的字段。

    Parameters for basic keyword fields

      keyword字段可以使用以下的参数:

    Constant keyword field type

      Constant keyword是keyword的一种特例用于所有的文档中会索引相同的值。

      constant_keyword支持跟keyword有相同的查询跟聚合,但是会利用所有文档拥有相同的值这个特点来提高查询效率。

      同时还允许文档中不包含这个字段或者这个字段的字段值跟mapping中的值相同。下面两个索引请求是等价的:

      然而如果文档中该字段的字段值跟mapping中的不一致是不允许。

      如果mapping中没有配置value,那么该字段会基于第一篇文档中该字段的值自动的配置。注意的是这意味着如果第一篇文档的值是有问题的,会导致其他的合法的文档被reject。

      在提供value之前(通过mapping或者第一篇文档),任何对该字段的查询都不会匹配任何文档。包括exists query。

      该字段的value在设置后就不能变更。

    Parameters for constant keyword fields

      该类型可以有以下的参数:

    Wildcard field type

      wildcard字段是一种特殊的keyword类型,用于无结构的机器自动生成的内容,并且你计划使用wildcardregexp这类Query进行查询。wildcard类型对于large value和high cardinality有专门的优化。

    Mapping unstructured content   你可以将一个无结构的内容使用text或者keyword家族字段。使用哪一种取决于内容的特点以及你如何查询这个字段 如果有以下的场景,则使用text字段:

    • 内容是可读的(human-readable),比如邮件正文或者产品描述

    • 你想要使用独立的单词或者短语进行查询,例如the brown fox jumped,使用full text queries,Elasticsearch会对text字段进行分词并且返回相关性最高的结果。

    如果有以下的场景,则使用keyword家族字段:

    • 内容是机器自动生成的,比如日志消息或者HTTP请求信息

    • 你想要使用精确完整的值进行查询,比如org.foo.bar,或者使用部分字符序列,比如使用term-level queires查询org.foo.*

    Choosing a keyword family field type 如果你选择了一个keyword家族字段,使用keyword还是wildcard取决于字段值的长度和字段值的种类(cardinality)。如果你经常使用wildcard或者regexp查询并且满足下面类别的一种,则使用wildcard

    • 字段值种类包含超过one million个并且经常使用通配符在关键字开头的查询,例如*foo*baz

    • 字段值大小超过32KB并且经常使用wildcard pattern查询

    否则就使用keyword类型,这样查询速度更快,索引更快并且占用更少的存储开销。对于深入的比较以及讨论,见related blog post。

    Switching from a text field to a keyword field 如果你之前使用text字段处理无结构的机器自动生成的内容。你可以reindex to update the mappingkeyword或者wildcard字段中。我们还建议,将你们应用或者工作流中在这个字段上的full text queries替换为等价的term-level queries

      在内部,通配符字段使用 ngram 对整个字段值进行索引,并存储完整字符串。这个索引被用作rough filter,以减少随后通过检索和检查完整值来检查的值数量。这个字段特别适合用于在日志行上运行类似 grep 的查询。存储成本通常低于keyword字段,但对完整词项的精确匹配的搜索速度较慢。如果字段值共享许多前缀,如同一个网站的 URL,wildcard字段的存储成本可能高于等效的keyword字段。

      你可以通过下面的方式索引以及查询一个wildcard字段:

    Parameters for wildcard fields

      wildcard可以使用下面的参数:

    Limitations

    Nested field type

    (8.2)link

      nested类型是object类型的特殊版本,它允许将对象数组以一种可以独立查询每个对象的方式进行索引。

    TIP:当你需要处理包含大量任意键的键值对时,你可能会考虑将每一对键值作为一个独立的嵌套文档进行建模,其中每个文档包含两个字段:一个用于键(key),另一个用于值(value)。

    • 例如产品A:color: red size: medium 产品B: color: blueweight: 1kg。希望通过color: red size: medium这两个条件才会找到产品A。

    • 若考虑使用flattened数据类型,则将整个对象作为一个字段的字段值,允许对整个对象的内容做简单的搜索。Nested document和query通常开销昂贵,所以在这种例子中使用flattened数据类型是个不错的选择。

    How arrays of objects are flattened

      Elasticsearch没有inner object的概念。因此,它是将其平铺为的字段名字段值列表。例如索引以下的文档:

      第4行,user字段会动态的添加为object类型。

      上面的文档在内部被转化为以下的内容:

      user.firstuser.last平铺为多值的字段,同时alicewhite的关联信息也丢失了(关联信息指的是:它们两个属于同一个对象)。下面alice AND smith的这种查询会错误的匹配到这篇文档:

    Using nested fields for arrays of objects

      如果你需要索引对象数组并且还要维护数组中每一个对象相对独立,那么使用nested数据类型而不是object数据类型。

      在内部,nested object会将数组中每一个对象分别索引到一个hidden document(即在Lucene层每一个对象对应一个文档),意思是每一个nested object可以使用nested query独立于其他对象进行查询

      第6行,user字段使用nested而不是object   第36行,因为AliceSmith不是同一个nested object,所以这个query不会匹配到文档   第53行,因为AliceWhite是同一个nested object,所以这个query会匹配到文档   第57行,inner_hits允许我们高亮匹配到的文档。

    Interacting with nested documents

      使用nested query查询

      nested聚合以及reverse_nested aggregations.

      nested sorting排序

      nested inner hits检索以及高亮

    IMPORTANT:因为nested documents索引为单独的文档(在lucene中是单独的文档,数组中的每一个对象都是lucene中的一篇文档,并且包含父文档的父文档ID,以及在主文档中的位置信息)。因此它们只能通过nested query, nested/reverse_nested aggregation,或者nested inner hits访问。

    例如,如果nested document内的字符串字段的index_options设置为offsets以便在高亮显示时使用倒排信息,那么在主要高亮(main highlighting)显示阶段这些偏移量将不可用。相反,需要通过nested inner hits来执行高亮显示。在通过docvalue_fieldsstored_fields进行搜索时加载字段时,同样的考虑也适用。

    Parameters for nested fields

      可以有下面的参数:

      这两个参数为true的好处相同点就是可以通过普通query就可以进行查询,而不需要专用的nested query

    Numeric field types

    (8.2)link

      支持下列的数值类型:

      下面是在mapping中配置数值字段的例子:

    NOTE:double, floathalf_float类型中-0.0+0.0是不一样的值。因此,term query -0.0不会匹配到+0.0,反之亦然。对于range query也是一样的:如果上界是-0.0那么+0.0不会匹配,同样的,如果下界是+0.0那么-0.0不会匹配到。

    Which type should I use?

      对于整数类型(byte, short, integer 以及long),对于你的用例,你应该选择最小类型(smallest Type)。这将让索引和搜索更加高效。注意的是尽管存储时会基于实际的值进行优化,因此选择一种类型而不是另一种类型对存储需求没有影响。

      对于浮点型,通常使用scaling factor将浮点数据存储为整数会更有效率,这正是scaled_float类型在底层所做的。例如,一个price字段可以使用scaling factor为100的scaled_float来存储。API中像是将字段值作为一个double存储,但在Elasticsearch内部以"分"为单位存储,price*100,就可以将double变成一个整数。相较于浮点数,整数更易于压缩来节省磁盘开销。scaled_float属于精度跟磁盘开销之间的折中方式。例如,假设你在跟踪 CPU利用率,这是一个介于 0 和 1 之间的数字。CPU 利用率是 12.7% 还是 13% 通常并不重要,所以你可以使用一个 scaling_factor 为 100 的 scaled_float,以将 CPU 利用率四舍五入到最接近的百分比,以节省空间。(如果字段值是固定小数位,用scaled_float是个不错的选择)

      如果scaled_float不适合你的使用场景,你应该在浮点型之间选择一个够用且最小的类型:doublefloathalf_float。这里提供了一个类型之间差异的表,帮助你选择适当的浮点型类型。

    TypeMinimum valueMaximum valueSignificant bits / digitsExample precision loss
    double2^-1074(2-2^-52)·2^102353 / 15.951.23456789123456781.234567891234568
    float2^-149(2-2^-23)·2^12724 / 7.221.234567891.2345679
    half_float2^-246550411 / 3.311.23451.234375

    TIP:Mapping numeric identifiers 不是所有的数值类型的数据都应该映射为一个numeric数据类型。Elasticsearch会为数值类型的字段,比如integerlong针对range查询优化。然而,keyword字段更适合于term以及其他term-level Query。 比如一些标识符,ISBN或者产品ID,很少用于range query,但是常用于term-level query。 如果有以下的场景,可以考虑将数值类型的标识符映射为keyword

    • 你不打算将标识符类型的数据用于range query

    • 快速的检索对你来说很重要的话,那么相较于数值类型的字段,在keyword字段上进行term query通常更快。

    如果你不确定该使用哪种类型,那么可以通过multi-field来同时使用keyword跟数值类型的字段。

    Parameters for numeric fields

      数值类型的字段可以使用以下的参数:

    Parameters for scaled_float

      scaled_float可以使用下面额外的参数

    Object field type

    (8.2)link

      事实上JSON documents是有层次的。文档中可能包含inner objects,并且它们自身还包含inner objects:

      第2行,文档外部同样是JSON object   第4行,包含一个名为manager的inner object   第6行,manager接着还包含一个名为name的inner object

      内部的实现是一个简单的,扁平的key-value链,如下所示:

      上述文档对应的显示的mapping如下所示:

      第4行,mapping中最顶层的properties的定义   第8行,manager字段是一个inner object   第11行,manager.name字段是manager字段中的inner object

      你不需要显示的指定object指定type

    Parameters for object fields

      下面的参数可以应用于object字段

    IMPORTANT:如果不是要索引一个object,而是object数组,请先阅读Nested

    Percolator field type

    link

    Point field type

    link

    Range field types

    link

    Rank features field type

    link

    Rank feature field type

    link

    Search-as-you-type field type

    link

      

    Shape field type

    link

      

    Text type family

    (8.2)link

      text family包含的字段类型(field type)如下所示:

    Text field type

      索引full-text values的字段,例如email的body或者一个产品的描述。字段值会被分词,字段值会被analyzer分词,将一个string值转化为一个一个独立的term,并将这些term进行索引。analysis process允许Elasticsearch在每一个full text filed中查询独立的词(individual Word)。text字段不用于排序或者很少用于聚合(尽管significant text aggregation是一个明显的例外)。

      text字段最适合用于无结构的并且是human-readable的内容。如果你需要索引无结构的machine-generated的内容,见Mapping unstructured content

      如果你需要索引例如email地址,hostnames,状态码,或者tags,你应该选择keyword字段。

      下面是text字段的mapping例子:

    Use a field as both text and keyword

      有时候同一个字段需要同时有full text(text)和keyword(keyword)。一个用来全文检索,另一个用于聚合和排序。可以通过 multi-fields实现。

    Parameters for text fields

      text字段接受下面的参数

    analyzer分词器analyzery应该同时用于index-time和search-time(除非被search_analyzer重写(override)),默认是index analyzer或者standard analyzer.
    eager_global_ordinals是否在refresh尽快的载入global ordinals?默认是false。如果经常用于terms aggregation,开启这个参数是很有必要的
    fielddata这个字段是否用于排序、聚合、或在script中使用?默认是false
    fielddata_frequency_filter(Expert Setting)在开启fielddata后,将哪些值载入到内存中,默认值是false
    fieldsMulti-fields允许同一个将string value基于不同的目的索引用多种方式进行索引。比如用于查询或者用于排序聚合,或者使用不同的分词器对string value进行分词
    index这个字段是否可以被搜索?默认是true
    index_options哪些信息需要被存储到索引中用于查询和高亮,默认是positions
    index_prefixes开启这个参数后,term的2到5个前缀字符会被索引到额外的字段(separate filed)。这使得前缀搜索更高效,代价就是索引大小会增加
    index_phrases开启这个参数后,2个term组成的字段值会被索引到额外的字段(separate filed)中。这使得exact phrase(no slop) 查询可以更高效,代价就是索引大小会增加。注意的是只有移除了停用词后才能达到最佳性能,因为包含了停用词的短语将不会使用subsidiary field并且会回滚到标准的短语查询。默认是false
    norms执行打分的查询时是否要考虑字段值的长度
    position_increment_gapThe number of fake term position which should be inserted between each element of an array of strings. Defaults to the position_increment_gap configured on the analyzer which defaults to 100. 100 was chosen because it prevents phrase queries with reasonably large slops (less than 100) from matching terms across field values.
    store是否存储字段值并且可以通过_source字段查询。默认是false
    search_analyzer是否在search-time时使用上文中第一个参数中指定的分词器(默认值)?
    search_quote_analyzer当遇到短语时,是否在search-time使用上文中第一个参数中指定的分词。默认值是上文中search_analyzer中指定的分词器
    similarity使用哪种打分算法?默认值是BM25
    term_vector是否为这个字段存储term vectors?默认值是false
    meta这个字段的Metadata
    fielddata mapping parameter

      text字段默认是可以用于搜索的,但是默认不能用于聚合、排序、或者scripting。如果你想要排序,聚合,或者从script中访问text字段,你将会遇到这个异常:Fielddata is disabled on text fields by default。 设置your_field_namefielddata=true,通过uninverting倒排索引(inverted index)将fielddata导入到内存中。注意的是这将会使用大量的内存。

      Field data是在排序、聚合、或者scripting中访问fulll text field的分词后的token的唯一方法。例如,比如说New York这个full text field将会分词为newyork两个token,对这些token进行聚合需要field data。

    Before enabling fielddata

      在text field上开启fielddata通常是没有意义的。Field data使用field data cache并存储在堆上,因为计算开销很大。计算field data会导致latency spikes并且增加堆内存的使用,这也是导致集群性能问题的原因之一。

      大多数的用户会使用multi-field mappings来同时获得text字段用于全文检索以及不分词的keyword字段用于聚合,如下所示:

      第5行,my_field字段用于查询   第8行,my_field.keyword用于聚合、排序或者在script中使用

    Enabling fielddata on text fields

      你可以使用update mapping API对现有的text字段开启fielddata,如下所示:

      第4行,my_field指定的mapping应该由这个字段现有的mapping加上fielddata参数组成。

    fielddata_frequency_filter mapping parameter

      FieldData filtering可以用于减少载入到内存的term的数量,因此能降低内存使用量。可以通过frequency来过滤term:

      frequency filter能让你只将frequency在minmax之间的term载入到内存,minmax可以是一个确切的数值(absolute number, 数值大于1)或者是一个百分值(比如0.01就是1%并且1.0就是100%)。frequency在每个段中进行计算。百分值基于一个段中拥有这个字段的文档数量相对于所有文档的数量。

      可以通过指定min_segment_size,即段中包含的文档数量最小值来排除一些小段:

    Match-only text field type

      text类型的一个变体是match_only_text。它是打分和与位置相关的query的一种折中类型。这个类型的字段跟只索引文档号(index_options: docs)的text字段有相同存储数据效率并且关闭了norms(norms: false)。在这个字段上执行term query跟在text类型的字段上更快,至少也是相等。然而如果在match_only_text上执行需要位置信息的query,例如match_phrase,那性能会降低,因为需要从_source中验证短语是否匹配。所有的query返回固定的打分值:1.0。

      不能配置分词器:文本总是用默认的分词器分词(默认是standard)。

      span queries无法在这个类型的字段上使用,可以使用interval queries,或者你真的需要使用span queries,那么使用text类型。

      除此之外,match_only_text支持与文本(text)相同的查询。就像text一样,它不支持排序,并且对聚合的支持有限。

    Parameters for match-only text fields

      match_only_text接受下面的参数:

    Token count field type

    (8.2)link

      token_count字段是一个integer类型的字段,它用来接收字符串的值,然后分词最后记录字符串中token的数量。

      例如:

      第5行,名为name的字段是一个text字段,使用了默认的standard分词器。   第7行,name.length字段是一个multi-fieldtoken_count字段,它会记录name字段中token的数量,   第28行,这个query只会匹配包含Rachel Alice Williams的文档,因为它会被分为三个token。

    Parameters for token_count fields

      token_count字段接收下列的参数:

    Unsigned long field type

    (8.2)link

      Unsigned long是一个数值类型的字段,代表一个无符号的64bit的整数,最小值为0并且最大值为2^64 - 1([0, 18446744073709551615])

      unsigned long可以用数值或者字符串的格式进行索引,代表了[0, 18446744073709551615]范围的整数。不能有小数部分。

      Term query可以使用数值或者字符串格式。

      range query可以包含带有小数的值。在这种情况下,Elasticsearch会将它们转化成整数:gtegt会转化成最近的向上的整数(inclusive);ltlte会转化成最近的向下的整数(inclusive)。

      建议使用字符串格式的值,就不会再解析时丢失精度。

    Sort values

      对于使用unsigned_long字段排序的query,对于某个文档,如果字段值在long的范围内,则返回long类型的排序值,如果字段值超过了这个范围,则返回BigInteger

    NOTE:客户端需要能够正确的处理JSON种的big integer

    Stored fields

      如果unsigned_long被设置为stored,那么会以字符串存储,并且返回的结果也是字符串。

    Aggregation

      对于term aggregattion,跟sort values一样,会使用Long或者BigInteger。对于其他聚合,会被转化成double类型。

    Script values

      默认情况下,脚本中unsigned_long字段返回了一个signed long,意味着大于Long.MAX_VALUE的值会显示为负数。你可以使用Long.compareUnsigned(long, long), Long.divideUnsigned(long, long) 以及 Long.remainderUnsigned(long, long)来正确的处理这些值。

      比如说,下面的脚本返回一个counter/10的值:

      或者在脚本中你可以使用field API将unsigned long类型视为BigInteger。下面的脚本中将my_counter视为BigInteger,并且默认值为BigInteger.ZERO

      如果脚本中需要返回float或者double类型,你可以进一步将BigInteger转化为一个double或者float:

    Queries with mixed numeric types

      支持包含unsigned_long在内的混合数值类型的搜索查询,但排序查询除外。因此,在两个索引中进行排序查询时,如果相同的字段名在一个索引中是unsigned_long类型,在另一个索引中是long类型,这将无法产生正确的结果,应该避免这种情况。如果确实需要这种排序,可以使用基于脚本的排序。

      支持包含unsigned_long在内的多种数值类型的聚合操作。在这种情况下,值会被转换为double类型。

    Version field type

    (8.2)link

      version字段是keyword字段的特例类型,用于处理软件版本号以及支持特殊的优先级规则(specialized precedence rule)。优先级遵循Semantic Versioning。例如按照主要(major)、次要(minor)、补丁(patch)的数值排序(比如 "2.1.0" < 2.4.1"" < "2.11.2")。预发布版本排在正式版之前(比如"1.0.0-alpha" < 1.0.0"")。

      你可以按照下面的内容索引一个version字段:

      该字段提供了跟常规的keyword字段相同的搜索能力。比如可以使用match或者term query来精确匹配并且支持前缀(prefix)和通配符(wildcard)查询。最主要的好处就是range query遵循Semver排序,所以"1.0.0"到"1.5.0"的range查询会包含"1.2.3",但是不会包含"1.11.2"。注意的是如果使用keyword存储版本号则排序是不同的,因为排序规则是字典序。

      软件版本号应该遵循[Semantic Versioning rules]的策略和优先级规则,不过有一个显著的例外就是允许主要的版本标识多于或少于三个(例如"1.2"或"1.2.3.4"是有效的(valid)版本号,但没有严格遵循Semver的规则)不满足Semver规则的版本号(例如,“1.2.alpha.4”)仍然会被索引并且可以精确匹配。但是这些版本号会按照字典序排序,并且排在有效版本号之后。空的version字段值被认为是无效的,并且排在所有有效版本号之后,其他无效版本号之前。

    Parameters for version fields

    Metadata fields

    (8.2)link

      每一篇文档都有关联的metadata,例如_index_id metadata field。这些metadata fields的行为可以在创建mapping时自定义。

    Identity metadata fields

      _index:文档所属索引。

      _id:文档的ID。

    Document source metadata fields

      _source:代表文档内容的原始JSON。

      _size_srouce字段的大小(单位:字节),由mapper-size插件提供。

    Doc count metadata field

      _doc_count:当文档作为pre-aggregation 数据时的一个自定义的用于存储文档计数的字段。

    Indexing metadata fields

      _field_names:文档中所有字段值不为null的字段。

      _ignored:因为ignore_malformed,在索引期间文档中所有被ignore的字段、

    Routing metadata field

      _routing:自定义的routing value用于将一篇文档路由到指定的分片上。

    Other metadata field

      _meta:应用指定的metadata。

      _tier:文档所属的索引所在的data tier

    _doc_count field

    (8.2)link

      Bucket aggregation总是返回一个名为doc_count的字段,它表示每一个bucket中参与集合的文档数量。计算doc_count的值是很简单的。在每一个bucket中,每收集到一篇文档,doc_count的值就加一。

      在独立的文档中进行聚合计算时这种简单的方式是很高效的。但是统计那些存储pre-aggregation的文档数量就会丢失精度(比如说histogram或者aggregate_metric_double),因为一个summary field中代表了多篇文档(见Histogram fields)。

      为了允许纠正统计pre-aggregation数据时的文档数量。可以使用一种名为_doc_count的metadata field类型。_doc_count必须总是用一个正整数来表示单个summary field对应的文档数量。

      当文档中添加了_doc_count,所有的bucket aggregation必须遵照这个_doc_count的值,按照这个值来累加bucket中doc_count的值。如果一篇文档中不包含任何_doc_count,默认存在一个_doc_count = 1的信息。

    IMPORTANT:

    • _doc_count字段的字段值在一篇文档中只能是一个正整数,Nested arrays是不允许的如果一篇文档中不包含_doc_count

    • 按照_doc_count = 1这种默认行为进行聚合统计

    Example

      下面的create index API使用下面的mapping创建了一个新的索引:

      下面的index API请求存储2个histogram的pre-aggregated data:histogram_1and histogram_2

      第18行,_doc_count必须是一个正整数表示每一个histogram中的文档数量。

      如果我们在my_index上运行下面的terms aggregation

      我们会得到下面的response:

    _field_names field

    (8.2)link

      _field_names字段用来对一篇文档中每一个字段值不是null的字段的字段名进行索引。exists query使用这个字段来查找具有或不具有特定字段的任何非空值的文档。

      现在_field_names只会对有doc_values以及关闭norms的字段的字段名进行索引。对于有些只开启doc_values或者只开启norms的字段也可以使用exists query,但是不是通过_field_names字段实现的。

    Disabling _field_names

      不允许关闭_field_names。现在默认开启_field_names是因为它不再有曾经的索引开销。

    NOTE:关闭_field_names的功能已经被移除了。在新的索引上使用它会抛出一个错误。在8.0前的索引上关闭_field_names仍然是允许的,但是会报告出一个deprecation的警告。

    _ignored field

    (8.2)link

      _ignored field 用来索引并存储在索引期间被忽略的文档的所有字段的名称。例如字段值是格式错误的并且开启了ignore_malformed或者keyword字段值超过了ignore_above中的设置。

      这个字段可以使用 term, terms, exists进行查询。

      下面的例子描述了匹配的文档中包含一个或者多个被忽略的字段。

      下面的例子描述了将匹配在索引期间,@timestamp字段被忽略的文档。

    _id field

    (8.2)link

      每个文档都有一个_id用于唯一识别(unique identification)。该值会被索引使得可以通过GET API或者ids query用于查找。这个_id要么在索引期间被赋值(assigned)、要么通过Elasticsearch生成一个唯一的值。这个字段在mappings中是不可以配置的。

      _id字段的值可以在termtermsmatchquery_string查询中可用(accessible)。

      第16行即根据_id进行查询,见ids query

      _id字段在聚合(aggregation)、排序、脚本中是被限制使用的。万一(in case)需要使用_id字段来进行排序或者聚合,建议将_id字段的值复制(duplicate)到其他字段并且这个字段开启doc_valies

    _id字段的值的大小被限制为512个字节并且larger values会被reject。

    _index field

    (8.2)link

      当在多个索引上执行查询时,有时候希望增加一个关联相关索引的子query(query clause)。_index字段允许你只在相关的索引上匹配文档。_index的值可以用于某些查询、聚合或者排序、Script:

      第15行,根据_index的字段值查询   第21行,在_index上执行聚合   第28行,基于_index字段排序   第37行,在脚本中访问_index的值

      _index field exposed virtually,它不会作为一个真实的字段添加到Lucene的索引中。这意味着你可以在termterms查询中使用_index 字段(或任何被重写为 term 查询的查询,如 matchquery_stringsimple_query_string 查询),以及 prefixwildcard 查询。但是,它不支持regexpfuzzy 查询。

      _index 字段的查询除了接受具体的索引名称外,还接受索引别名。

    NOTE:在指定远程索引名称(如 cluster_1:index_3)时,查询必须包含分隔符 :。例如,对 cluster_*:index_3wildcard 查询将匹配远程索引中的文档。然而,对 cluster*index_1 的查询只会匹配本地索引,因为没有分隔符。这种行为与远程索引名称的通常解析规则一致。

    _meta field

    (8.2)link

      一种可以使用自定义元数据(meta data)跟mapping进行关联的类型。Elasticsearch完全不会去使用它,可以用来存储指定应用(application-specific)的元数据,比如说这篇文档所属类别:

      第4行,可以通过 GET mapping API检索_meta的信息

      _meta字段可以通过update mapping API对已存在的类型进行变更。

    _routing field

    (8.2)link

      使用下面的公式让索引中的一篇文档被路由到指定的分片中:

      num_routing_shards即索引设置中的index.number_of_routing_shards

      num_primary_shards即索引设置中的index.number_of_shards

      _routing的默认值是文档的_id。自定义的路由模板(routing pattern)可以通过对某个文档指定一个自定义的routing值实现。例如:

      第1行中,这篇文档使用user1作为路由值替代ID。   第6行中,当gettingdeletingupdating这篇文档时需要提供路由值。

      _routing的值可以在查询中使用(accessible):

      第5行中,在_routing字段上进行查询,见ids query

    Data streams不支持自定义routing除非创建时,在模板中开启allow_custom_routing。

    Searching with custom routing

      自定义的路由能减少(reduce)查询的压力。不需要将搜索请求分散(fan out)到索引的所有分片,而是只发送到匹配特定路由值的分片。

      第1行中,这次查询只会在路由值user1、user2相关的分片中执行。

    Making a routing value required

      当使用自定义的路由时,无论是Indexinggettingdeletingupdating一篇文档时都是需要提供路由值的。

      忘掉路由值能将一篇文档索引到一个或多个分片上。作为一个安全措施(as a safeguard),_routing字段可以被配置使得在所有的CRUD操作时都需要routing值。

      第5行中,所有文档的操作都需要提供路由值。   第10行中,这个请求会抛出routing_missing_exception的异常。

    Routing to an index partition

      使用自定义的路由值来配置索引时,可以路由到一个分片集合中而不是单个分片上。这可以降低集群不平衡导致关闭的风险,同时能降低查询压力。

      在索引创建期间可以通过索引层的设置index.routing_partition_size来实现。随着分区(partition)的大小的增长,数据将分布的越均匀(evenly),那么每次查询都需要搜索更多的分片。

      当提供了这个设置后,计算分片的公式将变成:

      也就是说(that is)routing字段将用来计算出分片集合,然后_id用来从分片集合中选出一个分片。

      要开启这个功能,index.routing_partition_size的值要大于1并且小于index.number_of_shards

      一旦开启这个功能,被分区(partitioned)的索引将有下列的限制:

    _source field

    (8.2)link

      _source字段包含了在索引期间传给Elasticsearch的原始的JSON格式的文档内容。_source自身不会被索引(因此这个字段没法用于搜索),又因为它被存储了,所以可以通过fetch requests例如get或者search方式来获得。

    Disabling the _source field

      _source字段会带来索引的存储成本,基于这个原因可以通过下面的方式关闭:

    WARNING:Think before disabling the _source field   用户经常不考虑关闭_source字段的后果然后会后悔这么做。如果_source字段不可见那么下面的功能就没法支持:

    • updateupdate_by_query以及reindex这些API

    • On the fly highlighting

    • 从一个索引重新索引到另一个的能力,或者是修改mapping、分词器或者升级一个索引到一个新的主要版本

    • 索引期间通过观察原始文档调试查询或者聚合的能力

    • 在未来的版本中可能可以自动修复受损(corruption)索引的能力

    TIP:如果需要关心磁盘空间,可以提高 compression level而不是关闭_source

    Including / Excluding fields from _source

      这是expert-only的功能使得在_source的内容在索引之后、存储之前进行字段的剪枝。

    WARNING:从_source中移除一些字段跟关闭_source有着类似的负面问题(downside),特别是你不能从一个Elasticsearch索引重新索引到另一个。可以考虑使用source filtering 来替代这种方式。

      参数includes/excludes(支持wildcards)可以按照以下方式使用:

      第21、25、27、28行,_source 字段存储之前会移除这几个字段   第37行,我们仍然可以通过这个字段进行检索,尽管它没有被存储

    _tier field

    (8.2)link

      在多个索引上执行查询时,有时候希望在包含指定数据层(data tie)(data_hot, data_warm, data_cold or data_frozen)的索引上查询。_tier字段用于匹配索引设置tier_preference

      第15行,根据_tier的值查询

      通常,查询会使用 terms 查询来列出感兴趣的层级,但你可以在任何被重写为 term 查询的查询中使用_tier 字段,比如 matchquery_stringtermtermssimple_query_string 查询,以及 prefixwildcard 查询。然而,它不支持 regexpfuzzy查询。

      索引的 tier_preference 设置是一个逗号分隔的层级名称列表,按优先顺序排列,即首选托管索引的层级排在最前,其后可能有许多备选选项。查询匹配只考虑第一优先级(列表的第一个值)。

    Mapping parameters

    (8.2)link

      这一章节提供了不同的mapping 参数(mapping parameters)的详细的介绍,mapping参数用于filed mappings

      下面的mapping参数对于某些或者所有的字段的数据类型是通用的:

    analyzer(mapping parameter)

    (8.2)link

    IMPORTANT:只有text类型支持analyzer参数。

      analyzer参数用来指定分词器analyzer 并且用于在索引和查询text字段时进行文本分词text analysis

      除非用mapping参数search_analyzer进行覆盖,分词器将同时用于index and search analysis,见Specify an analyzer

    TIP:建议在生产中使用前先试用下分词器,见Test an analyzer

    TIP:analyzer参数不能通过update mapping API对已存在的字段进行变更。

    search_quote_analyzer

      search_quote_analyzer允许你指定一个分词器用于match_phrase和query_string这类phrase query,处理这类query并且不使用停用词时特别有用。

      若要为phrase query不启动停用词可以利用三个分词器:

    1. 使用设置analyzer用于索引所有的term,包括停用词

    2. 使用设置search_analyzer用于non-phrase query,它将移除停用词

    3. 使用设置search_quote_analyzer用于phrase query,它将不会移除停用词

    TIP:可以通过update mapping API对现有的字段更新search_quote_analyzer设置。

      第1行,my_analyzer对所有的字符串进行分词,包括停用词   第2行,my_stop_analyzer会移除停用词   第3行,analyzer会在索引期间使用my_analyzer这个分词器   第4行,search_analyzer会为non-phrase query使用my_stop_analyzer这个分词器并且移除停用词   第5行,search_quote_analyzer会使用my_analyzer分词器并且确保使用phrase query时停用词不会被移除   第6行,由于query语句作为一个phrase query使用引号包裹,因此触发search_quote_analyzer并且保证停用词不会从这个query中移除。my_analyzer分词器会返回下面的token: [the, quick, brown, fox] 用来匹配文档。同时term query会使用my_stop_analyzer分词器并且过滤掉停用词。因此查询语句quick brown fox或者A quick brown fox都会返回两篇文档(the是停用词),因为这两篇文档都包含下面的token: [quick, brown, fox]。没有search_quote_analyzer的话,就无法为phrase query执行精确匹配(exactly match),是因为停用词会被移除,使得两篇文档都会被匹配。

    coerce

    (8.2)link

      Data is not always clean,在JSON中,5这个数字可以用字符串"5"表示,也可以用数值表示,或者应该是整数5,但是在JSON中是一个浮点数,比如5.0,甚至是字符串"5.0"。

      coerce会尝试将dirty value转化为某个合适的字段的数据类型。比如:

      例如:

      第18行,number_one这个字段将包含数值类型的10   第23行,由于coerce被禁用了,所以这篇文档会被reject

    TIP:coerce参数可以通过update mapping API更新。

    Index-level default

      index.mapping.coerce这个设置能够在索引层全局的关闭所有字段的coerce的设置

      第20行,number_one这个字段中的设置覆盖了索引层的设置,即开启了coerce   第23行,这个文档会被reject,因为number_two继承了索引层的设置,即关闭了coerce

    copy_to

    (8.2)link

      copy_to参数允许你将多个字段的字段值写入到group field中,这个group filed可以被当成一个字段进行查询。

    TIP:如果你经常使用多个字段进行查询,你可以使用copy_to写入到较少的字段来提高查询速度。

      Tune for search speed

      下图中,first_namelast_name的字段值能被拷贝到full_name中:

      第7、11行,first_namelast_name的字段值被拷贝到full_name   第30行,first_namelast_name这两个字段依然能分别用来查询frist_name以及last_name,而full_name可以用来同时查询frist_name以及last_name。

      一些重要点:

    NOTE:字段值类型是objects的字段不支持copy_to,例如date_range。

    doc_values

    (8.2)link

      大部分的字段默认情况下都会被索引,使得可以被用于搜索。倒排索引使得可以在有序的term集合中找到该term,并且能马上获取到包含 term的文档列表。

      排序、聚合以及脚本中访问字段值需要一种不同的数据访问模式(data access pattern)。我们需要能够根据文档(文档号)找到这个文档中包含的某个字段的所有字段值,而不是根据字段值找到文档。

      DocValues一种 on-disk的数据结构。这种基于文档的索引,使得上述的数据访问模式的成为可能。DocValues使用列式存储column-oriented 存储了跟_source字段相同的值,使得排序跟聚合更高效。DocValues几乎支持所有的字段类型,除了text跟annotated_text这两类字段。

    Doc-value-only fields

      Numeric types, date types, boolean type, ip type, geo_point typekeyword type这些字段只开启了docValues(在Lucene中只用正排的数据结构存储)而没有用倒排索引存储,这些字段仍旧能够实现搜索,但是查询性能较差。这种索引方式是一种disk usage和查询性能的折中(tradeoff),适合用于那些不用于查询或者查询性能不重要的字段。这使得只包含docValues的字段非常适合通常不用于过滤的字段,例如metric data上的计量表(gauges)或计数器。

      Doc-value-only字段可以通过下面方式配置:

      第6行,status_code是一个普通的long类型的字段。   第10行,session_id关闭了index,使得该字段是Doc-value-only字段,并且只开启DocValues。

    Disabling doc values

      所有支持DocValues的字段都会默认开启DocValues,如果你确定这个字段不需要进行聚合、排序,或者在脚本中访问这个字段的字段值,那么你可以关闭DocValues来节省磁盘空间:

      status_code默认开启doc_values

      status_code关闭了doc_values,但是仍然能被用于查询。

    NOTE:你不能关闭wildcard 字段的doc_values

    dynamic(mapping parameter)

    (8.2)link

      当你索引的一篇文档中包含一个新的字段时,Elasticsearch会动态的添加字段,添加到文档中,或者文档中某个对象字段(object field)中,下面的例子在文档中添加了一个String类型的字段username,以及对象字段name,在这个对象字段中添加了两个字段:

      第4行,name对象字段下的两个字段是name.firstname.last   第10行,查看这个索引的mapping

      下面这篇文档增加两个字符串字段: emailname.middle:

    Setting dynamic on inner objects

      inner object会继承parent object或者mapping type中的dynamic参数,在下面的例子,在mapping顶层中关闭了dynamic,所以顶层中新的字段不会被动态添加。

      然而,user.social_networks这个object字段开启了动态mapping,所以这一层的新的字段会被动态添加:

      第4行,mapping类型那一层关闭了动态mapping   第6行,user这个object字段继承了mapping类型一层的dynamic的参数   第12行,social_networks这个inner object开启了动态mapping

    Parameters for dynamic

      dynamic的不同值控制了是否动态的添加新的字段,可选值如下:

    eager_global_ordinals

    (8.2)link

    What are global ordinals?

      为了能支持在聚合和其他操作中可以从文档中找到字段值,Elasticsearch使用了一个成为doc values的数据结构。例如keyword这种Term-based的字段类型(field type)会使用ordinal mapping这种更紧凑的数据结构来存储doc values。ordinal mapping的工作原理是给每一个term分配一个基于字典序,递增有序的整数。会为每篇文档存储这个字段的doc values的ordinal(数字),而不是字段值对应的原始term,通过一个lookup Structure实现ordinal和term之间的转化。

      在聚合中使用ordinal能极大的提高性能。例如在分片级别(shard-level)terms aggregation中使用ordinal来收集文档号并放入到分桶中,并且在跨分片对查询结果合并(combining)前将ordinal转化为对应的原始的term值。

      每一个index segment定义了自己的ordinal mapping。但是聚合是需要收集分片上的所有数据。所以为了能在分片级别使用ordinal用于聚合,Elasticsearch创建了一个名为global ordinals的统一映射(ordinal mapping)。这个global ordinal mapping是一个segment original,为每一个段构建并维护了global ordinal 到local ordinal的映射关系。

      如果查询中包含了下列的component就会使用Global ordinals:

    NOTE: global ordinal mapping会占用heap memory,属于field data cache的一部分。 对high cardinality fields(不同的字段值数量很多)进行聚合会使用很多的内存并且会触发field data circuit breaker

    Loading global ordinals

      查询期间,在ordinals可以被使用前必须先构建global ordinal mapping。默认情况下,在需要使用global ordinal时并且只在这类查询第一次发起后才会构建这个mapping。如果你想要优化索引速度(Indexing speed),这是一种正确的方式。但如果查询性能的优先级最高,建议尽快生成将要执行聚合的字段的global ordinals:

      开启eager_global_ordinals后,在分片refresh后就会构建global ordinals。Elasticsearch总是在展示(expose)变更的索引内容前先载入它们,将构建global ordinal的开销从查询期间转移到索引期间。Elasticsearch将总是在创建一个新的副本分片时急切的(eagerly)构建global ordinal,同样的会发生在增加副本数量或者在新的节点重新分配一个分片时。

      可以通过更新eager_global_ordinals这个设置来关闭Eager loading:

    Avoiding global ordinal loading

      通常来说,global ordinal不会在载入时间跟内存占用方面有很大的开销。然而在大的分片上或者字段中包含了很多唯一term上载入global ordinal的开销会比较昂贵。因为global ordinal提供了分片上所有段的统一的mapping,当出现一个新段后需要重新完整的构建global ordinal:

      在某些情况下,可以完全避免加载global ordinal:

    enabled(mapping parameter)

    (8.2)link

      Elasticsearch会尝试索引你提供的所有的字段,但有时候你只是想保存某些字段而不想索引它们。例如你想要使用Elasticsearch来存储web session,你也许要索引session ID和 last update time,但是你不想对session data进行查询或者聚合操作。

      enabled参数只能在mapping的顶层top-level定义并且只能应用object类型的字段,这会使得Elasticsearch不再解析object字段下所有内容,JSON内容仍然可以从_source中检索到,无法通过其他方式查询或者进行存储:

      第11行,session_data字段的enable参数为false   第22行,任意类型的数据都可以赋值给session_data字段,Elasticsearch不会解析这些数据(不解析意味着可以给一个object字段赋非JSON格式的数据)   第33行,session_data字段同样会忽略不是JSON类型的数据

      可以在mapping中直接定义enable参数为false,这样使得所有的内容可以在_source字段中检索到但是不会被索引。

      第4行,enable参数将应用mapping中的所有字段   第19行,文档可以被检索到   第21行,这个索引的mapping中没有任何的字段的信息

      The enabled setting for existing fields and the top-level mapping definition cannot be updated。

      由于Elasticsearch完全不会去解析字段值,所以可以把非object格式(JSON格式)的值赋值给object字段:

      成功添加了文档,并且session_data字段的字段值不是JSON类型。

    format(mapping parameter)

    (8.2)link

      在JSON类型的文档中,日期用字符串表示。Elasticsearch使用预先配置好的一些format集合来识别并且将这些字符串解析为long类型的milliseconds-since-the-epoch UTC。

      除了build-in formats,你可以指定custom formats,例如使用熟悉的yyyy/MM/dd

      许多API支持date value,也支持date math expression,例如now-1m/d,即当前时间减去一个月,四舍五入到最近的那天。

    Custom date formats

      支持自定义的date format。参考DateTimeFormatter docs

    Built In Formats

      大多数下面提到的格式都有一个严格对应的格式,这意味着年、月和日的部分必须分别严格使用4位、2位和2位数字,可能需要前面补零。例如,像 5/11/1 这样的日期将被视为无效,需要重写为 2005/11/01 才能被日期解析器(Date format)接受。

      要使用它们,您需要在日期格式的名称前加上 strict_ ,例如使用 strict_date_optional_time 而不是 date_optional_time。

      这些严格的日期格式在动态映射日期(date fields are dynamically mapped)字段时特别有用,以确保不会意外地将无关的字符串映射为日期。

      下表列出了所有支持的默认 ISO 格式(国际标准化组织(International Organization for Standardization, ISO)制定的标准格式):

    epoch_millis

      一个用于自epoch以来毫秒数的format。请注意,这个时间戳受限于 Java 的 Long.MIN_VALUE 和 Long.MAX_VALUE。

    epoch_second

      一个用于自epoch以来毫秒数的format。请注意,这个时间戳受限于 Java 的 Long.MIN_VALUE 和 Long.MAX_VALUE。epoch_millis除以1000即epoch_second。

    date_optional_time or strict_date_optional_time

      一个通用的 ISO 日期时间format,其中日期至少必须包括年份,而时间(由 T 分隔)是可选的。示例:yyyy-MM-dd'T'HH:mm:ss.SSSZyyyy-MM-dd.sss表示毫秒,Z表示时区,它等同于+0000

    strict_date_optional_time_nanos

      一个通用的 ISO 日期时间format,其中日期至少必须包括年份,而时间(由 T 分隔)是可选的。秒的小数部分具有纳秒级的分辨率。示例:yyyy-MM-dd'T'HH:mm:ss.SSSSSSZyyyy-MM-dd

    basic_date

      一个基本的完整的日期format:4位数的年,2位数的月以及2位数的天。示例:yyyyMMdd

    basic_date_time

      一个基本的format由日期和时间组成,用T分隔:yyyyMMdd'T'HHmmssZ

    basic_date_time_no_millis

      一个基本的format由日期和时间组成,用T分隔,没有毫秒:yyyyMMdd'T'HHmmssZ

    basic_ordinal_date

      完整的序数日期(ordinal date)的format,使用4位数的年以及3位数的天:yyyyDDD。比如2023年的1月1日表示为 2023001,而12月31日表示为 2023365(或在闰年中为 2023366)。。

    basic_ordinal_date_time

      一个用于完整序数日期和时间的格式化器,使用4位数年份和3位数一年中的天数:yyyyDDD'T'HHmmss.SSSZ。比如2023301'T'153045.678+0100

    basic_ordinal_date_time_no_millis

      一个用于完整序数日期和不带毫秒的时间的格式化器,使用4位数年份和3位数一年中的天数:yyyyDDD'T'HHmmssZ

    basic_time

      一个基本的format,使用2位数的小时,2位数的分钟,2位数的秒,3位数的毫秒以及时区偏移:HHmmss.SSSZ。这里的Z表示UTC时区,例如153045.678Z表示0时区,而153045.678+0800表示东八区,同样的153045.678Z153045.678+0000是一样的。

    basic_time_no_millis

      一个基本的format,使用2位数的小时,2位数的分钟,2位数的秒以及时区偏移:HHmmssZ

    basic_t_time

      一个基本的format,使用2位数的小时,2位数的分钟,2位数的秒,3位数的毫秒以及时区偏移,T作为前缀:'T'HHmmss.SSSZ

    basic_t_time_no_millis

      一个基本的format,使用2位数的小时,2位数的分钟,2位数的秒以及时区偏移,T作为前缀:'T'HHmmssZ

    basic_week_date or strict_basic_week_date

      一个基本完整日期,使用4位数的年,2位数的周以及1位数的天:xxxx'W'wwe。例如2023年的第一周的周三可以表示为 2023W013

    basic_week_date_time or strict_basic_week_date_time

      相较于basic_week_date or strict_basic_week_date,额外增加了时间,用T分隔:xxxx'W'wwe'T'HHmmss.SSSZ

    basic_week_date_time_no_millis or strict_basic_week_date_time_no_millis

      相较于basic_week_date_time or strict_basic_week_date_time,少了毫秒:xxxx'W'wwe'T'HHmmssZ

    date or strict_date

      一个完整的日期,使用4位数的年,2位数的月,2位数的天:yyyy-MM-dd

    date_hour or strict_date_hour

      相较于date or strict_date,额外增加了时间,用T分隔:yyyy-MM-dd'T'HH

    date_hour_minute or strict_date_hour_minute

      相较于date_hour or strict_date_hour,额外增加了分钟:yyyy-MM-dd'T'HH:mm

    date_hour_minute_second or strict_date_hour_minute_second

      相较于date_hour_minute or strict_date_hour_minute,额外增加了秒:yyyy-MM-dd'T'HH:mm:ss

    date_hour_minute_second_fraction or strict_date_hour_minute_second_fraction

      相较于date_hour_minute_second or strict_date_hour_minute_second,额外增加了秒的小数部分(也即就是毫秒),描述000~999范围:yyyy-MM-dd'T'HH:mm:ss.SSS

    date_hour_minute_second_millis or strict_date_hour_minute_second_millis

      相较于date_hour_minute_second or strict_date_hour_minute_second,额外增加了毫秒,描述000~999范围:yyyy-MM-dd'T'HH:mm:ss.SSS

      date_hour_minute_second_fraction or strict_date_hour_minute_second_fraction跟date_hour_minute_second_millis or strict_date_hour_minute_second_millis是相同的。

    date_time or strict_date_time

      一种基本的完整的日期跟时间的format,用T分隔日期跟时间:yyyy-MM-dd'T'HH:mm:ss.SSSZ

    date_time_no_millis or strict_date_time_no_millis

      相较于date_time or strict_date_time,没有毫秒:yyyy-MM-dd'T'HH:mm:ssZ

    hour or strict_hour

      2位数的小时:HH

    hour_minute or strict_hour_minute

      相较于hour or strict_hour,额外增加了分钟:HH:mm

    hour_minute_second or strict_hour_minute_second

      相较于hour_minute or strict_hour_minute,额外增加了秒:HH:mm:ss

    hour_minute_second_fraction or strict_hour_minute_second_fraction

      相较于hour_minute_second or strict_hour_minute_second,额外增加了秒的小数(也就是毫秒):HH:mm:ss.SSS

    hour_minute_second_millis or strict_hour_minute_second_millis

      相较于hour_minute_second or strict_hour_minute_second,额外增加了毫秒:HH:mm:ss.SSS

    ordinal_date or strict_ordinal_date

      一个完整的序数日期,使用4位数的年和3位数的天:yyyy-DDD。例如,2023-001 表示 2023 年的第一天,即 1 月 1 日。而 2023-365 表示 2023 年的最后一天,假设它不是闰年。

    ordinal_date_time or strict_ordinal_date_time

      相比较ordinal_date or strict_ordinal_date,额外增加了时间:yyyy-DDD'T'HH:mm:ss.SSSZ

    ordinal_date_time_no_millis or strict_ordinal_date_time_no_millis

      相比较ordinal_date_time or strict_ordinal_date_time,没有毫秒:yyyy-DDD'T'HH:mm:ssZ

    time or strict_time

      一个使用2位数的小时,2位数的分钟,2位数的秒以及3位数的秒的小数(也即是毫秒)和时区偏移:HH:mm:ss.SSSZ

    time_no_millis or strict_time_no_millis

      相比较 time or strict_time,没有毫秒:HH:mm:ssZ

    t_time or strict_t_time

      相比较 time or strict_time,额外使用了T作为前缀:'T'HH:mm:ss.SSSZ

    t_time_no_millis or strict_t_time_no_millis

      相比较t_time or strict_t_time,没有毫秒:'T'HH:mm:ssZ

    week_date or strict_week_date

      一个完整的日期,使用4位数的年,2位数的周以及1位数的天:xxxx-'W'ww-e。 例如2023年的第一周的周三可以表示为 2023-W01-3。

    week_date_time or strict_week_date_time

      相较于week_date or strict_week_date,额外增加了时间,使用T分隔:xxxx-'W'ww-e'T'HH:mm:ss.SSSZ

    week_date_time_no_millis or strict_week_date_time_no_millis

      相较于week_date_time or strict_week_date_time,没有毫秒:xxxx-'W'ww-e'T'HH:mm:ssZ

    weekyear or strict_weekyear

      一个使用4位数的年的format:xxxx

    weekyear_week or strict_weekyear_week

      相较于weekyear or strict_weekyear,额外增加了2位数的周:xxxx-'W'ww

    weekyear_week_day or strict_weekyear_week_day

      相较于weekyear_week or strict_weekyear_week,额外增加了1位数的天:xxxx-'W'ww-e

    year or strict_year

      一个使用4位数的年的format:yyyy

    year_month or strict_year_month

      相较于year or strict_year,额外增加了2位数的月:yyyy-MM

    year_month_day or strict_year_month_day

      相较于year_month or strict_year_month,额外增加了2位数的天:yyyy-MM-dd

    ignore_above

    (8.2)link

      字符串长度超过ignore_above中设置的值不会被索引或者存储,对于字符串数组,ignore_above会应用(apply)到数组中每一个字符串,并且超过ignore_above中设置的值不会被索引或者存储。

    NOTE:All strings/array elements will still be present in the _source field, if the latter is enabled which is the default in Elasticsearch.

      第7行,这个字段会忽略字符串长度超过20的字段值   第13行,这篇文档能成功索引   第18行,这篇文档会被索引,但是message字段不会被索引   第23行,两篇文档都会被搜索到,但聚合中只有第一篇文档的message的值会被呈现present

    TIP:可以通过update mapping API更新ignore_above的值。

      这个选项也可以用来处理Lucene中单个term的最大长度只支持到32766的问题。

    NOTE:ignore_above计算的字符的数量,但Lucene是按照字节计算的,如果你使用UTF-8那么长度应该限制到 32766/4 =8191,因为UTF-8最多用4个字节来描述一个字符。

    ignore_malformed

    (8.2)link

      有时候你不用过度控制待写入的数据,用户可能发送了date类型的login字段,但是又发送了一个email地址的login字段。

      尝试索引一个数据类型错误的字段默认情况下会抛出异常,并且reject这个文档,ignore_malformed参数如果设置为true,允许忽略异常,数据格式异常的字段不会被索引,其他的字段会被正常处理。

      第19行,这篇文档的text字段会被索引,number_one字段不会被索引   第25行,这篇文档会被reject因为number_two字段不允许数据格式错误的字段值

      下面的mapping类型允许设置ignore_malformed参数:

    Numericlong, integer, short, byte, double, float, half_float, scaled_float
    Datedate
    Date nanosecondsdate_nanos
    Geopointgeo_point for lat/lon points
    Geoshapegeo_shape for complex shapes like polygons
    IPip for IPv4 and IPv6 addresses

    TIP:可以通过update mapping API更新ignore_malformed的值。

    Index-level default

      在索引层index level设置index.mapping.ignore_malformed会对mapping中所有字段生效,如果mapping中的某些类型不支持这个参数会忽略该设置。

      第8行,number_one字段会继承索引层的设置   第13行,number_two字段的ignore_malformed会覆盖索引层的设置

    Dealing with malformed fields

      ignore_malformed开启后,数据格式错误的字段在索引期间会被忽略,无论如何建议保留那些包含数据格式错误字段的文档的数量,否则查询_ignored字段就没有意义了。Elasticsearch可以使用_ignored字段结合exists,term or terms来查询哪些文档中有数据格式错误的字段。

    Limits for JSON Objects

      下面的数据类型不能使用ignore_malformed

      ignore_malformed参数不能用于JSON objects。JSON object是使用{}包住的类型,它包含的数据映射了nested, object, and range数据类型。

      如果你提交了数据格式错误的JSON object,Elasticsearch会无视ignore_malformed参数的设置并返回错误并且reject这个文档。

    index(mapping parameter)

    (8.2)link

      index这个参数用来控制字段值是否要索引,该值可以是true或者false,默认值为true,没有进行索引的字段通常是无法用于查询的。

    index_options

    (8.2)link

      index_options参数用来控制哪些信息被添加到倒排索引inverted index中,用于查询或者高亮。只有term-based的字段比如textkeyword才支持该配置。

      index_options参数的可选值如下所示,注意的是每个参数值包含上一个参数值中添加的参数,比如freq包含docspositions同时包含freqdocs

      第27行,因为第7行设置了offsets参数,text字段将默认使用倒排信息(posting)来实现高亮。

    index_phrases

    (8.2)link

      开启这个参数后,2个term组成的字段值会被索引到额外的字段(separate filed)中。这使得exact phrase(no slop) 查询可以更高效,代价就是索引大小会增加。注意的是只有移除了停用词后才能达到最佳性能,因为包含了停用词的短语将不会使用subsidiary field并且会回滚到标准的短语查询。默认是false。

    index_prefixes

    (8.2)link

      index_prefixes参数对term的前缀进行索引来加速前缀查询。接收下面的可选设置:

      用于索引的前缀长度最小值。该值必须大于0,默认值是2(inclusive)

      用于索引的前缀长度最大值。该值必须小于20,默认值是5(inclusive)

      下面的例子使用默认的前缀长度设置创建了一个text字段:

      第7行,空的object即使用默认的min_charsmax_chars设置。

      这个例子使用了自定义的前缀长度设置:

    meta(mapping parameter)

    (8.2)link

      字段的附加元信息(metadata)(key-value键值对信息),元数据对Elasticsearch是不透明的,他只是用来在多个应用间分享在同一个索引中某个字段的元信息,比如字段值的单位unit:

    NOTE:字段的元数据最多可以设置5个,key的长度必须小于等于20,value的长度必须小于等于50

    NOTE:字段的元数据可以通过mapping更新进行变更,新的元信息会覆盖旧的元信息

      Elastic产品会使用下面2个标准的字段的元数据,你可以遵循这些元数据约定来获得更好的数据开箱即用体验

    unit

      数值类型的单位,例如percent, byte或者 time unit,默认情况字段是没有单位的,除了数值类型的字段,百分比单位约定 1100%

    metric_type

      metric_type同样用于数值类型的字段,可选值是gaugecounter,gauge是一种单值测量,可以随着时间的推移而上升或下降,例如温度。counter是一个单值累积计数器,它只上升,比如web服务器处理的请求数。默认情况下,字段不会使用metric_type参数。仅对数值类型的字段有效。

    fields

    (8.2)link

      经常出于某些目的需要对同一个字段执行不同的索引方式,这就是multi-fields的设计初衷。例如,一个字符串的字段值可以作为text字段使得可以全文检索,也可以作为keyword字段使得可以用于排序、聚合:

      第8行,city.raw字段是city字段的keyword版本   第31行,city字段可以用于全文检索   第35、40行,city.raw可以用于排序跟聚合

      你可以通过update mapping API对现有的字段添加multi-filed

      multi-field字段完全独立与parent filed(上面的例子中,city.raw的parent filed就是city),意味着它不会继承parent field的任何参数。当然了,Multi-fields不会更改_source中的内容。

    Multi-fields with multiple analyzers

      另一个multi-fields的用例就是对同一个字段的字段值采用不同的分词器来得到更好的关联(better relevance)。比如我们可以对字段值使用standard analyzer,将这个字段值分为多个词(word),或者对这个字段值使用english analyzer ,将英文单词转为root format,并且写入到索引:

      第5行,text字段使用standard(默认)分词器   第8行,text.english字段使用english分词器   第19、22行,索引了两篇文档,一篇文档中包含了fox而另一篇则包含了foxes   第33行,同时查询texttext.english字段,这两个字段都会影响文档的打分

      text字段在第一篇文档中包含了fox并且在第二篇文档中包含了foxestext.english字段在两篇文档中都包含了fox,因为foxes被词根化stemmed为成了fox

      查询中的字符串同样会对于text字段使用standard分词器,并且对于text.english字段使用english分词器。词根化stemmed的字段允许如果是查询foxes,会去匹配包含fox的文档,使得我们可以尽可能的匹配更多的文档。当查询没有词根化unstemmed的text字段时,我们会提高那些同时匹配foxes的文档的分数。

    normalizer(mapping parameter)

    (8.2)link

      keyword的属性normalizer类似与analyzer,只是它能保证分析链(analysis chain)只会生成单个token。

      normalizer先应用到keyword然后再进行索引,同样的在查询期间,查询kewword字段时会执行一个query parser,例如match query或者term-level query例如term query。

      可以使用一个简单的elasticsearch自带的(ship with)名为lowercase的normalizer,自定义的normalizer可以在analysis中定义:

      上面的查询会匹配到1和2这两篇文档,因为BAR同时在索引和查询期间被转化为bar

      同样的,由于keyword的值在索引前就先被转化了,意味着聚合操作返回的是normalized values:

      返回:

    norms(mapping parameter)

    (8.2)link

      norms存储各种标准化因子(normalization),随后在查询期间用于文档的打分 。

      norms对于打分是很有用的,但是它同时需要很多的磁盘空间(通常在每个文档每个字段上约占一个字节,即使是索引中没有这个特定字段的文档也是如此)。因此,如果你不需要在某个特定字段上进行得分计算,你应该禁用该字段上的规范。特别是对于那些仅用于过滤或聚合的字段。

    TIP:可以通过update mapping API对关闭现有的字段的norm

      Norms可以通过update mapping API按照下面的方式关闭:

    NOTE:Norms不会马上被移除,而是在你继续索引新的文档后,并且在旧的段合并到新段后才会移除。被移除了norm的字段将返回不一致的结果,因为有些文档不在有norm,而其他的文档仍然有norm。

    null_value

    (8.2)link

      null不能被索引或者搜索,当一个字段被设置为null(空的数组或者数组元素都是null),该字段被认为是没有值的。

      null_value允许将那些为null的字段值替换为你指定的值,使得可以被索引和搜索,例如:

      第7行,使用字符串NULL替换那些为null的字段值。   第20行,空的数组不包含显示的null值,该字段值不会被替换为NULL   第27行,字段名status_code、字段值NULL的查询可以匹配文档1,不会匹配文档2

    IMPORTANT:null_value的字段值类型必须跟这个字段的类型一致,long类型的字段不能设置为字符串类型的null_value

    NOTE:null_value只会影响数据的索引和查询,它不会修改_source中文档的数据

    position_increment_gap

    (8.2)link

      为了能支持proximity or phrase queries,text类型的字段被分词(Analyzed)后会统计term的positions信息。当索引多值(Arrays)的text字段时,Elasticsearch会在这些值之间添加一个假的距离,来阻止phrase query能跨相邻两个值进行查询。这个假的距离使用position_increment_gap配置并且默认值是100。

      例如

      第11行,这个phrase query 不会匹配到文档,与我们的期望不符。   第23行,这个phrase query会匹配到文档,因为slop大于position_increment_gap,尽管AbrahamLincoln是两个数组元素的值。

      position_increment_gap可以通过下面的方式在mapping中指定:

      第7行,若position_increment_gap设置为0,那么数组中相邻的两个term的距离为0

      第22行,这个phrase query会匹配到文档看起来是有点奇怪的,但原因是我们在mapping要求这么做的。

    小知识

      在es中定义了"names": [ "John Abraham", "Lincoln Smith"],如果position_increment_gap的值为0,那么相当于定义了"names": "John Abraham Lincoln Smith"。在Lucene层,es的arrays类型会将每一个数组元素作为Lucene中同一篇文档的相同字段名的多个字段信息。以name为例,在Lucene中,会生成两个字段名为name,字段值分别为John Abraham和Lincoln Smith的字段。由于这两个字段有相同的字段名,那么在倒排索引中,Abraham和Lincoln的位置是相邻的,当然前提是position_increment_gap的值为0。

    properties

    (8.2)link

      类型映射,object fields和包含子字段(sub-field)nested fiedlds都称为properties。这些properties可能是任意的数据类型(date type),包括objectnested。可以通过下面的方式添加properties

      下面是一个添加properties的例子,添加了一个objectnested字段:

      第4行,在顶层mapping中定义   第6行,在manager下定义   第13行,在employees下定义   第22行,索引一篇对应上面定义的mapping的文档

    TIP:properties这个配置运行在同一个索引中对同一个字段名有不同的设置。可以通过update mapping API添加或者更新现有字段的properties。

    Dot notation

      Inner field可以通过dot notation获取并在query、aggregation中使用:

    IMPORTANT:必须要指定Inner field的完整路径

    search_analyzer

    (8.2)link

      通常来说,在索引和查询期间应该应用(apply)相同的analyzer来保证query中的term跟倒排索引中的term有相同的格式(in the same format)。

      但有的时候在查询期间使用不同的分词器是有意义的,比如使用edge_ngram tokenizer 用于autocomplete或者查询期间的同义词查询。

      默认情况下,查询会使用mapping中定义的analyzer,但是可以用search_analyzer设置覆盖:

      第13行,Analysis设置中自定义的分词器autocomplete   第28,29行,text字段使用在索引期间使用autocomplete分词器,而在查询期间使用standard分词器   第37行,这个字段对应的这些term会被索引:[q, qu, qui, quic, quick, b, br, bro, brow, brown, f, fo, fox]   第45行,query中查询的term为:[quick, br]

      Index time search-as-you- type 查看这个例子的详细介绍。

    TIP:可以使用update mapping API对现有的字段上更新search_analyzer设置。注意的是,Note, that in order to do so, any existing "analyzer" setting and "type" need to be repeated in the updated field definition。

    similarity

    (8.2)link

      Elasticsearch允许你为每一个字段配置一个文本打分算法(text scoring algorithm)或者similarity。参数similarity允许你提供一个简单文本打分算法而不是使用默认的BM25,例如boolean

    BM25Okapi BM25 algorithm,Elasticsearch以及Lucene默认使用这个算法
    boolean一个简单的布尔算法,不需要全文本ranking并且打分值基于是否匹配到了查询中的term。Boolean算法给term打出的分数跟它们的query boost一样

      参数similarity可以在字段最开始创建时设置在这个字段的层级:

      第5行,这个字段名为default_field的字段使用BM25算法   第10行,这个字段名为boolean_sim_field的字段使用boolean算法

    store(mapping parameter)

    (8.2)link

      默认情况下,字段值被indexed使得可以被搜索到,但是它们没有存储(store)。意味着该字段能用于查询,但是原始的字段值(origin source value)不能被检索到。

      通常来说没有关系,因为字段值早已经是_source字段的一部分,默认被存储了。如果你想检索单个字段或者一些字段的字段值而不是整个_source, 你可以使用source filtering来达到你的目的。

      在有些情况下store一个字段的字段值是合理的(make sense)。比如说你有一篇文档有titledate以及一个字段值很大的content字段。你可能只想获取titledate的字段值而不用从字段值很大(因为_source中包含所有字段的字段值)的_source字段中提取出来:

      第7、11行,titledate字段的字段值被存储了   第29行,请求将检索titledate的字段值(不是从_source中提取)

    NOTE:

    Stored fields returned as arrays

    为了一致性,stored fields总是以数组方式返回,因为没法知道原始的字段值是单值,多值还是一个空的数组。如果你想获取这个字段原始的字段值(输入文档中的值),你应该从_source中获取。

    term_vector

    (8.2)link

      Term vectors包含了经过analysis处理后生成的terms的信息,包括:

      这些term vector会被存储所以可以针对某一篇文档进行检索。

      term_vector可以接受下面的参数:

    no不会存储term vectors(默认)
    yes只有term(位置、偏移、负载不会存储)会被存储
    with_positions存储term跟位置
    with_offsets存储term跟偏移
    with_positions_offsets存储term、位置以及偏移
    with_positions_payloads存储term、位置以及负载
    with_positions_offsets_payloads存储term、位置、偏移以及负载

      fast vector highlighter需要参数with_positions_offsetsterm vectors API用来检索存储的信息。

    WARNING:参数with_positions_offsets设置后会使得这个字段的索引大小翻倍。

      term vectors开启后,text字段会默认使用fast vector highlighter。

    Mapping limit settings

    (8.2)link   使用下面的设置限制mapping(手动或者动态创建)中字段的数量,防止因为文档(比如每一篇文档都会增加一些字段)导致mapping explosion。

    index.mapping.total_fields.limit

      索引中字段的数量最大值。Field and object mappings,以及field aliases都会纳入到统计中并受到限制。默认值为1000

    IMPORTANT:这个限制是为了防止mappings和查询变的很大(too large)。数量越高会导致性能下降以及内存问题,特别是集群处于高负载或者低资源时。 如果你提高这个设置,我们建议你同时提高indices.query.bool.max_clause_count,这个设置限制了一个Query中clause数量的最大值。

    TIP:如果你mapping中包含 a large,arbitrary set of keys,考虑使用flattened 数据类型。

    index.mapping.depth.limit

      某个字段的最大深度,用来估量inner object的数量。例如,如果所有的字段都在root object level,那么深度为1。如果某个字段有一个object mapping,那么深度就是2。默认值为20

    index.mapping.nested_fields.limit

      索引中nested类型的字段的数量最大值。nested类型应该只用于特殊的用例中,数组中的object需要各自独立的进行查询。为了保护mapping的不当设计,这个设置会限制每一个索引中nested类型的字段的数量。默认值是50

    index.mapping.nested_objects.limit

      一篇文档中所有nested类型的字段中JSON object的数量总和最大值。当一篇文档中包含太多的nested object时,防止出现OOM的错误。默认值是10000

    index.mapping.field_name_length.limit

      字段的名称长度最大值。这个设置不能解决mappings explosion的问题,但是如果你想要限制filed length时仍然是有用的。通常不需要设置它。除非用户增加了大量的字段,并且每个字段的字段名长度非常的长,否则使用默认值就可以了。默认值是Long.MAX_VALUE (no limit)

    index.mapping.dimension_fields.limit

      预览功能(Dynamic,integer)

      Elastic内部使用。

      索引中时序维度(time series dimension)数量的最大值。默认值为16

      你可以使用time_series_dimension mapping参数将某个字段标记为一个dimension。

    Removal of mapping types

    (8.2)link

      Elasticsearch 8.0.0不再支持mapping types。见7.x中的removal of types了解如何不使用mapping Type并迁移你的集群。

    Text analysis

    (8.2)link

      Text analysis是将无结构的文本(unstructured text),例如email的body或者产品描述,转化为优化查询的有结构的格式(structured format)的过程。

    When to configure text analysis

      Elasticsearch在索引和查询text字段时会执行text analysis。

      如果你的索引中没有text字段,那你不需要任何设置,可以跳过本章节内容。

      然而,如果你使用了text字段或者你的文本查询(text analysis)没有返回期望的结果,那configuring text analysis可以提供一定的帮助。如果你正在使用Elasticsearch实现下面的功能,那你也应该要查看下analysis configuration:

    In this section

    Text analysis overview

    (8.2)link

      文本分析(Text analysis)使得Elasticsearch可以执行全文检索(full-text search),查询结果将返回所有相关的结果而不是返回精确的匹配结果。

      如果你查询Quick fox jumps,你可能希望返回的文档中包含A quick brown fox jumps over the lazy dog,并且你可能还想要文档中包含像fast fox或者foxes leap相关的词。

    Tokenization

      Analysis通过tokenization使得全文检索成为可能。将一个文本break down成较小的多个块(smaller chunks),称为tokens。大部分情况下,token是一个个独立的单词(individual word)。

      如果你将一个短语the quick brown fox jumps作为单个string,然后用户查询quick fox,则不会匹配到这个短语。如果对这个短语进行tokenize,并且分别索引每一个词,这个query string中的term会被分别的查询。意味着这个短语会被quick foxfox brown或者其他variations匹配到。

    Normalization

      Tokenization使得可以匹配到独立的term(individual term),但只是字符匹配(match literally),意思是:

      为了解决上述的问题,text analysis可以将这些token normalize到一个标准格式。这使得你可以匹配到一些token,尽管这些token跟查询的term不是完全一样,但是它们足够的相似使得可以产生关联,例如:

      为了查询时能如期(intend)的匹配到这些词,你可以对query string应用相同的Tokenization和Normalization。例如Foxes leap的查询可以被normalized 成fox jump的查询。

    Customize text analysis

      Text analysis通过分词器analyzer实现,一系列的规则来管理整个的处理过程。

      Elasticsearch包含一个默认的分词器(analyzer),名为standard analyzer,这个分词器在大部分的开箱即用用例中都表现不错。

      如果你想自定(tailor)查询的体验,你可以选择不同的built-in analyzer,甚至configure a custom one。自定义的分词器可以控制分词处理过程中的一些步骤,包括:

    Text analysis concepts

    (8.2)link

      这一章节介绍Elasticsearch中text analysis的一些基本内容:

    Anatomy of an analyzer

    (8.2)link

      分词器(analyzer)可以是内置或者自定义的,它是包含了三个lower-level building blocks的包:character filters, tokenizers, 和 token filters。

    Character filters(concept)

      原始的文本作为一个字符流(a stream of characters),character filter接受这个字符流,通过adding,removing,或者changing character的方式对字符流进行转化。例如character filter可以用来将Hindu-Arabic numerals (٠١٢٣٤٥٦٧٨٩) 转化为 Arabic-Latin equivalents (0123456789)或者从流中移除(strip)HTML的element,比如<b>

      一个分词器可以没有,或者多个character filter。有序的依次应用(apply)这些character filter。

    Tokenizer(concept)

      Tokenizer接受字符流,将其拆分(break up)为独立的token(individual token),token通常是独立的一个词(individual word),然后输出一个token流(a stream of tokens)。例如whitespace会将文本按照空格进行token的划分,它会将Quick brown fox!划分成[Quick, brown, fox!]

      tokenizer同样负责记录每一个term的先后顺序,位置,以及字符的开始跟结束的偏移信息。

      一个分词器只能有一个Tokenizer

    Token filters(concept)

      token filters接受token流,并且add,remove,或者更改token。例如,lowercase这个token filters会将所有的token转成小写,stop token filter会从token流中移除常见的词(common word,停用词),比如thesynonym token filter会将同义词放到token流中。

      Token filters不允许更改token的位置以及偏移信息。

      一个分词器可以没有,或者多个Token filters,有序的依次应用(apply)这些token filters。

    Index and search analysis

    (8.2)link

      Text analysis会在下面两个时间点发生:

    Index time

      当索引一篇文档时,所有的text的字段值都会被分词(analyzed)。

    Search time

      当在text字段上执行full-text search时,query string(用户查询的内容)会被分词。

      Search time也被称为query time。

      analyzer或者一系列的analysis rules在不同的时间点分别称为index analyzersearch analyzer

    How the index and search analyzer work together

      在大多数情况下,Index time和search time应该使用相同的analyzer。这样能保证字段值跟query string都被更改(change)成相同的tokens。这样的话在搜索时就能达到期望的token匹配。

    example

      下面的值作为text字段的字段值进行索引:

      如果Index analyzer将上文的字段值转化为成token并进行了normalizes,在这个例子中,每一个token代表了一个词:

      这些token都会被索引。

      随后,一位用户会在相同的text字段上进行以下的查询:

      用户想要匹配刚刚上文中索引的句子:The QUICK brown foxes jumped over the dog!

      但是用户提供的query string中不存在精确的词(exact word)来匹配文档中的内容:

      为了能正确的查询,query string要使用相同的analyzer。这个analyzer会产生下面的tokens:

      执行查询时,Elasticsearch会比较query string中tokens 和text字段索引的tokens:

    TokenQuery stringtext field
    quickXX
    brown X
    foxXX
    jump X
    over X
    dog X

      由于字段值跟query string使用相同方式进行分词,因此它们会生成相同的token。quickfox是精确匹配,意味着查询会匹配到包含"The QUICK brown foxes jumped over the dog!"的文档,满足用户期望。

    When to use a different search analyzer

      有时候index time和search time需要使用不同的analyzer,不过这种场景不是很常见(while less common)。Elasticsearch允许你specify a separate search analyzer来处理这种场景。

      通常来说,当字段值和query string使用相同格式的token(same form of tokens)后得到不在期望内或者不相关的匹配时才会考虑使用不同的(separate)search analyzer。

    example

      Elasticsearch用来创建一个搜索引擎来匹配那些以查询词为前缀的结果。例如,查询词tr应该匹配tram或者trope,而不会匹配taxi或者bat

      一篇文档被添加到搜索引擎的索引中,这篇文档包含一个text类型的字段的值:

      index analyzer会将这个字段值转化为tokens并且执行normalizes。在这个例子中,每一个token是这个词的各种前缀。

      这些token都会被索引。

      随后,用户在相同的text字段上进行搜索:

      用户期望匹配以appli为前缀的结果,比如appliance或者application。这个查询不应该匹配到apply

      然而如果使用index analyzer来处理这个query string,它会生成下面的tokens:

      当Elasticsearch拿着query string中的tokens去匹配apply的tokens时,它会找到好几个匹配的结果:

    Tokenappliapple
    aXX
    apXX
    appXX
    applXX
    appli X

      这意味着错误的(erroneous)匹配到了apple,而且不仅仅会匹配到apply,还会匹配到所有以a为前缀的结果。

      要修复这种情况,可以为query string指定一个不同的search analyzer来处理text字段。

      在这个例子中,你可以指定一个search analyzer来生成单个token而不是生成前缀集合:

      这个query string token只会匹配以appli为前缀的结果,更接近用户期望的查询结果。

    Stemming

    (8.2)link

      Stemming(词根化)将一个词reduce到这个词的root form(词根)。使得这个词的各种变形都能在查询时匹配到。

      例如,walkingwalked都可以被stemmed到相同的root word:walk。一旦进行stemming,walkingwalkedwalk任意一个出现在查询中都会匹配到另外两个。

      Stemming属于language-dependent,但通常就是移除词的前缀跟后缀。

      有些情况下,经过stemming后的词可能就不是一个真实的词。例如jumpingjumpiness可以stemmed为jumpijumpi不是一个真实存在的词,但是这不会影响查询。如果所有词的变形都可以reduce为相同的词根,就可以正确的匹配到。

    Stemmer token filters

      在Elasticsearch中,在stemmer token filters中处理stemming。这些token filter根据它们不同词根化的方式可以分类为:

      由于词根化会更改token,我们建议在index and search analysis中使用相同的stemmer token filters。

    Algorithmic stemmers

      Algorithmic stemmers通过应用一系列的规则将每一个词reduce到它的词根(root form)。例如,一个用于英文的algorithmic stemmers会移除复数(plural)的-s-es后缀。

      Algorithmic stemmers有以下的一些优点:

      然而大多数的algorithmic stemmers只会改变词的文字(text of a word)。这意味着一些irregular word,它们本身不包含词根的内容,这类词就不能很好的词根化:

      下面的token filters使用了algorithmic stemming:

    Dictionary stemmers

      Dictionary stemmers从提供的字典中查找词。将未词根化的word variants替换为字典中词根化的词。

      理论上,dictionary stemmers适用于:

      实践中,algorithmic stemmers通常优于(outperform)dictionary stemmers。因为dictionary stemmers有以下的缺点:

      你可以使用hunspell token filter来执行 dictionary stemming。

    TIPs:如果可以的话,我们建议在使用 hunspell token filter前先使用algorithmic stemmer。

    Control stemming

      有时候stemming会将一些词共享同一个词根但是这些词之间只是拼写相似但是含义是没有任何关联的。例如,skiesskiing会被词根化为ski

      为了防止出现上述问题以及更好的控制stemming,你可以使用下面的token filters:

      对于内置(built-in)的language analyzers,你可以使用stem_exclusion参数来指定不需要词根化的词。

    Token graphs

    (8.2)link

      tokenizer 将文本转化为tokens后,它同时会记录下面的信息:

      使用上述信息可以创建一个directed acyclic graph,称为token graph。在一个token graph中,每一个位置代表了一个节点(node)。每一个token代表了一个edge或者arc,指向下一个位置。

    Synonyms

      一些token filters会增加新的token到现有的token stream中,例如同义词。这些同义词通常跟现有的tokens拥有相同的position。

      在下面的图中,quick和它的同义词fast有相同的位置:0。它们跨越相同的位置:

    Multi-position tokens

      有些token filters会增加跨越多个位置的token。这个token是multi-word的同义词,例如使用atm作为automatic teller machine的同义词。

      然而只有一些token filters,比如graph token filters,会为multi-position的token记录准确的positionLength。这类token filter包括:

      Some tokenizers, such as the nori_tokenizer, also accurately decompose compound tokens into multi-position tokens。

      下图中,domain name system和它的同义词dns,它们的position都是0。然而dnspositionLength3。其他的token在图中的positionLength的值默认就是1

      Indexing会忽略positionLength的属性并且不支持包含multi-position tokens的token graph。

      然而matchmatch_phrase query会使用这些图从单个query string中生成多个sub-queries。

      某个用户使用match_phrase查询下面的短语:

      search analysis中,dnsdomain name system的同义词,会被添加到query string对应的token stream中。dns这个token的positionLength的值为3

      match_phrase使用这个图来生成下面的sub-queries:

      意味着查询会匹配包含dns is fragile或者domain name system is fragile的文档。

    Invalid token graphs

      下面的token filter会添加token,这些token会跨越多个位置,但是只将positionLength记录为默认值:1

      这意味着这些filters会为包含这些token的流生产出错误的(invalid)token graph。

      在下图中,dns是multi-position,它是domain name system的同义词。然而dnspositionLength1,导致一个错误的图。

      避免使用错误的token图用于搜索。错误的图会导致不满足期望的查询结果。

    Configure text analysis

    (8.2)link

      默认情况下,Elasticsearch会使用默认的standard analyzer用于所有的文本分析(text analysis)。standard分词器(analyzer)作为开箱即用能满足大多数的语言和用例。如果你选择standard,那么不需要其他的任何配置。

      如果standard满足不了你的需求,你可以查看以及测试Elasticsearch提供的其他内置的built-in analyzers。内置的分词器也不需要进行配置,但是可以使用一些参数来调节分词器的行为。例如你可以对standard配置一个自定义的停用词列表。

      如果内置的的分词器都不能满足你的需求,你可以创建并测试你自定义的分词器。自定义的分词器包括选择和组合不同的analyzer components,让你能控制分词的过程。

    Test an analyzer

    (8.2)link

      analyze API 是一个非常有用(invaluable)的工具来查看分词器的分词效果。请求中可以指定内置的分词器:

      API会返回如下的结果:

      你也可以测试下面的组合:

      API会返回如下的结果:

    Positions and character offsets 从上文中的analyze API可以看出,分词器不仅仅会将词转化为term,并且还会有序的记录每一个term的相对位置(用于短语查询或者word proximity查询),以及每一个term在原始文本中的开始跟结束的偏移位置(用于高亮查询)

      或者在指定的索引上运行analyze API时指定一个custom analyzer

      第6行,定义一个名为std_folded的分词器   第21行,my_text字段使用std_folded分词器进行分词   第27行,要想引用这个分词器,analyze API必须要指定索引名   第29行,通过分词器的名称来指定一个分词器   第35行,对my_text字段进行分词

      API会返回如下的结果:

    Configuring built-in analyzers

    (8.2)link

      内置的分词器(analyzer)可以直接使用而不需要进行任何的配置。而一些内置的分词器支持参数配置来改变分词器的行为。例如,standard analyzer可以配置自定义的停用词集合:

      第6行,我们定义了一个基于standard的分词器std_english,但是使用了英语的停用词   第17行,my_text字段直接使用了standard分词器,没有进行任何的配置。   第31行,不会移除停用词,所以分词结果为:[the, old, brown, cow]   第21行,my_text.english字段使用了std_english,所以英语停用词会被移除,所以第37行的分词结果为:[old, brown, cow]

    Create a custom analyzer

    (8.2)link

      当内置的分词器(analyzer)无法满足你的需求时,你可以创建一个custom分词器,并使用合适的组合:

    Configuration

      custom分词器接受以下的参数:

    type分词器类型,可以是built-in analyzer类型。对于custom analyzer,使用custom或者omit这个参数
    tokenizer内置或者自定义的tokenizer
    char_filter可选参数,一个或者多个内置或者自定义character filters
    filter可选参数,一个或者多个内置或者自定义token filters
    position_increment_gapWhen indexing an array of text values, Elasticsearch inserts a fake "gap" between the last term of one value and the first term of the next value to ensure that a phrase query doesn’t match two terms from different array elements. Defaults to 100. See position_increment_gap for more.
    Example configuration

      这个例子使用了以下的组合:

    Character Filter
    Tokenizer
    Token Filters

      第7行,对于custom分词器,使用参数type的值为custom或者omittype这个参数。

      例子:

      第6行,分配给这个索引一个默认自定义的分词器,my_custom_analyzer。这个分词器使用了一个自定义的tokenizer,character filter以及token filter。这个分词器omit了type参数。   第18行,定义了一个自定义的名为punctuation的tokenizer。   第24行,定义了一个自定义的名为emoticons的character filter。   第33行,定义了一个自定义的名为english_stop的token filter。

      上面的例子会生成下面的term:

    Specify an analyzer

    (8.2)link

      Elasticsearch提供了多种方法(a variety of ways)来指定一个内置的或者自定义的分词器(analyzer)。

    TIP: Keep it simple 在不同的level(filed-level,index-level)和不同的时间点(索引或查询期间)能够灵活的指定分词器is good,但只有必要时才这么做。

    大多数情况下,简单的方式可以work well:为每一个text字段指定分词器。见Specify the analyzer for a field

    这个方式会按Elasticsearch的默认行为工作,让你在索引和查询阶段使用相同的分词器。也能让你快速的通过get mapping API了解哪个字段使用了哪个分词器。

    如果你不为你的索引创建mapping,你可以使用index templates来达到相同的效果。

    How Elasticsearch determines the search analyzer

      Elasticsearch会有序的检查下面的参数来检测使用了哪种index analyzer:

      如果没有指定这些参数,那么默认使用standard analyzer

    Specify the analyzer for a field

      你可以使用mapping参数analyzer为每一个text字段指定分词器。

      下面的create index API要求为title字段指定whitespace分词器:

    Specify the default analyzer for an index

      除了在field-level指定分词器,你可以使用analysis.analyzer.default设置一个fallback analyzer。

      下面的create index API为索引my-index-000001设置了一个名为simple的fallback analyzer。

    Specify the search analyzer for a query

      在执行full-text query时,你可以使用analyzer参数来指定 search analyzer,它会覆盖任何其他的search analyzer。

      下面的search APImatch query中设置了一个stop的分词器。

    Specify the search analyzer for a field

      你可以使用search_analyzer参数为每一个text字段指定一个search analyzer。

      如果提供了search analyzer,必须使用analyzer参数来指定index analyzer。

      下面的create index APItitle字段指定了一个simply分词器作为search analyzer。

    Specify the default search analyzer for an index

      creating an index时,你可以使用analysis.analyzer.default_search设置一个默认的search analyzer。

      如果设置了默认的search analyzer,你必须要使用analysis.analyzer.default设置默认的index analyzer。

      下面的creating an index中,为名为my-index-000001的索引设置了一个默认的名为whitespace分词器作为默认的search analyzer。

    Built-in analyzer reference

    (8.2)link

      Elasticsearch自带多种内置分析器,这些分析器可以在任何索引中使用,无需进一步配置:

    Custom analyzers

      如果你没有找到你想要的分词器,那你可以custom一个分词器,让这个分词器包含合适的character filtertokenizer以及token filters

    Fingerprint analyzer

    (8.2)link

      fingerprint 分词器实现了fingerprinting algorithm 用于在OpenRefine项目中帮助进行聚类。

      输入的文本会被小写化、标准化来移除扩展的字符,排序、去重并且最后拼接成单个token。如果配置了stopword列表,停用词会被移除。

    Example output

      上面的句子生成下面的单个term:

    Configuration

      fingerprint 分词器接受以下的参数:

      Stop Token Filter了解更多关于停用词配置的信息。

    Example configuration

      下面的例子中,我们为fingerprint分词器配置了一个预先定义好的English停用词:

      上面的例子中生成以下的term:

    Definition

      fingerprint包含下面的内容:

    Tokenizer
    Token Filters (in order)

      如果你需要自定义fingerprint分词器,你可以重新创建一个名为custom分词器然后修改它,通常添加token filter。这将重建内置的fingerprint分词器,你可以使用它,将其作为进一步的自定义作为一个起始点:

    Keyword analyzer

    (8.2)link

      keyword分词器是一个"noop"(没有操作)的分词器,它将整个输入的字符串作为单个token。

    Example output

      上面的句子将会生成以下单个term:

    Configuration

      keyword分词器没有配置项。

    Definition

      keyword 分词器包含以下内容:

    Tokenizer

      如果你需要自定义keyword分词器,你可以重新创建一个名为custom分词器然后修改它,通常添加token filter。通常如果你不需要将字符串切分为token时应该选择Keyword type 类型,但如果你一定要这么勇,这将重建内置的fingerprint分词器,你可以使用它,将其作为进一步的自定义作为一个起始点:

      第8行,你可以在这里添加任意的token filter。

    Language analyzers

    link

    Configuring language analyzers
    Excluding words from stemming

    Pattern analyzer

    link

    Simple analyzer

    (8.2)link

      simple分词器根据任意非字母(non-letter)的字符对文本进行划分。比如数字、空格、连字符和撇号,丢弃非字母字符,并将大写字母转换为小写字母。

    Example

      simple分词器解析上面的句子并且生成下面的token:

    Definition

      simple分词器包含以下内容:

    Tokenizer:
    Customize

      如果你需要自定义simple分词器,你可以重新创建一个名为custom分词器然后修改它,通常添加token filter:

      第8行,在这里添加token filter。

    Standard analyzer

    (8.2)link

      standard 分词器(analyzer)是默认的分词器,如果没有指定分词器则使用standardstandard提供了基于语法的分词(基于Unicode Text Segmentation algorithm,见 Unicode Standard Annex #29),它能很好的对大多数语言进行分词。

    Example output

      上面的句子会生成下面的term:

    Configuration

      standard分词器接收下面的参数:

      Stop Token Filter查看停用词的配置。

    Example configuration

      在这个例子中,我们将standard分词器的参数max_token_length设置为5(只是为了展示参数效果),然后使用预先定义的英语停用词:

      上面的例子能生成下面的term:

    Definition

      standard分词器包括下面的内容:

    Tokenizer
    Token Filters

      如果你需要自定义配置参数外的standard分词器,你需要重建一个custom的分词器然后修改它。通常是添加token filter。这样将重建一个内置的standard分词器。

      第9行,你可以在lowercase后添加其他的token filter。

    Stop analyzer

    (8.2)link

      stop 分词器和simple analyzer是一样的,但是增加了支持移除停用词。默认使用_english_停用词。

    Example output

      上面的句子将生成以下term:

    Configuration

      stop分词器接受以下的参数:

      Stop Token Filter了解更多关于停用词配置的信息。

    Example configuration

      在这个例子中,我们配置stop分词器来使用一个指定的停用词列表:

      上面的例子生成下面的term:

    Definition

      包含以下内容:

    Tokenizer:
    Token filters

      如果你需要自定义stop分词器,你可以重新创建一个名为custom分词器然后修改它,通常添加token filter,这将重建内置的stop分词器,你可以使用它,将其作为进一步的自定义作为一个起始点:

      第8行,默认的停用出可以用stopwords或者stopwords_path参数覆盖   第15行,你可以在english_stop后面添加任意的token filter

    Whitespace analyzer

    (8.2)link

      whitespace分词器(analyzer)会在根据空格将文本划分出term。

    Example output

      上面的句子会生成下面的term:

    Configuration

      whitespace 分词器不可以配置。

    Definition

      whitespace分词器包含下面的内容:

    Tokenizer

      如果你需要自定义whitespace分词器,你可以重新创建一个名为custom分词器然后修改它,通常添加token filter。这将重建内置的whitespace分词器:

      第8行,你可以在这里添加token filter。

    Tokenizer reference

    link

    Character group tokenizer

    link

      char_group tokenizer定义了一组集合,集合中的元素作为文本切分标识。希望自定义一个简单的分词器或者或者无法接受pattern tokenizer 的开销时,使用这个tokenizer非常有用。

    Configuration

      char_group tokenizer 接受以下参数:

    Example output

      输出:

    Classic tokenizer

    (8.2)link

      classic tokenizer是一个基于语法的分词器,适用于英文文档。这个分词器对首字母缩写词、公司名称、电子邮件地址和互联网主机名有特殊处理的启发式(tokenizer)规则。然而,这些规则并非总是有效,而且这个分词器对于英语以外的大多数语言效果不佳:

    Example output

      上面的句子将会生成下面的term:

    Configuration

      classic tokenizer 接受以下参数:

    Example configuration

      在这个例子中,我们将max_token_length的值设置为5(出于演示目的):

      上面的例子生成以下的term:

    Edge n-gram tokenizer

    link

      

    Keyword tokenizer

    link

      keyword tokenizer是一个noop(没有任何操作) tokenizer。无论给定的文本是什么样子,总是将其作为单个term。他可以跟token filter结合来标准化输出,比如将email地址小写。

    Letter tokenizer

    (8.2)link

      letter tokenizer在遇到一个非字母时开始切分。对于大多数的欧洲语言,这种切分方式是合理的,但是对于一些亚洲语言就不行了,因为单词之间不是用空格分隔的。

    Example output

      上面的例子生成以下的term:

    Configuration

      letter tokenizer没有配置项。

    Lowercase tokenizer

    link

      lowercase tokenizer跟letter tokenizer是一样的,也就是遇到一个非字母时开始切分,区别就是同时将所有的字母小写化。这个tokenizer的功能就相当于组合了letter tokenizerlowercase token filter,但是性能更好,因为它将这两个步骤同时处理了。

    Example output

      上面的例子生成以下的term:

    Configuration

      lowercase tokenizer没有配置项。

    N-gram tokenizer

    link

      

    Path hierarchy tokenizer

    link

      path_hierarchy tokenizer 用来处理有层级的值,比如说文件系统路径,根据路径符号划分,然后输出不同层的term。

    Pattern tokenizer

    link

      Pattern tokenizer使用正则表达式将文本进行分词,将匹配到的词,或者匹配到一段文本作为term。

    Simple pattern tokenizer

    link

      

    Simple pattern split tokenizer

    link

      

    Standard tokenizer

    (8.2)link

      standard tokenizer提供了基于语法的分词(基于Unicode Text Segmentation algorithm,见 Unicode Standard Annex #29),它能很好的对大多数语言进行分词。

    Example output

      上面的句子会生成下面的term:

    Configuration

      standard tokenizer接收下面的参数:

    Example configuration

      在这个例子中,我们将standardtokenizer的参数max_token_length配置为5(至少为了展示参数效果):

      上面的例子会生成下面的term:

    Thai tokenizer

    link

      

    UAX URL email tokenizer

    (8.2)link

      uax_url_email tokenizer跟standard tokenizer很像,差别是它能识别URLs以及email,并且他们作为单个term。

    Example output

      上面的例子会生成下面的term:

      如果是standard tokenizer会生成:

    Configuration

      uax_url_email tokenizer接受以下参数:

    Example configuration

      在这个例子中,我们将max_token_length设置为5(仅演示目的):

      上面的例子会生成下面的term:

    Whitespace tokenizer

    (8.2)link

      whitespace tokenizer会在根据空格将文本划分出term。

    Example output

      上面的句子将生成下面的term:

    Configuration

      whitespace tokenizer接收下面的参数:

    Token filter reference

    link

    Apostrophe token filter

    (8.2)link

      移除撇号后所有的字符,包括撇号自身。

      这个filter被包含在Elasticsearch内置的Turkish language analyzer。它使用的是Lucene中的ApostropheFilter,为Turkish语言构建的。

    Example

      下面的analyze API请求中展示了apostrophe token filter是如何工作的。

      这个filter生成下面的tokens:

    Add to an analyzer

      下面的create index API请求中使用这个filter来配置一个全新的custom analyzer

    ASCII folding token filter

    link

      ASCII folding token filter将不在Basic Latin Unicode block(基本拉丁字母Unicode块)(前127个ASCII字符)中的字母、数字和符号字符转换为它们的等价的ASCII(如果存在的话)。例如,这个过滤器会将à转换为a

      这个filter使用的是Lucene中的ASCIIFoldingFilter

    CJK bigram token filter

    link

      

    CJK width token filter

    link

      

    Classic token filter

    link

    Common grams token filter

    link

      

    Conditional token filter

    link

      定义token filter集合,应用到满足脚本中条件的token上。

      这个filter使用的是Lucene中的ConditionalTokenFilter

    Decimal digit token filter

    link

      

    Delimited payload token filter

    link

      

    Dictionary decompounder token filter

    link

      

    Edge n-gram token filter

    link

      

    Elision token filter

    link

      

    Fingerprint token filter

    link

      对一个token stream进行排序和去重,让将这个stream中的token进行拼接,最后作为单个token输出。

      例如,这个filter会对[ the, fox, was, very, very, quick ]这个token stream进行如下更改:

    1. 根据字母排序:[ fox, quick, the, very, very, was ]

    2. 移除重复的very 这个token

    3. 将这个token stream拼接成单个token:[fox quick the very was ]

    Flatten graph token filter

    link

      

    Hunspell token filter

    link

      

    Hyphenation decompounder token filter

    link

      

    Keep types token filter

    link

      保留或移除指定的类型。比如你可以使用这个filter通过只保留<ALPHANUM>3 quick foxes修改为quick foxes

    Keep words token filter

    link

      指定一个word list,只保留在这个列表中的word。

    Keyword marker token filter

    link

      

    Keyword repeat token filter

    link

      

    KStem token filter

    link

      

    Length token filter

    link

      指定token中字符数量的min跟max,小于min或者大于max的token会被移除。比如你可以使用这个filter过滤掉小于2个字符以及大于5个字符的token。

    Limit token count token filter

    link

      限制输出的token数量。这个filter通常用于根据token的数量来限制文档字段值的大小。

      默认情况下,这个filter只保留token stream中的第一个token。比如,这个filter可以将[ one, two, three ]这个token filter改为[ one ]

    Lowercase token filter

    (8.2)link

      将token text都转为小写的token。例如你可以使用lowercase filter将THE Lazy DoG转化为the lazy dog

      除了默认的filter,lowercase token filter还提供了访问Lucene中为Greek, Irish, and Turkish特别定制的lowercase filter。

    Example

      下面的analyze API使用默认的Lowercase filter 将THE Quick FoX JUMPs转化为小写。

      这个filter产生下面的token:

    Add to an analyzer

      下面的create index API 配置了一个custom analyzer,它使用了lowercase filter:

    Configurable parameters
    language

      (optional)特定的一些语言对应的lowercase token filter。可选值为:

      如果不指定该参数,则默认使用LowerCaseFilter

    Customize

      若要自定义lowercase filter,为新的自定义的token filter创建所需要的基本要素(basis)。

      下面的例子中自定义了用于Greek语言的lowercase filter:

    MinHash token filter

    link

      

    Multiplexer token filter

    link

      

    N-gram token filter

    link

      

    Normalization token filters

    link

      

    Pattern capture token filter

    link

      

    Pattern replace token filter

    link

      

    Phonetic token filter

    link

      

    Porter stem token filter

    link

      

    Predicate script token filter

    link

      移除不满足脚本条件的token。这个filter只支持内联的Painless脚本。脚本在analysis predicate context中计算。

    Remove duplicates token filter

    link

    Reverse token filter

    (8.2)link

      将stream中的每一个token进行颠倒(反转)。比如,你可以使用这个filter将cat改成tac

      基于后缀查询,比如找到以-ion为后缀的词或者根据扩展名查询的场景使用这个filter就非常有用。

      这个filter使用了Lucene中的ReverseStringFilter

    Example

      下面的analyze API请求中使用了reverse filter将quick for jumps中的每一个token进行了颠倒:

      下面的filter生成了以下的token:

    Add to an analyzer

      下面的create index API请求使用了这个filter来配置一个全新的custom analyzer

    Shingle token filter

    link

      

    Snowball token filter

    link

    Stemmer token filter

    link

    Stemmer override token filter

    link

    Stop token filter

    (8.2)link

      从token stream中移除stop words

      如果没有自定义停用词,会默认移除下列的英文单词:

      除了英语的停用词,stop filter支持预先定义好的stop word lists for several languages。你也可以用数组或者文件来定义属于你的停用词。

      stop filter使用的是Lucene的StopFilter

    Example

      下面的analyzer API请求中使用stop filter将移除a quick fox jumps over the lazy dog中的athe

      这个filter会生成下面的token:

    Add to an analyzer

      下面的create index API请求使用stop filter来配置一个新的自定义的custom analyzer

    Configurable parameters
    Customize

      要自定义stop filter,需要创建一个新的custom token filter所需要的基本要素。你可以使用可配置的参数来更改filter。

      例如,下面的请求中创建了一个自定义的大小写不敏感的stop filter。这个filter会移除_english_中的停用词。

      你也可以指定自定义的停用词。例如下面的请求中创建了一个自定义的大小写敏感的stop filter,它只移除andisthe

    Stop words by language

      下列是参数stopwords支持的参数值。并且链接指向了Lucene中每一种语言对应的停用词:

    _arabic_

    Arabic stop words

    _armenian_

    Armenian stop words

    _basque_

    Basque stop words

    _bengali_

    Bengali stop words

    _brazilian_ (Brazilian Portuguese)

    Brazilian Portuguese stop words

    _bulgarian_

    Bulgarian stop words

    _catalan_

    Catalan stop words

    _cjk_ (Chinese, Japanese, and Korean)

    CJK stop words

    _czech_

    Czech stop words

    _danish_

    Danish stop words

    _dutch_

    Dutch stop words

    _english_

    English stop words

    _estonian_

    Estonian stop words

    _finnish_

    Finnish stop words

    _french_

    French stop words

    _galician_

    Galician stop words

    _german_

    German stop words

    _greek_

    Greek stop words

    _hindi_

    Hindi stop words

    _hungarian_

    Hungarian stop words

    _indonesian_

    Indonesian stop words

    _irish_

    Irish stop words

    _italian_

    Italian stop words

    _latvian_

    Latvian stop words

    _lithuanian_

    Lithuanian stop words

    _norwegian_

    Norwegian stop words

    _persian_

    Persian stop words

    _portuguese_

    Portuguese stop words

    _romanian_

    Romanian stop words

    _russian_

    Russian stop words

    _sorani_

    Sorani stop words

    _spanish_

    Spanish stop words

    _swedish_

    Swedish stop words

    _thai_

    Thai stop words

    _turkish_

    Turkish stop words

    Synonym token filter

    link

      synonym token filter允许在解析过程(analysis process)中处理同义词。通过一个配置文件来配置同义词。例子:

      上面的例子中配置了一个带有analysis/synonym.txt路径的synonym filter(相对于config目录)。synonym分词器然后使用这个filter。

      (未完成)

    Synonym token filter

    link

      

    Synonym graph token filter

    link

      

    Trim token filter

    link

      

    Truncate token filter

    (8.2)link

      对超过字符数量限制的token进行截断。这个限制值默认是10,可以通过参数length参数配置。

      例如,你可以使用这个filter将所有的token中的字符数量限制到3或者更少的值。jumping fox修改为jum fox

      这个filter使用的是Lucene中的TruncateTokenFilter

    Example

      下面的analyze API请求使用这个filter将he quinquennial extravaganza carried on中超过10个字符的token进行了截断:

      下面的filter生成以下的tokens:

    Add to analyzer

      下面的create index API请求使用这个filter用来配置一个全新的custom analyzer

    Configurable parameters
    Customize

      要自定义这个filter,需要创建一个新的custom token filter所需要的基本要素。你可以使用可配置的参数来更改filter。

      例如,下面的请求创建了一个名为5_char_trunctruncate filter,会将token中的字符限制到5个或者5个以下。

    Unique token filter

    link

    Uppercase token filter

    (8.2)link

      将token转化为大写。比如你可以使用这个filter将the Lazy DoG修改为THE LAZY DOG

      这个filter使用的是Lucene中的UpperCaseFilter

    WARNING:某些语言中大写字符能映射多个小写字符。因此使用这个filter可能导致失去小写字符的信息。 若要避免这种损失但仍保持一致的字母大小写,可以改用lowercase filter。

    Example

      下面的analyze API请求使用这个filter将the Quick FoX JUMPs修改为大写。

      这个filter生成以下的tokens:

    Add to an analyzer

      下面的create index API请求使用这个filter来配置一个全新的customer analyzer

    Word delimiter token filter

    link

      

    Word delimiter graph token filter

    link

      

    Character filters reference

    link

    HTML strip character filter

    (8.2)link

      将HTML元素从文本中移除并且将HTML实体替换成解码后的值(比如&amp;替换为&)。

      html_strip filter使用的是Lucene中的HTMLStripCharFilter

    Example

      下面的analyzer API使用html_strip filter 将文本<p>I&apos;m so <b>happy</b>!</p> 修改为\nI'm so happy!\n

      这个filter生成下面的文本:

    Add to an analyzer

      下面的create index API请求使用html_strip filter来配置一个全新的custom analyzer

    Configurable parameters
    Customize

      若要自定义html_strip filter,则将其作为一个全新自定义的filter的组成部分,你可以使用可配置的参数来修改filter。

      下面的create index API使用了一个名为my_custom_html_strip_char_filter的自定义html_strip filter,并且配置到custom analyzer 中。

      my_custom_html_strip_char_filter跳过了<b>这个HTML 元素。

    Mapping character filter

    (8.2)link

      mapping character filter接收一个key,value的map。在character stream中遇到map中的key时,则将其替换为map中对应的value。

      这是一种greedy的匹配。按照最长模板进行匹配。替换值(replacement)可以是一个空的string。

      mapping filter 使用了 Lucene中的MappingCharFilter

    Example

      下面的analyze API使用了mapping filter 将Hindu-Arabic numerals (٠١٢٣٤٥٦٧٨٩) 转化为Arabic-Latin equivalents (0123456789)。将文本内容My license plate is ٢٥٠١٥转化为了My license plate is 25015

      上面的filter会生成下面的文本:

    Configurable parameters
    Customize and add to an analyzer

      要自定义mappings filter,创建一个自定义的character filter所需要的基本要素,你可以使用可配置的参数来修改它。

      下面的create index API请求配置了一个新的custom analyzer,它使用了一个自定义的mappings filter,my_mappings_char_filter

      my_mappings_char_filter filter将表情符号(emoticons):),:(替换成相同意思的文本:

      上面的analyze API请求使用自定义的my_mappings_char_filter将文本I'm delighted about it :(中的:(替换成了_sad_

      这个filter会生成下面的文本:

    Pattern replace character filter

    link

      

    Normalizers

    (8.2)link

      Normalizers跟分词器类似,区别在于它只输出单个token。因此,它没有tokenizer并且只接收一些有效的character filter和token filter。只有对单个字符处理的filter是允许在Normalizers中使用的。例如lowercase filter是允许的,而stemming filter则不允许,因为它需要将关键字作为一个整体来处理。下面的filter可以在Normalizers中使用:arabic_normalization, asciifolding, bengali_normalization, cjk_width, decimal_digit, elision, german_normalization, hindi_normalization, indic_normalization, lowercase, persian_normalization, scandinavian_folding, serbian_normalization, sorani_normalization, uppercase

      Elasticsearch使用lowercase用于内置的normalizers。其他形式的normalizers要求进行配置。

    Custom normalizers

      自定义的normalizers可以定义character filtertoken filter的集合。

    Index templates

    (8.2)link

    这个主题介绍了在Elasticsearch 7.8引入的composable index template。关于之前版本的index template是如何工作的见legacy template documentation

      在创建一个索引时,index template告诉Elasticsearch如何进行创建。对于data streams,index template用于创建流的backing索引。Template先于索引的创建。手动或者通过索引一篇文档创建一个索引后,template setting会作为创建索引的一个基本要素( basis)。

      一共有索引模板index template和组件模版component template两种类型的模板。component template构建配置了mapping,settings,alias这几块并可以复用。你可以使用一个或多个component template来构造index template,但不能直接应用到(apply)索引集合(a set of indices)。index templates 可以包含一个component template集合,直接指定settings,mappings和aliases。

      应用(apply)index template的几个条件:

    Avoid index pattern collisions

       Elasticsearch有内置的index template,每一个的优先级都是100,如下:

      Elastic Agent使用这些模板来创建data streams。Fleet integration创建的index template使用类似的overlapping index patterns并且优先级是200

      如果你使用Fleet或者Elastic Agent, 那么你的index template的优先级要小于100来防止覆盖掉这些模板。若要避免意外的应用了这些内置模板,采取下面一个或者多个方法:

    Create index template

      使用index templateput component templateAPIs来创建和更新index templates。你也可以在Kibana用意Stack Management来manage index templates

      下面的请求创建了两个component templates。

      第18行,这个component template添加了一个名为day_of_weekruntime field的字段,用于一个新的索引匹配到模板时。

      下面的请求创建了一个由上面的component template组成的index template。

    Simulate multi-component templates

    (8.2)link

      模板不仅仅由多个component template进行组合,也可以由index template自身。有两个simulation APIs用来查看最终的索引设置(index settings)。(当你指定了一个新的模板后,由于现有的模板可能跟这个新的模板有相同的index patter,由于优先级问题导致新的模板无法应用到新创建的索引,那么可以通过simulate来查看某个索引对应的index template,或者查看某个模板设置,见Simulate index template API Simulate index API

      若要模拟(simulate)出将要应用到某个指定的索引的索引设置,可以通过以下请求获取。

      若要模拟(simulate)出某个模板的模板设置,可以通过以下请求获取。

      你也可以在simulate 请求body中指定一个模板定义(新的模板设置)。这可以让你在添加一个新的模板前先校验下settings。(校验的目的之一是查看新的模板会不会被现有的模板覆盖或者覆盖现有的模板)

      下面的响应中展示了将会应用到匹配到的索引配置中的settings,mappings,以及aliases。任何被覆盖的模板中的配置会被simulate 请求中指定模板定义或者优先级更高的现有的模板取代。

      第5行,分片的数量来自simulate请求中的值,替代了index templatect1中的值   第19行,@timestap字段的定义来自index templatect2   第 27行,被覆盖的模板信息,它们有较低的优先级

     

    Data streams

    (8.2)link

      数据流(data stream)允许你跨多个索引append-only方式存储时间序列数据,同时为你提供单个命名资源用于请求。Data stream非常适合用于logs、events、metrics以及其他源源不断生成的数据。

      你可以直接向一个数据流提交索引和查询请求。数据流可以自动的将请求路由到存储流数据(stream's data)的backing indices中。你可以使用index lifecycle management(ILM)实现backing indeices的自动化管理。例如,你可以使用ILM自动将较老的backing indices移到成本更低的硬件上以及删除不再需要的数据。ILM可以帮助你降低随着不断增长的数据带来的开销和成本。

    Backing indices

      一个数据流由一个或者多个hidden、自动生成的backing indices组成。

      一个数据流要求有一个匹配的index template(index template)。这个模板包含了用于配置流的backing indices的mappings和settings。

      每一个索引到数据流中的文档必须包含一个@timestamp字段,映射为date或者date_nanos字段类型。如果index template没有指定@timestamp字段。Elasticsearch会根据默认选项映射一个date类型的@timestmap字段。

      同一个index template可以用于多个数据流。你不能删除一个正在被某个数据流使用的index template。

    Read requests

      当你向一个数据流提交一个读请求时,数据流会将这个请求路由到所有的backing indice上。

    Write index

      最近创建的backing index是数据流的write index。数据流只向这个索引中增加文档。

      你不能往其他backing indices中添加新的文档,甚至不能直接向这些索引中发送请求。

      你同样不能在write index上执行下面的操作,免得阻碍(hinder)索引写入:

    Rollover

      rollover操作会创建一个新的backing index,这个索引成为数据流中新的write index。

      我们建议使用ILM,它能在write index达到一个指定的寿命(age)或者大小后自动的滚动(roll over)数据流。如果有必要的话,你也可以manually roll over一个数据流。

    Generation

      每一个数据流会追踪它的generation:一个六位数字,0作为填充值的整数,用来累计(cumulative)数据流滚动次数,从000001开始。

      当创建一个backing index后,这个索引按下面的方式约定命名

      <yyyy.MM.dd>是backing index的创建时间。generation数值越大的backing index包含更多最近的数据。例如,web-server-logs这个数据流的generation的值为34。这个流在2099年3月7日创建,那么就命名为.ds-web-server-logs-2099.03.07-000034

      有些shink或者restore操作会更改backing index的名称。这些名称的变更不会数据流中移除backing index。

    Append-only

      数据流被设计为用于现有数据很少或者从不更新的场景。你不能向数据流中现有的文档发送更新或者删除的请求。与之替换使用update by querydelete by query APIs。

      如果有必要的话,你可以使用update or delete documents 向文档的backing index中提交请求。

    TIP:如果你要频繁的更新或删除时序数据,使用write index的index alias来替换数据流。见Manage time series data without data streams

    Set up a data stream

    (8.2)link

      按照下面几个步骤来设置一个数据流

    1. Create an index lifecycle policy

    2. Create component templates

    3. Create an index template

    4. Create the data stream

    5. Secure the data stream

      你也可以convert an index alias to a data stream

    IMPORTANT:如果你使用Fleet或者Elastic Agent,可以跳过这个教程。Fleet和Elastic Agent会为你设置数据流。见Fleet的data streams文档。

    Create an index lifecycle policy

      尽管是可选的,我们建议你使用ILM来实现数据流的backing indice的管理自动化。ILM需要一个索引生命周期策略。

      在Kibana中创建一个索引生命周期策略,打开主菜单然后选择Stack Management > Index Lifecycle Policies,点击Create policy

      你也可以通过create lifecycle policy API创建。

    Create component templates(data stream)

      data stream需要匹配一个索引模板(Index template)。在大多数情况下,你会使用一个或者多个组件模版component templates来组合成一个索引模板。你通常会为mappings跟Index settingss使用各自的component templates。这可以让你在多个索引模板中复用component templates。

      当你创建组件模版时,包括:

    TIP:使用Elastic Common Schema (ECS)来映射你的字段类型。ECS字段默认跟一些Elastic Stack features 集成 如果你不确定如何映射你的字段类型,你可以在查询期间使用runtime fields从非结构化的内容unstructured content中提取字段。例如你可以将log message索引到一个wildcard字段,随后在查询期间从这个字段中提取IP地址和其他数据。

      若要创建在kibana中创建一个组件模版,打开主菜单然后跳转到Stack Management > Index Management。在Index Templates视图中,点击Create component template

      你也可以使用create component template API创建组件模版。

    Create an index template(data stream)

      若要使用你的组件模版来创建一个索引模板,需要指定:

      若要在Kibana中创建一个index template,那么打开主菜单然后跳转到Stack Management > Index Management。在Index Templates视图中,点击Create template。

      你也可以使用create index template API。包含data_stream object使得模版可以用于data streams。

    Create the data stream(data stream)

      Indxing requests将文档添加到data stream中。这些请求必须使用create类型中的op_type。文档中必须包含@timestamp字段。

      若要自动创建你的data stream,提交一个索引请求并指定目标data stream的名称。名称必须能匹配到索引模板中的index_patterns

      你也可以使用create data stream API手动创建时stream。这个stream的名称仍然必须能匹配到索引模板中的index_patterns

    Secure the data stream

      使用index privilege来控制对data stream的访问。保证data stream跟它的backing indices有相同的权限。

      Data stream privileges中的例子。

    Convert an index alias to a data stream

      在Elasticsearch7.9之前,你通常使用index alias with a write index来管理时序数据。Data stream替代了这个功能,更低的维护成本以及自动跟data tiers集成。

      若要将带有writer Index的索引别名转化为一个data stream,并且使用相同的名称,请使用migrate to data stream API。在传化期间,别名的索引变成了stream中的隐藏的backing indices。索引别名中的writer Index变成了stream的writer Index。这个stream依然要求一个能匹配的索引模板,并且这个索引模板能适用于data stream(模版中要有data_stream字段)。

    Get information about a data stream

      若要在Kibana中获取data stream的信息,打开主菜单然后跳转到Stack Management > Index Management,在Data Streams视图中,点击data stream的名称。

      你可以使用get data stream API

    Delete a data stream

      若要在kibana中删除一个data stream和它的backing indices。打开主菜单然后跳转到Stack Management > Index Management,在Data Streams视图中,点击trash icon。当你有这个data stream的delete_indexsecurity privilege 才能看到这个图标。

      你也可以使用delete data stream API实现

    Use a data stream

    (8.2)link

      set up a data stream之后,你可以:

    Add documents to a data stream

      若要添加一篇独立的文档,使用index API。支持Ingest pipeline

      你不能使用index API中的PUT/<target>/_doc/<_id>这种请求格式将一篇文档添加到data stream中。若要指定文档ID,使用PUT/<target>/_create/<_id>这种格式刷。只支持create类型中的op_type

      若要一次请求添加多篇文档,使用bulk API。只支持create选项。

    Search a data stream

      data stream支持以下查询:

    Get statistics for a data stream

      使用data stream stats API获取一个或多个data stream的统计数据。

    Manually roll over a data stream

      使用rollover API手动roll over一个data stream:

    Open closed backing indices

      你不能搜索一个closed backing index,即使是搜索对应的data stream也不行。你不能updatedelete关闭的索引中的文档。

      若要重新打开一个关闭的backing index,向对应的索引直接提交一个open index API request

      若要重新打开data stream中所有已关闭的索引,向这个stream提交一个open index API 请求:

    Reindex with a data stream

      使用reindex API从一个现有的索引、别名。或者data stream中拷贝文档到一个data stream中。因为data stream是append-only,因此reindex到一个data stream时必须使用create类型为op_type的值。reindex不能更新现有文档到一个data stream中。

    Update documents in a data stream by query

      使用update by query API将满足Query的文档更新到一个data stream中。

    Delete documents in a data stream by query

      使用delete by query API将满足Query的文档从data stream中删除。

    Update or delete documents in a backing index

      如果有需要的话,你可以通过往包含文档的backing index中发送请求来更新/删除data stream中的文档。你需要:

      若要获取这些信息,使用一个search request

      响应:

      第18行,包含文档的backing index   第19行,文档的Document ID   第20行,文档目前的序号   第21行,文档的primary term

      若要更新文档,使用index API并且携带合法的if_seq_noif_primary_term参数 :

      若要删除文档,使用delete API

      如要使用一个请求来删除/更新多篇文档,使用buli API中的deleteindex以及update动作。对于index,需要包含合法的if_seq_no and if_primary_term 参数。

    Change mappings and settings for a data stream

    (8.2)link

      每一个data steam有一个matching index template。模板中的mappings和index settings会应用到这个stream创建出来的新的backing index。也同时包括stream自动创建出来的的第一个backing index。

      在创建一个data stream之前,我们建议你考虑好模板中的mappings和settings。

      如果你随后需要更改某个data stream的mappings或settings,你有以下的选项:

    TIP:如果你的更改中包含对现有的field mappings或static index settings做更改,通常需要reindex来应用到data stream的backing index 中。如果你已经执行了reindex,你可以使用相同的过程来添加新的field mappings以及更改dynamic index settings。见Use reindex to change mappings or settings

    Add a new field mapping to a data stream

      若要向data stream中为一个新的字段添加一个mapping,按照下面的步骤执行:

    1. 更新data steam使用的index template。保证新的field mapping添加到这个stream以后创建的backing index中。

      例如,名为my-data-stream的data stream现在使用的是名为my-data-steram-template的模板。

      下面的create or update index template请求向模板中为新的字段message添加了一个mapping。

      第7行,为新的字段message添加一个mapping。

    1. 使用update mapping API添加新的字段的mapping到data stream中。默认情况下会添加到stream中现有的backing index中,包括write index。

      下面的更新mapping API请求将新的字段message添加到名为my-data-stream的data stream中。

      若只向stream中的write index添加mapping,在更新mapping API中添加请求参数write_index_onlytrue

      下面的更新mapping请求中将新的字段message的mapping只添加到write index中。没有添加到这个stream的其他backing index中。

    Change an existing field mapping in a data stream

      每一个mapping parameter的文档中都会告知是否可以使用update mapping API更新现有的字段。若要为现有的字段更新这些参数,按照下面的步骤执行:

    1. 更新data steam使用的index template。保证新的field mapping添加到这个stream以后创建的backing index中。

      例如,名为my-data-stream的data stream现在使用的是名为my-data-steram-template的模板。

      下面的create or update index template请求为host.ip修改了参数。字段的ignore_malformed的值设置为true

      第13行,修改host.ipignore_malformed的值为true

    1. 使用update mapping API添加新的字段的mapping到data stream中。默认情况下会添加到stream中现有的backing index中,包括write index。

      下面的update mapping API请求目标是my-data-stream。该请求将host.ip字段的ignore_malformed的值设置为true

      若只向stream中的write index添加mapping,在更新mapping API中添加请求参数write_index_onlytrue

      下面的更新mapping请求只对my-data-stream的write index中的host.ip字段变更。这个更改不会应用到stream的其他backing index。

      除了支持更新mapping参数,我们不建议更改现有字段的mapping或者类型,即使是在data stream匹配到的index template或者它的backing index中。更改现有字段的mapping会invalidate已经索引的数据。

      如果你需要修改现有字段的mapping,那么创建一个新的data stream然后reindex。见Use reindex to change mappings or settings

    Change a dynamic index setting for a data stream

      若要为data stream更改dynamic index template,按照下面的步骤执行:

    1. 更新data steam使用的index template。保证setting能应用到到这个stream以后创建的backing index中。

      例如,名为my-data-stream的data stream现在使用的是名为my-data-steram-template的模板。

      下面的create or update index template请求将模板的index.refresh_interval设置为30s(30秒)。

    第8行,将index.refresh_interval设置为30s

    1. 使用update mapping API更新data stream的index setting。默认情况下会添加到stream中现有的backing index中,包括write index。

      下面的更新index settings API请求为my-data-stream更新设置index.refresh_interval

    IMPORTANT:若要修改index.lifecycle.name,首先使用remove policy API移除现有的ILM策略。见Switch lifecycle policies

    Change a static index setting for a data stream

      只有在backing index创建时才能设置Static index settings。你不能使用update index settings API更新static index settings。

      若要将新的static setting应用到以后的backing index上,那么更新data steam使用的index template。更新之后会自动的应用到新创建的backing index上。

      例如,my-data-stream-template是一个my-data-stream使用的现有的index template。

      下面的create or update index template API请求向模板中添加了新的sort.fieldsort.order两个设置。

      第8行, 增加index setting sort.field   第9行,增加index setting sort.order

      如果需要的话,你可以roll over the data stream来马上将设置应用到data stream的write index上。应用到在rollover之后新添加到stream的数据上。然而不会影响data stream中现有的索引和现有的数据上。

      若要应用static settings changes到现有的backing index上,你必须创建一个新的data stream然后reindex。见Use reindex to change mappings or settings

    Use reindex to change mappings or settings

      你可以使用reindex修改data stream的mapping或settings。这么做通常是因为要对现有的字段的类型做变更或者要为backing index更新static index settings。

      若要reindex某个data stream。首先创建或者更新index template,这样才能包含你想要的修改后的mapping或settings。你随后就可以将现有的数据reindex到一个新的匹配到模板的data stream中。模板中变更的mapping和setting都会应用到添加到新的data stream中的每一篇文档和backing index。

      按照下面的步骤执行:

    1. 为新的data stream选择一个名称或者index pattern。这个新的data stream会包含你现有的stream中的数据。

      你可以使用 resolve index API检查下 名称或者pattern会不会匹配到现有的索引,aliases或者data stream。如果有,你应该考虑使用其他的名称或者pattern。

      下面的resolve index API请求会检查现有的索引,aliases或者data stream有没有以new-data-stream开头的。如果没有,index pattern new-data-stream* 可以用于创建新的data stream。

      API返回了下面的响应,指出现有的目标(existing target)中不匹配这个pattern。

    1. 创建或者更新一个index template。这个模板引应该包含你想要应用到新的data stream中的backing index的mappings和settings。

      这个index template必须满足requirements for a data stream template。他应该在index_patterns属性中同样包含之前选择的名称或者index patter。

    TIP:如果你只增加或者修改小部分东西,我们建议你通过拷贝现有的模板,根据你的需要进行修改,然后用于创建一个新的模板。

      例如,名为my-data-stream的data stream现在使用的是名为my-data-steram-template的模板。

      下面的create or update index template API 请求创建了一个新的index template,名为new-data-stream-templatenew-data-stream-templatemy-data-stream-template作为基准,作出了下面的改动:

      第10行,@timestamp字段的类型修改为date_nanos   第15行,增加index setting sort.field   第16行,增加index setting sort.order

    1. 使用create data stream API 手动创建新的data stream。data stream的名称必须匹配定义在index template中的index_patterns属性。

      我们不建议indexing new data to create this data stream。因为随后你将从现有的data stream中的旧数据reindex到这个data stream中。这会导致一个或者多个backing index会同时包含新旧数据。

    IMPORTANT:Mixing new and old data in a data stream 尽管新旧数据的混合是安全,但它会影响data retention。如果你要删除旧的索引,你可能会意外的删除一个同时包含新旧数据的索引。为了防止过早的(premature)数据丢失,你需要保留这样的backing index直到里面最新的数据可以被删除。

      下面的create data stream API请求的目标是new-data-stream,它会匹配到index template中的new-data-stream-template。因为现有的索引或data stream没有使用这个名称,所以这个请求会创建名为new-data-stream的data stream。

    1. 如果你不想在新的data stream中混合新旧数据,那么先暂停新文档的索引。尽管新旧数据的混合是安全,但它会影响data retention。如果你要删除旧的索引,你可能会意外的删除一个同时包含新旧数据的索引。为了防止过早的(premature)数据丢失,你需要保留这样的backing index直到里面最新的数据可以被删除。

    2. 如果你使用ILM来automate rollover,那么降低ILM的poll interval。这能保证在下一次rollover检查之前,当前的write index不会增长的过大。默认情况下,ILM每10分钟检查下rollover的条件。

      下面cluster update settings API 请求将indices.lifecycle.poll_interval的值降低为1m

    1. 使用op_type 中的create将你的数据reindex到新的data stream中

      如果你想要按照原来索引的顺序来对数据进行划分,你可以允许多个reindex请求。这些reindex请求可以使用独立的backing index作为输入源。你可以使用get data stream API查看backing index列表。

      例如,你计划将my-data-stream reindex到new-data-steram中,然而你想要为my-data-steram中的每一个backing index分别提交一个reindex请求,从最旧的backing index开始。这样就能保留原来索引的顺序。

      下面的get data stream API请求查看了my-data-stream的信息,包含了一个backing index的列表。

      响应中的indices包含了stream中当前的backing index。数组中第一个元素就是最旧的backing index的信息。

      第10行,my-data-steramindices数组中第一个条目中包含了这个stream中最旧的名为.ds-my-data-stream-2099.03.07-000001的backing index信息。

      下面的reindex API请求将.ds-my-data-stream-2099.03.07-000001中的文档拷贝到new-data-steam中。这个请求的op_typecreate

      你也可以在每次的请求中使用一个query对一个文档子集进行reindex。

      下面的reindex API请求将my-data-steram中的文档拷贝到new-data-stream中,请求中使用了range query,只reindex了上周的文档。注意的是这个请求的op_typecraete

    1. 如果你之前修改了ILM的poll interval,那么在reindex完成后改回到原来的值。防止master node上没必要的负载。

      下面的cluster update settings API请求将indices.lifecycle.poll_interval设置为默认值。

    1. 使用新的data stream恢复索引。在这个stream上的查询会使用新的数据以及reindex的数据。

    2. 一旦你验证完所有的reindex数据在新的data stream是可见的,你就可以安全的移除旧的stream。

      下面的delete data stream API 请求删除了my-data-steam,这个请求同样会删除它包含的所有的backing index和其他任何数据。

    Ingest pipelines

    (8.2)link

      Ingest pipelines能让你在索引之前对你的数据执行常用的转换(common transformation)。例如你可以使用pipeline来移除字段,从文本中提取值,并且丰富你的数据(enrich your data)。

      一个pipeline由一系列称为processors的可配置的任务组成。每一个processor顺序的运行,对incoming document做对应的更改。在运行完processor后,Elasticsearch将转换后的document添加到data stream或者索引中。

      你可以使用Kibana的Ingest Pipelines 功能或者ingest APIS来管理ingest pipeline。Elasticsearch将pipeline存储在cluster state中。

    Prerequisites(ingest pipeline)

    Create and manage pipelines

      在Kibana中,打开主菜单并且点击Stack Management > Ingest Pipelines。从下拉菜单中,你可以:

      若要创建一个pipeline,点击Create pipeline > New pipeline。可以查看Example: Parse logs这个示例教程。

    NOTE:New pipeline from CSV可以让你使用一个CSV来创建一个ingest pipeline,它将自定义的数据映射到Elastic Common Schema (ECS)。将你的数据映射到ECS使得数据更易于查询并且能让你从其他数据集中复用(reuse)可视化。见Map custom data to ECS

      你也可以使用ingest APIs来创建和管理pipeline。下面的create pipeline API请求中创建了一个包含2个set processor ,以及一个lowercase processor的pipeline。这三个processor会根据指定的顺序有序执行。

    Manage pipeline versions

      当你创建或者更新一个pipeline时,你可以指定一个可选的version的整数值。你可以使用version以及参数if_version来有条件的更新pipeline。一次成功的更新操作会提高pipeline的版本号。

      若要通过API不设置version,可以在替换或者更新pipeline时不指定versopm参数。

    Test a pipeline

      在生产中使用pipeline前,我们建议你先用样例文档(sample document)进行测试。当在Kibana中创建或者编辑了一个pipeline,点击Document tab页的Add documents,提供样例文档并点击Run the pipeline

      你也可以使用simulate pipeline API来测试pipeline。你可以在请求路径中指定一个配置好的pipeline。例如下面的请求中测试了my-pipeline

      或者你可以指定一个在请求body中指定pipeline和它的processor。

      这个API会返回转换后的文档:

    Add a pipeline to an indexing request

      在请求参数中使用pipeline对单篇或者多篇文档应用一个pipeline

      你也可以在update by query或者 reindex API中使用pipeline参数:

    Set a default pipeline

      使用索引设置index.default_pipeline来设置一个默认的pipeline。如果没有指定pipeline参数,Elasticsearch则会应用(apply )这个默认的pipeline。

    Pipelines for Beats

      如果为Elastic Beat添加一个ingest pipeline,可以在<BEAT_NAME>.yml中的output.elasticsearch下指定参数pipeline

    Pipelines for Fleet and Elastic Agent

      Fleet会为integration自动的添加ingest pipeline。Fleet会使用包含了pipeline index settingsindex templates来 应用pipeline。Elasticsearch会基于stream’s naming scheme匹配到这些模板到你的Fleet data streams中。

    WARNING:不要修改Fleet的ingest pipeline或者对你的Fleet integration使用自定义的pipeline。这么做会破坏你的Fleet data streams。

      Fleet不会为Custom logs integration提供一个ingest pipeline。你可以使用两种方法中的一种来为你的integration安全的指定一个pipeline:index template 或者一个custom configuration

    Option 1: Index template
    1. Create并且test你的ingest pipeline。将你的pipeline命名为logs-<dataset-name>-default。这样方便为你的integration进行追踪(track)。

    1. 创建一个index template,包含在index setting中设置的pipeline的index.default_pipelineindex.final_pipeline。保证模板中开启了data stream。这个模板的index pattern应该匹配logs-<dataset-name>-*

      你可以使用Kibana的Index Management功能来create index template API

      例如,下面的请求创建了一个模板来匹配logs-my_app-*。这个模板使用了component template,它包含了index.default_pipeline这个index setting。

    1. 在Fleet中增加或者编辑Custom logs integration时,点击Configure integration > Custom log file > Advanced options

    2. Dataset name中,指定你的数据集名称,Fleet会为integration添加新的数据并输出(resulting)logs-<dataset-name>-default data stream。

      例如,如果你的数据集名称是my_app,Fleet将新的数据添加到logs-my_app-default数据流。

    1. 使用rollover API来roll over你的数据流。这将保证Elasticsearch为integration将index template和pipeline设置应用到新的数据上。

    Option 2: Custom configuration
    1. Createtest你的ingest pipeline。默认命名pipeline的名称为logs-<dataset-name>-default。这使得让你的integration更易于追踪(track)。

      例如,下面的请求中为数据集my-app创建了一个pipeline。这个pipeline的名称是logs-my_app-default

    1. 当你在Fleet中添加或者编辑你的Custom logs integration。点击Configure integration > Custom log file > Advanced options

    2. Dataset name,指定你的数据集名称。Fleet将为integration添加新的数据并且输出到logs-<dataset-name>-default 数据流中。

      例如,如果你的数据集名称是my_app,Fleet将添加新的数据到logs-my_app-default 数据流中。

    1. Custom Configurations,在pipeline策略设置中指定你的pipeline。

    Elastic Agent standalone

      如果你用standalone方式启动Elastic Agent。你可以使用包含index.default_pipelineindex.final_pipeline index setting的index template来应用pipeline。或者你可以在elastic-agent.yml中指定pipeline策略。见Install standalone Elastic Agents

    Access source fields in a processor

      Processor对incoming document的source field有读写权限。若要在一个processor中访问一个field,使用其字段名。下面的process set访问了my-long-field

      你也可以前置(prepend)_source前缀。

      使用.(dot notation)来访问object fields。

    IMPORTANT:如果你的文档中包含flattened object,使用dot_expander先进行expand。其他的ingest processor不能访问flattened object。

      多个processor参数支持Mustache template snippets。为了能在template snippet中访问字段值,使用三个大括号(curly brackets)包住字段名。你可以使用template snippets动态的设置字段名。

    Access metadata fields in a processor

      Processor能通过名称访问下面的metadata filed:

      使用一个Mustache template snippet来访问metadata filed的值。例如{{{_routing}}}将retrieve一篇文档的 routing value。

      上面的set processor告诉ES如果字段address在索引的映射中还未定义,则使用名为geo_point的动态模板。如果在批量请求中已经定义了address字段的动态模板,这个处理器会覆盖它,但对批量请求中定义的其他动态模板没有影响。

    WARNING: 如果你automatically generate document id,你不能在processor中使用{{{_id}}},因为Elasticsearch在ingest之后才会自动分配_id值。

    Access ingest metadata in a processor

      Ingest processors可以使用key _ingest添加并且访问ingest metadata。

      不同于source和metadata field,Elasticsearch默认不会索引ingest metadata。Elasticsearch同样允许以_ingest开头的source fields,如果你的数据中包含了这种source fields,使用_source._ingest来访问它们。

      pipeline默认只创建名为_ingest.timestamp的ingest metadata字段。这个字段包含的是Elasticsearch收到文档索引请求时的timestamp。若要索引_ingest.timestamp或者其他ingest metadata字段,使用setprocessor。

    Handling pipeline failures

      pipeline的processor有序运行的。默认情况下,当其中一个processor允许失败或者遇到一个错误时,pipeline的处理就会停止下来。

      若要忽略某个processor的失败并且运行剩余的 processor。将ignore_failuretrue

      使用on_failure参数指定processor list,在一个processor失败后马上就运行它们。如果指定了on_failure,即使没有配置任何processor,Elasticsearch之后会运行pipeline中剩余的processor。

      on_failure中嵌套processor用于嵌套错误的处理

      你也可以为一个pipeline指定on_failure。如果某个没有设置on_failure的processor失败后,Elasticsearch会使用这个pipeline-level的参数作为一个fallback。Elasticsearch不会尝试运行pipeline中剩余的processor。

      pipeline失败后的额外信息可以在document的metadata filed中查看:on_failure_message, on_failure_processor_type, on_failure_processor_tag, and on_failure_pipeline。这些字段的信息只能在on_failure中才能被访问。

      下面的例子中使用了document的metadata fields,它包含了pipeline 失败后的信息:

    Conditionally run a processor

      每一个processor都支持可选的if条件,使用Painless script编写。如果提供了这个配置,processor只有在if条件为ture的情况下才会运行。

    IMPORTANT: if条件运行于Painless的ingest processor context。在if条件中,ctx的值是只读的。

      如果开启了集群设置script.painless.regex.enabled,你可以在if条件脚本中使用正则表达式。见Painless regular expressions了解支持的语法。

    TIP:如果可以的话,避免在if条件中使用复杂或者开销大的脚本。然而你可以使用Kibana consloe的 triple quote syntax来编写以及调试larger script。

      你可以使用stored script作为if条件中的脚本。

      Incoming document通常包含object field。如果一个processor script尝试访问一个字段,但是parent object不存在,Elasticsearch会返回一个NullPointerException。若要避免这些异常,使用null safe operators,例如?.,你的script就可以变的null safe。

      例如,ctx.network?.name.equalsIgnoreCase('Guest') 不是null safe。ctx.network?.name可能返回null,将脚本重写为'Guest'.equalsIgnoreCase(ctx.network?.name)的话就是null safe,因为Guest总是non-null。

      如果无法确保是null safe,就添加一个显示的null检查。

    Conditionally apply pipelines

      基于你的规则,在pipeline中使用if 条件来为你的文档应用pipeline。你可以在index template中使用这个pipeline作为default pipeline

    Get pipeline usage statistics

      使用node stats API来获取全局的以及per-pipeline的ingest 统计数据。来检测出哪些pipeline运行频次最多或者处理时间耗时最多。

    Example: Parse logs in the Common Log Format

    (8.2)link

      在这个教程中,你将使用ingest pipeline以及common log format,在索引前对服务器日志进行解析。在开始之前,先查看使用ingest pipeline前的prerequisite

      你要解析的日志如下所示:

      这些日志中包含了timestamp,IP address,以及user agent。你要让这三个信息在Elasticsearch有自己的字段,使得可以用于快速的查询以及可视化。你同样想知道这些请求的出处。

    1. 在Kibana中,打开主菜单并且点击Stack Management > Ingest Pipelines

    1. 点击Create pipeline > New pipeline

    2. 给这个pipeline提供一个名称以及描述

    3. 添加一个grok processor来解析日志消息。

      1. 点击Add a processor并且选择Grok processor类型

      2. 设置Fieldmessage并且Patterns设置为下面的grok pattern

      3. 点击Add保存processor

      4. 设置processor的描述信息为Extract fields from 'message'

    1. 为timestamp,IP address,和user agent增加processor。如下配置processor:

    Processor typeFieldAdditional optionsDescription
    Date@timestampFormats: dd/MMM/yyyy:HH:mm:ss ZFormat '@timestamp' as 'dd/MMM/yyyy:HH:mm:ss Z'
    GeoIPsource.ipTarget field: source.geoAdd 'source.geo' GeoIP data for 'source.ip'
    User agentuser_agent Extract fields from 'user_agent'

      如下所示:

      下面四个processor将会顺序执行:

      Grok > Date > GeoIP > User agent

      你也可以使用箭头图标重新排序

      或者,你可以点击Import processors链接然后定义如下的JSON:

    1. 若要测试pipeline,点击Add documents

    2. Document tab页,提供了一个文档文档样例用于测试:

    1. 点击Run the pipeline然后验证pipeline是否按预期运行

    2. 如果一切看着都可以,关闭面板,然后点击Create pipeline

      现在你已经准备就绪将日志数据索引到data stream中。

    1. 创建一个index template并开启data stream

    1. 使用你创建的pipeline索引文档。

    1. 若要进行校验,查询data stream来检索文档。下面的查询使用filter_path来只返回document source

      这个API返回如下:

    Enrich your data

    (8.2)link

      你可以在ingest过程中使用enrich processor将现有的索引中的数据添加到incoming document(传入文档)中。

      例如,你可以使用enrich processor来实现以下目标:

    How the enrich processor works

      大多数processor是自包含的(self-contained,也就是processor都是独立的,它们不依赖于外部数据或其他processor来执行其任务),仅改变incoming document中的现有数据。

      enrich processor则是添加新的数据到incoming document中并且要求一些特殊的组件:

    enrich policy

      使用一些配置选项将正确的enrich data添加到正确的incoming document中。

      一个enrich policy中包含以下内如:

      enrich policy可以被processor使用之前需要先被executed。执行后,enrich policy使用策略中source index中的enrich data来创建一个名为enrich index的streamlined(简化) system index。processor使用这个索引匹配以及丰富incoming document。

    source index

      source index中包含了你想要添加到incoming document中的enrich data。你可以跟Elasticsearch中其他常规索引(regular index,系统索引就不属于常规索引)一样创建并且管理这些索引 。你可以在一个enrich policy中指定多个source index。你可以在多个enrich policy中使用相同的source index。

    enrich Index

      一种特殊的系统索引跟一个特定的enrich policy关联

      直接通过文档(source index中的document)到文档(incoming document)的方式会很慢,并且属于资源密集型的操作。为了提高速度,enrich processor使用了enrich index。

      enrich index中包含了来自source index中的丰富数据,但是有一些特殊的属性来帮助简化(streamline)处理过程:

    Set up an enrich processor

    (8.2)link

      按照以下步骤创建一个enrich processor:

    1. Check the prerequisites.

    2. Add enrich data.

    3. Create an enrich policy.

    4. Execute the enrich policy.

    5. Add an enrich processor to an ingest pipeline.

    6. Ingest and enrich documents.

      一旦你设置好了一个enrich processor,你可以update your enrich dataupdate your enrich policies

    IMPORTANT:enrich processor会执行很多操作,可能会影响ingest Pipeline的速度 强烈建议在生产中部署进行测试和基准测试 我们不建议使用enrich processor处理实时数据。enrich processor最合适处理很少更改的数据

    Prerequisites(Set up an enrich processor)

      如果开启了Elasticsearch security features,你必须要有:

    Add enrich data

      首先,添加文档到一个或多个source index中。这些文档应该包含你最终想要添加到incoming document中的丰富数据

      你可以使用documentindex API,跟Elasticsearch中其他常规索引一样,管理source index。

      你也可以设置Beats,例如Filebeat,来自动的发送/索引你的source Index。见Getting started with Beats

    Create an enrich policy

      source index中添加完丰富数据后,然后使用create enrich policy API创建一个enrich policy。

    WARNING:enrich policy一旦创建结束,你不能更新/更改。见Update an enrich policy

    Execute the enrich policy

      enrich policy创建后,你可以使用execute enrich policy API执行该策略来创建enrich index

      enrich index中包含了策略中的source index。enrich index 的名称总是以.enrich-*开头,只读索引,并且force merged

    WARNING:enrich index应该只被enrich processor使用,避免使用enrich index用于其他目的。

    Add an enrich processor to an ingest pipeline

      一旦你拥有了source Index、enrich policy以及相关的enrich Index,你就可以设置一个包含带有策略的enrich processor的ingest pipeline。

      定义一个enrich processor,然后使用create or update pipeline API将它添加到一个ingest pipeline中。

      在定义enrich processor时,你必须至少包含下面的内容:

      你可以使用max_matches选项设置一个incoming document可以匹配的丰富文档的数量。如果设置为默认值的1。那么target_field字段变成json object否则就是json array。

      Enrich了解全部的可配置的选项。

      你也可以在ingest pipeline中添加其他的processor

    Ingest and enrich documents

      你现在可以使用ingest pipeline丰富并索引文档了。

      在生产中使用pipeline之前,我们建议你先写入一些测试文档然后使用get API验证enrich data是否被正确的添加。

    Update an enrich index

      创建之后,你不能向enrich Index中更新或者添加文档。而是更新你的source index然后再次execute enrich policy。这样会从更新后的source Index中创建新的enrich index。之前的enrich index会使用一个maintenance job稍后删除。默认是每15分钟。

      如果有必要的话,你可以使用ingest pipelinereindex或者update已经提取的文档(ingested document)。

    Update an enrich policy

      enrich policy一旦创建完毕,你就不能更新或者修改,不过你可以:

    Enrich components

      enrich coordinator是一个组件,负责管理和执行每个ingest node上所需的搜索以丰富文档。它将所有pipeline中所有enrich processor的搜索合并成批量multi-searches

      enrich policy executor是一个组件,负责管理所有enrich policies的执行。当执行一个enrich policies时,此组件将创建一个新的enrich index并移除之前的enrich index。enrich policies的执行由elected master node管理。这些策略的执行发生在不同的节点上。

    Node Settings

      enrich processor有enrich coordinator和enrich policy executor相关的节点设置。

      enrich coordinator支持下面的节点设置:

    enrich.cache_size

      用于enriching documents的搜索的最大缓存数量。默认值为1000。整个集群的所有enrich processors共用一个缓存。此设置确定该缓存的大小。

    enrich.coordinator_proxy.max_concurrent_requests

      enriching documents时运行的最大并发multi-search requests请求数量。默认值为8。

    enrich.coordinator_proxy.max_lookups_per_request

      enriching documents时在一个multi-search requests请求中包含的最大搜索数量。默认值为128。

      enrich policy executor支持下面的节点设置:

    enrich.fetch_size

      将source index reindex到enrich index时的最大批量大小。默认值为10000。

    enrich.max_force_merge_attempts

      允许在enrich index上进行的最大force merge 尝试次数。默认值为3。

    enrich.cleanup_period

      Elasticsearch检查是否可以删除未使用的enrich index的频率。默认值为15分钟。

    enrich.max_concurrent_policy_executions

      最大并发执行的enrich policy数量。默认值为50。

    Example: Enrich your data based on geolocation

    (8.2)link

      geo_match类型的enrich policies基于一个geographic location,使用gep_shape query,将匹配到的丰富数据添加到incoming document中。

      下面的例子中创建了一个geo_match类型的enrich policy,基于坐标集(a set of coordinates)将postal code的信息添加到incoming document中。然后将geo_match类型的enrich policy添加到一个ingest pipeline中。

      使用create index API创建一个source index,索引中至少包含一个geo_shape字段。

      使用index API将enrich data添加到source index中

      使用create enrich policy API创建一个geo_match类型的enrich policy。这个策略包含:

      使用create or update pipeline API创建一个ingest pipeline。在这个pipeline中,添加一个包含以下内容的enrich processor

      使用ingest pipeline索引一篇文档。incoming document中应该包含enrich processor中指定的field

      若要验证enrich processor匹配到的、以及追加的字段的信息。可以使用get API查看索引后的文档:

      该接口返回以下响应:

    Example: Enrich your data based on exact values

    (8.2)link

      匹配enrich policies,将匹配到的enrich data基于精确值添加到incoming document中,比如email地址或者ID,使用的是term query

      下面的例子中创建了一个match类型的enrich policy,基于一个email地址将用户名(user name)和联系方式(contact)添加到incoming document中。然后将这个match policy添加到ingest pipeline的processor中。

      使用create index APIindex API创建一个source index。

      下面的index API创建了一个source index,然后向这个索引中索引了一个新的文档。

      使用create enrich policy API创建一个match类型的enrich policy。这个策略包含:

      使用execute enrich policy API为这个策略创建一个enrich Index。

      使用create or update pipeline API创建一个ingest pipeline。在这个pipeline中,添加一个包含以下内容的enrich processor

      使用ingest pipeline索引一篇文档。incoming document中应该包含enrich processor中指定的field

      若要验证enrich processor匹配到的、以及追加的字段的信息。可以使用get API查看索引后的文档:

      该接口返回以下响应:

    Example: Enrich your data by matching a value to a range

    (8.2)link

      一个range类型的enrich policy使用一个term query匹配incoming document中的数值、日期或者IP地址类型的字段,使用匹配到的字段值去enrich Index中执行同一个字段的范围查询。不支持range到range的匹配。

      下面的例子中创建了一个range类型的enrich policy,该策略基于IP地址向incoming document中添加描述性网络名称(descriptive network name)和负责部门(responsible department)。然后,它将enrich policy添加到ingest pipeline的一个processor中。

      使用create index API以及合适的mapping创建一个source index。

      下面的请求index API的请求向source Index中添加了一篇新文档。

      使用create enrich policy API创建一个range类型的enrich policy。这个策略必须包含:

      由于我们计划基于IP地址来丰富文档,因此策略中的match_field必须是ip_range字段

      使用execute enrich policy API 创建一个enrich Index。

      使用create or update pipeline API创建一个ingest pipeline。在这个pipeline中,添加一个包含以下内容的enrich processor

      使用ingest pipeline索引一篇文档。incoming document中应该包含enrich processor中指定的field

      若要验证enrich processor匹配到的、以及追加的字段的信息。可以使用get API查看索引后的文档:

      该接口返回以下响应:

    Ingest processor reference

    link

    Append processor

    link

      如果待追加的字段存在,并且是字段值是数组类型,那么追加一个或多个值到现有的数组中。如果待追加的字段存在,并且字段值是标量(scalar)类型,那么将其转化为数组类型,然后追加到数组中。如果待追加的字段不存在,那么创建一个数组类型的字段值并且追加到这个数组中。可以追加单个值或者数组。

    Bytes processor

    link

      将易于理解(human readable)的字节值(比如 1kb)转化为其字节值(比如 1024)。如果字段是string数组,那么数组中所有元素都会被转化。

      支持的易于理解的单位有bkbmbgbtbpb。不区分大小写。如果有不支持的格式或者转化后的值超过2^63则会发生错误。

    Circle processor

    link

      将圆形定义转化为近似的正多边形。

    Community ID processor

    link

      根据社区ID(Community ID Specification)规范计算网络流数据的社区ID。您可以使用社区ID来关联与单个流相关的网络事件。

      社区ID处理器默认从相关的Elastic Common Schema(ECS)字段读取网络流数据。如果您使用ECS,则无需配置。

    Convert processor

    link

      将当前被提取的文档中的字段转化为不同的类型。比如将string转化为Integer。如果字段值是个数组,那么所有数组元素都被转化。

      支持的类型有:integer, long, float, double, string, boolean, ip以及auto

      转化为boolean时,如果字符串的值为true(不区分大小)则转化为true,如果是false则转化为false。如果是其他值则抛出异常。

      如果包含了一个有效的IPv4或者IPv6地址可以转化为ip类型,并且使用IP的mapping类型进行索引。

      如果使用了auto,那么会将字符串类型的字段值转化为最接近的non-string、non-IP类型。比如,字段值为true时会转化为boolean类型。注意的转化为float的优先级高于double。比如242.15会自动转化为float类型。如果无法正确的自动转化,这个processor仍然算作处理成功并且字段值保持原样。这样,target_field将被更新为转化前的值。

    CSV processor

    link

      从文档中的单个文本字段提取CSV行的字段。CSV中的任何空字段都将被跳过。

    Date processor

    link

      解析字段中的日期。然后使用日期或者时间戳作为文档的timestamp。默认情况下,date processor将解析出的日期作为一个名为@timestamp的新字段。你可以通过target_field指定一个不同的字段名。可以在同一个date processor中定义多个format。它们将在处理过程中按照定义中的顺序依次用于尝试解析日期。

    Date index name processor

    link

      这个processor的目的是使用date math index name support.,基于文档中日期或者时间字段,将文档指向正确的基于时间的索引。

      processor根据提供的索引名称前缀、正在处理的文档中的日期或时间戳字段以及提供的日期舍入,设置带有日期数学索引名称表达式的_index元数据字段。

      首先processor获取处理中的文档中的日期或者时间戳字段的信息。然后(可选)将字段中的值根据format进行解析。然后,将此日期、提供的索引名称前缀和提供的日期舍入格式化为一个日期数学索引名称表达式(date math index name expression)。此处也可以可选地指定日期格式化,以指定日期应如何格式化为日期数学索引名称表达式。

    Dissect processor

    link

      Grok processor类型,dissect同样从文档中单个文本字段中提取出结构化的字段。跟Grok processor不同的是,它不使用Regular Expressions。这使得dissect的语法更简单并且有些情况下性能快于Grok processor

      Dissect根据定义的模式去匹配某个单文本的字段。

      比如有下面的模式:

      将会匹配下面的一行日志:

      将会生成下面的字段:

      dissect pattern由字符串中部分被丢弃的值定义,比如上面的例子中,第一个被丢弃的部分就是单个空格。Dissect会从头开始找到这个空格,然后将这个空前的所有值设置为clientio。后面dissect又匹配了[以及],然后将[]中所有的值设置为@timestamp。特别注意要丢弃的字符串部分将帮助构建成功的解析模式。

      成功的匹配要求模式中的所有key都必须有一个value。如果模式中定义的任何%{keyname}没有值,则会抛出异常,并且可能通过on_failure指令进行处理。可以使用空键%{}named skip key 匹配值,但从最终文档中排除该值。所有匹配的值都表示为字符串数据类型。可以使用convert processor将其转换为预期的数据类型。

      Dissect还支持可以改变dissect默认行为的key modifiers。例如,你可以指示dissect忽略某些字段、追加字段、跳过填充等。更多信息请见下文

    Dot expander processor

    (8.2)link

      将用点.表示的字段名扩展成一个对象字段。这个processor使得可以让点字段(field with dot)能在pipeline中被其他processor访问。否则这些点字段无法被任何processor访问。

    Table 14. Dot Expand Options

      该processor会将下面的内容:

      扩展为:

      如果bar已经是foo的子字段,那么processor合并这两个值。如果这个字段属于标量字段(scalar field,即只包含单个值的字段),那么就将这两个字段值用数组表示

      比如有以下的文档:

      会被dot_expander扩展为:

      如果将override选项设置为true

      这种情况下就进行覆盖:

      field选项可以设置为*将top-level的字段都进行扩展:

      该processor会将下面这篇文档:

      变成:

      如果leaf field上一层的字段跟现有的字段冲突,那么需要先重命名。

      如果有以下的文档:

      foo需要在dot_expander processor处理之前进行重命名。这样foo.bar才能将bar扩展到foo下:

      这么做的理由是ingest pipeline不知道如何将一个标量字段(scalar field)的字段转化为一个对象字段。

    Drop processor

    link

      丢弃文档并且不会抛出任何的错误。如果基于某些条件不索引某些文档时,这个processor就非常有用。

    Enrich processor

    (8.2)link

      enrich processor可以将一个索引中的数据丰富到文档中。见enrich data了解更多关于设置信息。

    Table 16. Enrich Options

    Fail processor

    link

      抛出一个异常,当你预期某个pipeline会失败并且将指定的消息回复给请求方。

    Fingerprint processor

    link

      计算文档的hash值,你可以使用这个hash值用于content fingerprinting

    Foreach processor

    link

      对数组或者对象中的每一个元素运行ingest processor。

      所有的ingest processor可以运行在数组或对象的院上。然而如果元素的数量未知,用相同的方法逐一处理它们可能会变得繁琐。

      foreach processor可以让你指定一个包含数组或者对象的字段,以及一个processor运行在字段中的每一个元素上。

    GeoIP processor

    link

      

    Grok processor

    link

      

    Gsub processor

    link

      对一个string类型的字段根据一个正则表达式以及替换值进行转化。如果该字段是数组类型,则数组中所有的元素会被转化。如果遇到了non-string的字段,则抛出一个异常。

    HTML strip processor

    link

      移除字段中的HTML标签。如果该字段是数组类型的,将移除数组中所有元素的HTML tags。

    Inference processor

    link

      在Pipeline中被提取的数据上使用预训练的数据框架分析模型或为自然语言处理任务部署的模型进行推断。

    Join processor

    link

      将数组中每一个元素通过分隔符组成单个字符串。如果该字段不是数组类型则会抛出异常。

    JSON processor

    link

      将一个JSON字符串转化为一个JSON对象。

    KV processor

    link

      这个processor用于自动解析foo-bar这类日志(或者特定时间类型)类型。

      例如,如果log message中包含ip=1.2.3.4 error=REFUSED,你可以通过以下配置自动解析出这些字段:

    Lowercase processor

    link

      将字符串转化为小写。如果该字段是数组类型,则数组中所有的元素会被转化。

    Network direction processor

    link

      

    Pipeline processor

    link

      执行另一个pipeline(在pipeline中使用其他pipeline)。

    Registered domain processor

    link

      

    Remove processor

    link

      移除现有的字段。如果待移除的字段不存在,则抛出一个异常。

    Rename processor

    link

      重命名一个现有的字段。如果该字段不存在或者新的名字已被使用,则抛出一个异常。

    Script processor

    (8.2)link

      在incoming document上运行脚本,可以是内联脚本,也可以是存储的脚本(stored script)。脚本运行在ingest的上下文中。

      该processor使用script cache来避免处理每一个文档时重复编译脚本内容。若要提高性能,确保在生产中在使用script processor时,script cache有一个合适的大小。

    Table 35. Script options
    Access source fields

      script processor将每一篇JSON格式的文档解析为map集合,列表,原始类型(primitives)。若要使用Painless 脚本访问这些字段,使用map access operatorctx['my-field']。你也可以使用简化的ctx.<my-field>语法。

    NOTE:script processor不支持ctx['_source']['my-field']ctx._source.<my-field>语法

      下面的processor使用了Painless脚本从evf字段中提取出tags字段。

      这个processor会生成:

    Access metadata fields

      你也可以使用这个processor访问元数据字段(metadata field),下面的processor使用Painless脚本设置了incoming document的_index的值。

      processor将文档的_index字段从generic-index修改为fr-catalog

    Set processor

    (8.2)link

      设置某个字段为指定的值。如果字段已经存在,那么字段值会被替换。

    Table 36. Set Options

      这个processor也可以从一个字段拷贝字段值到另一个字段。例如:

      响应:

      包含复杂类型的值比如数组跟对象,也可以使用copy_from从一个字段拷贝到另一个字段:

      响应:

    Set security user processor

    link

      

    Sort processor

    link

      对数组中的元素进行升序或降序排序。数字的同类(Homogeneous)数组将按数字顺序排序,而字符串数组或字符串+数字的异类(heterogeneous)数组将按字典顺序排序。当字段不是数组时抛出错误。

    Split processor

    link

      使用一个分隔符对字段值进行分割,写入到一个数组中。只能对string类型的字段处理。

    Trim processor

    link

      移除字段值首尾的空格。。。。。如果是数值类型的字段,则数组中的所有元素都会被处理

    Uppercase processor

    link

      将字符串转化为大写。如果该字段是数组类型,则数组的元素都会被处理。

    URL decode processor

    link

      将编码后的URL解码为字符串。如果该字段是数组类型,则数组的元素都会被处理。

    URI parts processor

    link

      URI部分处理器用于解析统一资源标识符(URI)字符串,并将其组成部分提取为一个对象。这个URI对象包含了URI的多个属性,如域(domain)、路径(path)、片段(fragment)、端口(port)、查询参数(query)、方案(scheme)、用户信息(user info)、用户名(username)和密码(password)。

    User agent processor

    link

      

    Aliases

    (8.2)link

      Alias是一组数据流(data stream)或者索引的别名(secondary name)。大多数的Elasticsearch API接受用一个alias来代替一个数据流或者索引。

      你可以在任何时间修改alias对应的数据流或者索引。如果你使用alias在你的应用中进行查询,你可以在不需要修改你代码并且不需要停机(downtime)的情况下reindex data。

    Alias types

      目前有两种类型的alias:

      alias不能同时指向数据流和索引。你不能添加一个数据流的backing index作为index alias。

    Add an alias

      使用 aliases APIadd动作对一个现有的数据流或者索引起个别名。如果别名不存在,那么这个请求就会进行创建。

      API的indexindices支持通配符(*)。如果通配符模板同时匹配到数据流或者索引则会返回错误。

    Remove an alias

      使用alias API的remove动作来移除别名。

    Multiple actions

      你可以使用alias API在一个原子操作中执行多个动作。

      例如,别名logs指向了一个数据流。下面的请求将交换别名(swap alias)。在这次交换期间,这个logs别名没有downtime(还可以用于查询)并且不会在同一时间指向多个流。

    Add an alias at index creation

      你可以在创建索引或者数据流时使用component或者index template为它们添加别名。

      你也可以在create index API请求中指定索引别名:

    View aliases

      可以使用不带参数的get alias API来获取你的集群的别名列表。

      _alias前指定数据流或者索引来查看它们的别名。

      _alias后指定别名来查看对应的数据量或者索引。

    Write index(Alias)

      你可以为别名使用is_write_index来指定一个用于写入的索引或者数据流。Elasticsearch会将对这个别名的任何写请求路由到这个索引或者数据流。

      如果一个别名指向多个索引或者多个数据流,并且没有设置is_write_index,这次写请求会被reject。如果一个别名指向一个索引并且没有设置is_write_index,那么这个索引默认作为write index。数据流的别名不会自动的设置为write data stream,及时这个别名只指向了一个数据流。

    TIP:我们建议使用数据流来存储append-only的时序数据(time series data)。如果你经常会更新或者删除现有的时序数据,转而使用index alias来指定write index。见Manage time series data without data streams

    Filter an alias

      filter选项使用 Query DSL来限制通过别名能查询到的文档。

    Routing

      使用routing选项将对别名发起的请求route到指定的分片。这样可以让你利用shard cache来加速查询。数据流不支持这个选项。

      使用index_routingsearch_routing给索引跟查询指定不同的路由值。在指定后,这些选项会用覆盖routing的值并执行它们各自的操作。

    Search your data

    link

    Filter search results

    (8.2)link

      你可以使用两种方式对查询结果进行过滤:

      你也可以在post filter后使用对命中的结果recore来提高相关性以及重排结果(reorder filter)。

    Post filter

      当你使用post_filter过滤查询结果时,会在聚合完成后对查询命中过滤。post filter不会对聚合结果有影响。

      比如说,你正在出售衬衫(shirt),并且有以下的属性:

      比如某个用户指定了两个filter:

      color:red以及brand:gucci。你只想要在查询结果中显示品牌为Gucci的红色衬衫。通常你会使用bool query实现:

      然而,你还想要使用faceted navigation显示一些可以让用户点击的选项,可能你有一个样式(model)字段允许用户限制他们的查询结果为T恤衫(t-shirts)以及正装衬衫(dress-shirts)。

      那么可以用terms aggregation实现:

      第13行,返回Gucci的最流行红色衬衫的样式。

      但是你可能想要告诉用户其他颜色的Gucci衬衫。如果你在color字段上添加一个terms aggregation,你只会获取到红色的衬衫,因为你的请求只会返回红色的Gucci衬衫。

      你可能想要在聚合中包含所有颜色的衬衫,然后只对查询结果应用colors过滤。那么你就可以使用post_filter

      第6行,请求现在会找到所有颜色的Gucci衬衫   第12行,对colors的聚合返回Gucci的所有颜色   第16、20行,color_red聚合将对models的聚合限制在红色的Gucci衬衫中   第25行,最终, post_filter从查询命中里移除了红色以外的结果。

    Rescore filtered search results

      rescore可以对query以及post_filter返回的Top文档使用一个通常有额外开销的次级算法(secondary algorithm)重新排序来提高精确度。而不是将这个次级算法应用到索引中所有文档上。

      rescore 请求在每一个分片上执行,然后通过节点重新排序来处理所有的查询请求。

      目前,rescore API只有一种实现方式:查询重评分器(query rescorer),它使用查询来微调评分。将来,可能会提供其他类型的重评分器,例如成对重评分器(pair-wise rescorer)。

    NOTE:如果在rescore query中提供了显式sort(除了降序的_score外),则会抛出错误。

    NOTE:当向用户展示分页时,你在浏览每一页时不应更改window_size(通过传递不同的from值),因为这可能会改变顶部命中,导致用户在翻页时结果出现令人困惑的变化。

    Query rescorer

      Query rescorer在query以及post_filter返回的Top-K的结果上执行一个次级的query。可以通过参数window_size控制每一个分片上的计算的文档数量,默认值为10

      默认情况下,original query和rescore query的得分会线性组合以产生每个文档的最终_score。original query和rescore query的相对重要性可以分别通过query_weightrescore_query_weight来控制,这两个参数默认值都是1。

      分数组合可以由score_mode控制:

    Score ModeDescription
    totalAdd the original score and the rescore query score. The default.
    multiplyMultiply the original score by the rescore query score. Useful for function query rescores.
    avgAverage the original score and the rescore query score.
    maxTake the max of original score and the rescore query score.
    minTake the min of the original score and the rescore query score.
    Multiple rescores

      也可以有序的执行多个rescore:

      第一个rescore基于query 的结果排序,第二个rescore根据第一个rescores排序后的结果再排序。第二个rescore可以看到第一个rescore的排序结果因此可以在第一个rescore中使用大的窗口然后再第二个rescore中使用较小的窗口。

    Highlighting

    link

      高亮器允许你从搜索结果中的一个或多个字段中获取高亮片段,以便可以向用户展示查询匹配的位置。当请求高亮显示时,响应中会为每个搜索命中包含一个额外的高亮元素,其中包含高亮字段和高亮片段(Highlighted fragments)。

    NOTE:高亮器(highlighter)在提取待高亮的术语时,不会考虑查询的布尔逻辑。因此,对于复杂的布尔查询(如嵌套布尔查询、使用minimum_should_match等),可能会高亮显示与查询不匹配的文档部分。

      高亮要求字段的真实内容。如果这个字段没有存储(即mapping中参数store设置为false),那么就会加载_source的内容,并从_source中提取出这个字段的内容。

      例如使用默认的高亮器从content字段中获取高亮信息,那么需要再请求体中包含一个Highlight对象,在对象中指定content字段:

      Elasticsearch支持三种高亮器:unifiedplainfvh(fast vector highlighter)。你可以为每一个字段指定不同的高亮器。

    Unified highlighter

      Unified高亮器使用Lucene Unified Highlighter,它将文本分解成句子,并使用BM25算法为每个句子打分,就像它们是语料库中的文档一样。此外,它还支持准确的短语和多项(模糊、前缀、正则)高亮显示。这是默认的高亮器。

    Plain highlighter

      plain高亮器使用标准的Lucene高亮器。它尝试在理解词语重要性和短语查询中的词语位置标准方面,反映查询匹配逻辑。   plain高亮器最适合在单个字段中高亮显示简单的查询匹配。为了准确反映查询逻辑,它创建一个小型内存索引,并通过Lucene的查询执行计划再次运行原始查询标准,以获取当前文档的底层匹配信息。这一过程需要为每个字段和每个需要高亮的文档重复。如果想在许多文档中高亮显示许多字段,并且查询复杂,我们推荐使用Unified高亮器处理postingterm_vector字段。

    Fast vector highlighter

      fvh高亮器使用Lucene快速向量高亮器,适用于在mapping中将term_vector设置为with_positions_offsets的字段。

    WARNING:fvh高亮器不支持span query,如果需要span query支持,可以尝试其他高亮器,如unified高亮器。

    Offsets strategy

      若要从被查询的term中找到有意义的查询片段,高亮器需要知道在原始文本中每一个word中字符的开始跟结束偏移信息,这些偏移可以从以下方式获取:

    WARNING:Plain Highlight对于大型文本可能要求更多的内存和处理时间。因此文本的字符数量会被限制为1000000来应对这个问题。可以通过index.highlight.max_analyzed_offset为特定的索引修改这个限制

    Highlighting settings

      高亮设置可以为全局(global-level)并且覆盖域层(field-level)的设置。

    Highlighting examples

    Override global settings

      你可以指定全局设置并且可以为不同的字段选择性的覆盖这些设置、

    Specify a highlight query

      你可以指定一个highlight_query,在高亮时可以添加额外的高亮。例如下面的例子中在highlight_query中同时包含了search query以及rescore query。如果没有highlight_query,则只会考虑search query中的条件。

    Set highlighter type

      type字段可以强制指定一个高亮器的类型。可选值有unifiedplainfvh。下面的例子使用了plain高亮器:

    Configure highlighting tags

      Elasticsearch默认使用<em></em>指定高亮范围。可以通过pre_tagspost_tags设置。

      当使用fast vector 高亮器时,你可以指定额外的标签以及"importance" is ordered。

      你可以使用内置的styled标签策略(tag scheme):

    Highlight on source

      强制高亮器基于_soure对字段进行高亮,即使字段没有单独存储。默认为false

    Highlight in all fields

      默认只会请求中匹配到的字段进行高亮。将require_field_match设置为false则对所有字段高亮。

    Combine matches on multiple fields

    WARNING:只能在fvh高亮器中支持

      

    Explicitly order highlighted fields

      

    Control highlighted fragments

      

    Highlight using the postings list

      

    Specify a fragmenter for the plain highlighter

      

    How highlighters work internally

      

    An example of the work of the unified highlighter

      

    Long-running searches

    (8.2)link

      Elasticsearch通常允许你搜索大量的数据。有这样的场景,当一个查询在很多分片上查询,可能查询了非常大的数据集或者多个remote cluster,对于这种查询可能无法在毫秒级别返回。当你需要执行long-running查询时,同步等待结果返回不是一种好的方式。异步查询(async search)可以让你提交一个查询请求,然后异步执行。可以监控请求的过程,随后去获取结果。你也可以在这个查询全部完成前让部分结果可见并且返回。

      你可以使用 submit async search API提交一个异步查询请求。get async search API允许你监控一个异步查询请求的过程并且获取结果。可以通过delete async search API删除一个正在进行中的异步查询。

    (8.2)link

      documents and indices中说到当在Elasticsearch中存储一篇文档时,文档在被索引后可以接近实时(near real-time search,简称NRT)(1秒内)的进行搜索。如何定义NRT?

      Elasticsearch依赖的Java库-Lucene中介绍了按段搜索(per-segment search)的概念。一个段类似一个倒排索引(inverted index),但是index在Lucene中的概念是"段的集合+ commit point"。 在一次提交(commit)后,一个新的段添加到commit point并且清空缓存(buffer is cleared)。

      位于Elasticsearch和磁盘中间的是文件系统缓存(filesystem cache)。内存中的索引缓存(FIgure 1)会写入到一个新的段中(Figure 2)。新的段首先写入到文件系统缓存中(开销小)然后随后写入到磁盘中(开销大)。然而当文档还在缓存中时,它就可以被打开并且像其他文件读取。

    Figure 1. Lucene中新的文档内存中的索引缓存

      Lucene允许新的段用于写入或者打开,使得这些段包含的段对搜索可见,并且不需要完整的提交(full commit)。相较于提交到磁盘这是一种轻量的操作,可以在不降低性能的情况下频繁的执行这些操作。

    Figure 2. 缓存的内容写入到了一个段中,并且这个段对搜索可见,但是这个段还没有提交

      在Elasticsearch中,写入并打开一个新段成为refresh。一次refresh操作使得自上一次refresh后在索引上的所有操作对查询可见。你可以通过下面的方式来控制refresh:

      默认情况下,Elasticsearch每一秒周期性的执行refresh,但是只在最新30s内收到一次或者多次查询的索引上才会执行。这就是为什么说Elasticsearch是近实时搜索:文档的变化不会马上对搜索可见,但是在这个时间(timeframe)内变成可见。

    Paginate search results

    link

      默认情况下,查询只会返回10条匹配的结果。你可以通过search API中的from + size参数来通过翻页方式查询一个较大的数据集。from参数描述了结果集的一个起始位置,size参数描述了从from位置开始的size条结果。这两个参数的组合定义了一个页面的结果集。

      避免使用from + size来分页太深或一次请求太多结果。查询通常会扫描多个分片,每一个分片会将查询对应的命中的结果以及from之前的结果都读取到内存中。所以深度分页或者获取一个很大的结果集这些操作会极大地提高内存跟CPU的使用量,导致节点性能降低或者失败。

      默认情况下,你不能通过from + size的方式来获得超过10000条的结果集。通过index.max_result_window这个索引配置进行安全的限制。

      如果你需要通过分页查询来获得超过10000的结果集,那么可以换成search_after参数来实现。

    WARNING:Elasticsearch使用Lucene的内部文档id作为tie-breakers。相同数据的分片之间,这些内部文档id可能完全不同。在进行分页搜索时,您可能偶尔会看到具有相同排序值的文档排序不一致

    Search after

      你可以使用search_after参数和上一页的sort values来获取下一页的结果。

      使用search_after要求每次的查询都要有相同的query以及sort value。如果在多次的上述请求时发生了refresh,结果的顺序可能会改变,导致页面之间的结果不一致,为了避免这种情况,可以创建一个point in time (PIT) 来保存搜索的当前索引状态。

      这个接口返回一个PIT ID。

      提交一次查询并带上sort参数来获得第一页的结果,如果使用PIT,在pit.id参数中指定PIT ID并且请求参数中移除目标data stream或者index。

    IMPORTANT:所有的PIT请求会带一个名为_shard_doc用于排序的内置的tiebreaker字段,tiebreaker字段也可以显示指定。如果你不能使用PIT,建议在sort中增加一个tiebreaker字段。每篇文档中应该有一个tiebreaker字段并且字段值是唯一的。如果文档中没有tiebreaker字段,分页结果中可能有丢失或者重复的数据。

    NOTE:当排序顺序是_shard_doc并且不需要命中总数时,Search after请求会得到优化并且查询更快。如果你想遍历所有的结果并且不关心排序,那么这是一个最高效的选项。

    IMPORTANT:如果sort字段在一些目标data stream或者index中是date类型但是在其他目标data stream或者index是date_nanos类型,那么使用numeric_type参数和format参数为sort字段指定一个date format,将sort字段的值转化为相同格式的值(single resolution)。否则Elasticsearch 不会在每个请求中正确解释(interpret) search after 参数。

      第10行,这次查询对应的PIT ID。   第13行,_shard_doc上显示指定一个升序的tiebreak字段,为这次查询返回有序的结果。

      查询响应中包含了一个数组,数组中的值是用于排序这条结果的sort的字段值(排序值)。如果你使用了PIT,数组中最后一个排序值是一个tiebreaker。在使用PIT时,名为_shard_doc的 tiebreaker值会在每一次查询请求中自动的添加。_shard_doc的值是 PIT 中的分片索引和 Lucene 的内部 doc ID的组合值。你也可以在查询请求中显示指定tiebreaker实现自定义排序:

      第10行,这次查询对应的PIT ID。   第13行,_shard_doc上显示指定一个降序的tiebreak字段,为这次查询返回有序的结果。

      第2行,Updated id for the point in time   第16行,最后一个结果对应的两个排序值   第18行,pid_id中每一篇文档的唯一的tiebreaker值

      为了获得下一页的结果,使用上一次查询中最后一个结果对应的排序值(包含tiebreaker)作为search_after的参数。如果使用了一个PIT,那么在pit.id参数中使用最新的PIT ID。这次查询的querysort参数必须不能被更改,from参数必须是0(默认值)或者-1

      第10行,上一次查询中返回的PIT ID   第16行,上一次查询结果中最后一个结果的排序值   第20行,关闭追踪命中的总数来加速分页查询

      你可以重复上述操作来获得额外的分页结果。如果使用了PIT,你可以在每一次查询请求中使用keep_alive参数来增加PIT的保留周期(retention period)。

      当你结束查询时,你应该删除PIT。

    Scroll search results

    IMPORTANT:我们不再建议使用scroll API进行深度分页查询。如果你需要保留索引状态(index state)同时分页查询10000+的结果,使用PIT的search_after

      尽管一次查询请求返回的是单页(single page)的结果,scroll API 可以用于在单次查询请求中检索大量的结果(甚至是所有的结果),就像在传统数据库上使用游标一样。

      Scrolling不是用来(intend for)实时用户请求(real time user request),而是用于处理大量的数据。 比如说为了将一个data stream或index的内容重新索引到具有不同配置的新的data stream或索引中。

    Client support for scrolling and reindexing Some of the officially supported clients provide helpers to assist with scrolled searches and reindexing: Perl   See Search::Elasticsearch::Client::5_0::Bulk and Search::Elasticsearch::Client::5_0::Scroll Python   See elasticsearch.helpers.* JavaScript   See client.helpers.*

    NOTE:从scroll查询返回的数据反应了data stream或者index在最初的执行查询时的状态,就像是快照一样。接下来文档发生的变化(增加,更新或者删除)只有在下次新的scroll查询中生效。

      为了能使用scrolling,最初的查询请求应该在query string中指定scroll参数,这个参数用来告诉Elasticsearch保留"search context"的时间(见Keeping the search context alive), 比如?scroll=1m

      上述的查询结果中会包含一个_scroll_id,这个值需要传给scroll API用于检索下一批数据。

      第1行,可以使用GETPOST并且URL中不应该包含index的名称----索引的名称在最开始的查询中指定   第3行,scroll参数告诉Elasticsearch接着保留1分钟的search context   第4行,scroll_id参数

      size参数允许你配置每次返回的结果数量上限。每次调用scroll API会返回下一批数据直到没有数据返回,比如hits数组为空。

    IMPORTANT:最初的查询请求以及每一个接下来的scroll请求都会返回_scroll_id_scroll_id可能会发生变化,但是不总是每次都会变化。无论如何,应该使用最新收到的_scroll_id

    NOTE:如果请求中指定了聚合(aggregation),只有最开始的查询响应中会包含聚合结果。

    NOTE:当排序字段是_doc时使用Scroll查询会得到优化。如果你想要遍历所有的结果而不关心结果顺序,这是最高效的选项:

    Keeping the search context alive

      scroll查询将返回最开始的查询请求匹配的所有文档。它会忽略随后对这些文档的更改。scroll_id定义了一个search context来保留一切(keep track of everything)使得Elasticsearch能正确的返回文档。这个search context在最开始的请求中创建并且通过随后的请求来保留这个search context

      scroll参数(传给search请求以及每一个scroll请求)告诉Elasticsearch保留search context的时间。该值(比如1m,见 Time units)不需要设置的太大来处理所有的数据--而是只需要足够长的时间来处理上一次的结果集。每一次scroll查询(使用scroll参数)设置一个新的过期时间。如果某次scroll请求没有传递scroll参数,那么释放search context回作为这次scroll请求的一部分。

      通常来说,后台的合并程序会把较小的段合并为一个新的,更大的段来优化索引。一旦这些较小的段不再被使用就会被删除。在执行scroll查询时,合并既然会继续,但是scroll查询会阻止旧的段被删除,因为这些段正在被scroll查询使用。

    TIP:保留旧的段意味着需要更多的磁盘空间以及文件句柄(file handle)。保证你已经将你的节点配置了足够的空闲的文件句柄。见File Descriptors

      另外, 如果一个段中包含了被删除或者更新的文档,那么search context会在最开始的查询请求的那个时间点保持追踪(keep track)段中的每一篇文档是否都live 。如果你在一个索引上有很多open scroll并且这个索引还不断的删除或者更新文档,那么你要保证你的节点有足够的堆空间。

    NOTE:为了防止出现打开太多的scroll而产生问题,在超过一定的限制后。用户不允许再open scroll。默认情况下,open scroll的最大值是500.可以通过search.max_open_scroll_context来修改这个限制。

       你可以通过note stats API来检查打开了多少个search context

    Clear scroll

      search context会在scroll超时后自动的移除。然而保留scroll打开需要一定的开销,如previous section中讨论的。所以一旦不需要scroll查询后 就可以通过clear-scrollAPI来显示的关闭:

      可以通过数组方式删除多个scroll IDs:

      所有的search context都可以通过_all参数清除:

      scroll_id可以作为一个query string参数或者在请求body中。多个scroll IDs使用逗号分隔:

    Sliced scroll

      

    (8.2)link

      默认情况下,查询响应中的每一个命中的结果中都会包含文档的_source,它是一个整个JSON object,即被索引的文档。下面有两个推荐的方法在一次查询请求中获取指定的(selected)的字段:

      你可以同时使用这些方法,fields这个方法更好些因为它能同时参考(consult)文档数据和index mappings。在某些情况下,你可能想要other methods来获取数据。

    The fields option

      若要在查询响应中获取指定的字段,则使用fields参数。相较于引用_sourcefields参数提供了几个有点,特别是,使用fields参数可以:

      Other mapping options are also respected。包括ignore_aboveignore_malformednull_value

      fields选项返回的值的方式跟Elasticsearch索引它们的方式是匹配的。对于standard fields,fields选项在_source中找到值,然后解析并使用mappings进行format。

    Retrieve specific fields

      下面的查询请求使用fields参数获取user.idhttp.response下所有的字段、@timestamp这些字段的值。

      使用object notation,你可以传递一个format自定义时间或者地理空间的值的格式。

      第10行,可以是完整的字段名或者是通配符pattern。   第13行,使用format参数对字段值进行format

    NOTE:默认情况下,当请求的fields选项使用了像*的通配符pattern,例如_id或者_index这些文档元数据是不会返回的。然而,当显示的使用这些字段名时,_id_routing_ignored_index_version这些元数据字段才返回。

    Response always returns an array

      fields响应中返回每一个字段的数组值,即使有些字段在_source是单值。这是因为Elasticsearch没有专门的数组类型,并且任何字段都有可能存在多值。fields参数同样不能保证数组中的值有一定的顺序。见arrays的mapping文档了解更多背景。

      响应中的fields块中包含一个平铺的list。因为fields参数不会获取整个object,只会返回leaf fields。

    Retrieve nested fields

      使用fields返回nested fields的响应中其他普通的object fields都少许不同。在普通的objectfields 中的leaf values的返回内容是平铺的列表(flat list),而nested field返回的内容也是一个平铺的列表,列表中是分组为一个个object,每一个object是nested fields的一个字段并且字段值也是一个数组。多层的nested fields按照这个规则嵌套下去。

      下面的mapping中,user是一个nested field,索引下面的文档并获取userfield中所有的字段:

      下面的响应中,对firstlast名称进行了分组而不是平铺出来。

      nested field会根据它们的nested path进行分组,不受获取时使用的pattern的影响。例如,如果你在上面的例子中只查询user.first

      响应中只返回user的first name,但是仍然是上面的例子的结构:

      然而,如果fields中的目标只填写user字段,那不会返回任何值因为没法匹配任何一个leaf fields。

    Retrieve unmapped fields

      默认情况下,fields参数只返回mapped fields的值,然而,Elasticsearch允许存储_source中的字段,并且这些字段是unmapped。 例如设置dynamic field mapping的值为false或者使用一个object字段并且设置enabledfalse。这些选项使得关闭解析并且不索引object的内容。

      若要在object中获取_source中的unmapped字段,那么在fields中 使用include_unmapped选项:

      第4行,关闭所有的mapping   第24行,包含匹配这个field pattern的unmapped fields

      这个响应会包含session_data.object.*路径中的字段值,即使这些字段是unmapped。user.id同样是unmapped,但是没有出现在响应中因为没有为那个field pattern设置include_unmapped

    Ignored field values

      响应中的fields块中只返回合法索引的值。如果你的查询请求要求的字段值忽略某些值,这些值是malformed或者太大,这些字段值会在另一个ignored_field_values块中返回。

      在这个例子中,我们索引了一篇文档,文档中的一个值被限制了长度导致没有添加到索引中,所以在查询请求中分开的显示:

      第5行,这个字段有长度限制   第13行,这个文档有一个字段值超过了长度限制所以没有被索引

      在这个响应中,在ignored_field_values路径中包含了被限制了长度的字段值。这个字段值是从文档的原始JSON source中获取出来的并且就是原始的数据,不会被formatted或者任何方式处理。不同于成功写入到索引的字段,它们的字段值在fields块中返回。

    The _source option

      你可以使用_source参数选择返回source中的哪些字段。这种称为source filtering

      下面的search API请求设置了请求body参数_sourcefalse。故响应中没有包括document source。

      若要返回一部分source fields,可以在_source参数中指定 一个通配符(*)pattern。下面的search API请求只返回obj字段和它的properties。

      你也可以在_source中指定一个通配符pattern数组。下面的search API请求只返回obj1obj2字段和它们的properties。

      为了更好的控制,你可以在_source中指定一个object,里面包含includesexcludes patterns。

      如果使用了includes属性,只返回匹配它里面的pattern的字段。你可以使excludes从这个子集中进一步排除。

      如果没有指定includes属性,所有的document source都会返回,除了匹配excludes中的pattern的字段。

      下面的search API请求返回obj1obj2的字段,但是排除所有child field为description的字段。

    Other methods of retrieving data

      通常来说使用field是比较好的,除非你必须一定要载入stored或者docvalue_fields

      文档的_source在Lucene中作为单独一个字段存储的。这种结构意味着需要加载整个_source对象,即使你只需要里面的部分内容。为了避免这种情况,你可以尝试其他办法加载字段:

      Elasticsearch总是尝试从_source中加载字段值。这种方式跟source filtering是一样的实现方式,即Elasticsearch需要加载并解析整个_source进行检索,即使只需要获取某一个字段。

    Doc value fields

      你可以使用docvalue_fields参数在查询响应中返回一个或多个dov values的字段。

      Doc Values跟_source一样都会存储,但以列式存储的数据结构存放,用于排序和聚合。由于每一个字段都是各自独立存储,Elasticsearch只需要读取请求中指定的字段,并能避免加载整个文档_source

      Doc values are stored for supported fields by default。然而,doc value不支持text或者text_annotated字段。

      下面的查询请求使用docvalue_fields参数获取user.id,所有以http.response开头的以及@timestamp的doc value。

      第10行,同时支持完整的字段名和通配符pattern   第13行,使用object notation,你可以传递一个format参数指定自定义的format应用到doc value上。Date fields支持date formatNumeric fields支持DecimalFormat pattern。其他的字段不支持format参数。

    TIP:你不可以为nested object使用docvalue_fields参数 来获取doc value。如果你指定了一个nested object,则返回一个空的数组。若要访问nested fields,使用inner_hits参数中的docvalue_fields属性

    Stored fields

      可以使用mapping 参数store来存储字段值。你可以使用stored_fields参数在响应中包含存储字段的字段值。

    WARNING:stored_fields用于那些在mapping中显示使用stroed的字段,默认是不启动并且通常不建议启用。建议使用source fitlering从原始数据(也就是_source)中获取选择的字段。

      运行在查询中选择指定文档中的存储字段。

      *可以用来获取文档中所有的存储字段。

      空的数组只能返回_id_type这两个存储字段,例如:

      想要查询的字段如果没有存储(mapping参数store设置为false),这些字段则会忽略。

      从文档中获取的存储字段总是以数组形式返回。相反,像_routing这样的元数据字段从不以数组形式返回。

      此外,只有leaf field可以通过stored_fields选项返回。如果指定了一个对象字段,它将被忽略。

    NOTE:单独使用stored_fields无法加载嵌套对象中的字段——如果一个字段在其路径中包含一个嵌套对象,那么该存储字段将不会返回任何数据。要访问嵌套字段,必须在inner_hits块内使用stored_fields。

    Disable stored fields

      若要完全禁用存储字段(以及元数据字段)可以使用:_none_

    NOTE:如果使用了_none,_srouceversion也不能使用

    Script fields

      你可以使用script_fields参数获取一个script evaluation(基于不同的字段),例如:

      Script fields可以应用在非存储字段上(比如上面的price)并且允许返回自定义的值(脚本中计算出的值)

      Script fields同样可以访问实际的_source文档并且通过params['_source']提取指定的内容。例子:

      注意的是,请求中的关键字_source用来导出类似json的模型(json-like model)

      理解doc['my_field'].valueparams['_source']['my_field']之间的区别很重要。首先,使用doc关键字,将导致该字段的术语被加载到内存中(缓存),这将导致执行速度更快,但消耗更多内存。此外,doc[...]表示法仅允许简单值字段(你不能从中返回一个json对象)并且只对non-analyzed或single term的字段有意义。然而,如果可能的话,使用doc仍然是访问文档内容的推荐方式,因为每次使用时都必须加载和解析_source。使用_source是非常慢的。

    Retrieve inner hits

    link

    Search across clusters

    (8.2)link

      Cross-cluster search能让你对一个或者多个集群运行单个查询请求。例如你可以使用CCS(Cross-cluster Search)对存储在不同的数据中心的集群上的日志数据进行过滤和分析。

    Supported APIs

      下面的APIs支持CCS:

    Prerequisites

    Cross-cluster search examples

    Remote cluster setup

      下面的cluster update settings API请求添加了三个remote集群:cluster_onecluster_twocluster_three

    Search a single remote cluster

      在查询请求中,指定remote cluster上的data stream以及索引:<remote_cluster_name>:<target>

      下面的search API请求在名为cluster_one的单个remote cluster上查询索引my-index-000001

      API返回下面的响应:

      第23行,查询响应中的_index参数包含了remote cluster的名称

    Search multiple remote clusters

      下面的search API请求在三个集群上查询索引my-index-000001

      API返回下面的响应:

      第24行,这篇文档的_index参数没有集群的名称,说明这个文档来自本地集群   第41行,这篇文档来自cluster_one   第58行,这篇文档来自cluster_two

    Optional remote clusters

      默认情况下,如果请求中的某个remote cluster返回了一个错误或者不可用(unavailable),那么CCS就会失败。使用cluster setting skip_unavailable标记特定的remote cluster在CCS时是可选的。

      如果skip_unavailabletrue。CCS将:

      下面的cluster update settings API请求将cluster_twoskip_unavailable设置为true

      如果cluster_two在CCS期间失去连接或者不可用。Elasticsearch不会在最终的结果中包含在那个集群中匹配到的文档。

    How cross-cluster search handles network delays

      由于CCS涉及到发送请求到remote cluster上,任何的网络延迟都会影响查询速度。为了避免慢查询(slow search),CCS提供了两个的方法来处理网络延迟:

    Minimize network roundtrips

      下面是在你minimize network roundtrips后,CCS的工作方式。

    1. 你发送一个CCS请求到你的本地集群。集群中的coordinating node接收并解析这个请求。

    1. coordinating node向每一个集群发送一个查询请求,包括本地的集群。每一个集群各自独立的执行这个查询请求,将它们自己的cluster-level的设置应用到这个请求上。

    1. 每一个remote cluster将其查询结果返回到coordinating node。

    1. 从每一个集群收集完结果后,coordinating node将最终的结果到CCS的响应中。

    Don’t minimize network roundtrips

      下面是没有minimize network roundtrips后,CCS的工作方式。

    1. 你发送一个CCS请求到你的本地集群。集群中的coordinating node接收并解析这个请求。

    1. coordinating node向每一个remote cluster发送一个search shards API请求。

    1. 每一个remote cluster将其响应发送回coordinating node。这个响应中包含了CCS将会执行索引和分片信息。

    1. coordinating node发送一个查询请求到每一个分片,包括它所在的集群。每一个分片各自独立的执行查询请求。

    WARNING:当没有最小化网络往返时,这个查询的执行过程就像是所有的数据都在coordinating node的集群中。我们建议更新cluster-level的设置来限制查询,例如action.search.shard_count.limitpre_filter_shard_sizemax_concurrent_shard_requests。如果限制值太低,查询可能被reject。

    1. 每一个分片将其查询结果返回到coordinating node。

    1. 从每一个集群收集完结果后,coordinating node将最终的结果到CCS的响应中。

    Supported cross-cluster search configurations

      在8.0+中,Elastic支持本地从本地集群到remote cluster的查询的版本:

      Elastic同样支持从本地集群(某个major版本中的最新的minor版本)到remote cluster(下一个major版本中的所有minor版本)的查询。例如,7.17版本的本地集群可以从8.x的任意版本的集群上查询。

     Remote cluster version     
    Local cluster version6.87.1–7.167.178.08.18.2
    6.8×××
    7.1–7.16×××
    7.17
    8.0××
    8.1×××
    8.2××××

    IMPORTANT:对于EQL search API,本地和远程集群必须使用相同的Elasticsearch版本。

      例如,8.0的本地集群可以查询7.17和所有8.x的集群。然而,8.0的本地集群不能查询7.16或者6.8的集群。

      所有集群都有的功能才能被支持。在某个remote cluster使用某个不具备的功能会导致undefined behavior。

      CCS中使用了不支持的配置可能可以正常工作。然而,Elastic没有测试过这种查询,不能保证其行为能正确工作。

    Ensure cross-cluster search support

      保证支持CCS最简单的方式就是每一个集群保持相同的版本。如果需要维护不同版本的集群,你可以:

    Cross-cluster search during an upgrade

      在本地集群上执行rolling upgrade时仍然可以查询remote cluster。然而,本地集群中的coordinating node的"upgrade from"和"upgrade to"的版本必须和remote cluster上的gateway node兼容。

    WARNING:Running multiple versions of Elasticsearch in the same cluster beyond the duration of an upgrade is not supported。

      Upgrading Elasticsearch了解更多升级信息。

    Search multiple data streams and indices

    (8.2)link

      若要搜索多个data stream和索引,则使用逗号隔开添加到search API请求路径上。

      下面的请求查询索引my-index-000001my-index-000002

      你也可以使用一个index pattern查询多个data stream和索引。

      下面的请求目标是my-index-*的index pattern。这个请求会查询集群中名称以my-index-开头的data stream或者索引。

      若要查询集群中所有的data stream和索引,将请求参数的目标改为_all或者*

      下面的请求都是相同的,会查询集群中所有的data stream和index。

    Index boost

      在查询多个索引索引时,你可以使用indices_boost参数boost一个或多个索引的结果。适用于从某些索引返回的结果比其他索引中的结果重要的场景。

    NOTE:你不能对data stream使用indices_boost

      也可以用于aliases和index pattern:

      如果匹配到了多个,则使用先匹配到的对应的boost。例如,如果某个索引属于alias1同时匹配了my-index* pattern,那么 boost value为1.4

    Search shard routing

    (8.2)link

      为了应对硬件故障以及提高搜索能力(search capacity),Elasticsearch会在多个节点上存储索引数据对应的多个副本分片。当允许一个查询请求时,Elasticsearch会选择一个包含索引数据副本的节点并且将这个查询请求转发到那个节点上的分片上。这个处理过程就是众所周知的search shard routing或者routing

    Adaptive replica selection

      默认情况下,Elasticsearch使用adaptive replica selection来路由查询请求。这个方法使用shard allocation awareness和下面的条件来选择有资格的节点(eligible node):

      Adaptive replica selection被设计为用于降低查询延迟。你可以使用cluster settings API设置cluster.routing.use_adaptive_replica_selectionfalse来关闭它。如果关闭了adaptive replica selection,Elasticsearch使用轮询(round-robin)方式来路由查询请求,这可能会导致查询缓慢。

    Set a preference

      默认情况下,adaptive replica selection从所有的eligible node和分片中进行选择。然而你可能只想从一个本地节点(local node)获取数据或者基于硬件因素将查询路由到指定的节点。或者你想要将重复的查询(repeated searcher)发送到同一个分片,使得可以利用cache。

      若要为查询请求限制eligible node和分片集合,你可以使用查询的API's的参数preference

      例如,下面的查询请求中使用了preference_local的参数来查询索引my-index-000001。它将查询限制到本地节点(local node)。如果local node没有这个索引数据的分片,这个请求会使用adaptive replica selection去其他eligible node,这个节点作为一个fallback。

      你也可以使用preference参数并基于提供的值将查询路由到指定的分片。如果集群状态(cluster state)和选择的分片没有发生变更,查询会使用相同的preference的值以相同的顺序被路由到相同的分片。

      我们建议使用一个独一无二的preference值,例如用户的名称或者web session ID。这个值不能以_开头。

    TIP:你可以使用这个方法为频繁的以及资源密集(resource-intensive)的查询使用缓存结果。如果分片没有发生变更,使用相同preference值的重复的查询会从相同的shard request cache中检索到结果。对于时序用例,比如说日志,旧的索引中的数据几乎不会更新,就可以从这个cache中直接返回结果

      下面的查询请求使用了值为my-custom-shard-stringpreference去索引my-index-000001上进行查询。

    NOTE:如果集群状态和选择的分片发生了变更,相同的preference的查询可能不会以相同的顺序路由到相同的分片。导致这个的原因很多,包括分片重新分配(shard relocation)以及分片错误(shard failure)。节点也会reject一个查询请求,Elasticsearch会将它路由到其他的节点。

    Use a routing value

      当你索引一篇文档时,你可以指定一个可选的routing value,这样会将这篇文档索引到一个指定的分片上。

      例如,下面的请求使用my-routing-value来路由一篇文档。

      你可以在查询的API's参数routing中使用相同的路由值。这能保证在相同的分片上查询。

      你可以指定多个用逗号分隔的路由值:

    Search concurrency and parallelism

      默认情况下,Elasticsearch不会基于请求命中的分片数量来reject这个查询请求。然而命中大量的分片会带来大量的CPU和内存的使用。

    TIP:为了防止索引有大量的分片,见Avoid oversharding

      你可以使用名为query parameter的查询参数(query parameter)来控制一个查询请求在一个节点上并发查询的分片数量。 这可以防止某个请求过度消耗(overloading)某个集群。这个查询参数的默认最大值是5

      你也可以使用集群设置action.search.shard_count.limit来限制查询命中的分片数量,在命中太多分片后就reject这个请求。你可以使用cluster settings API来配置action.search.shard_count.limit

    Search templates

    (8.2)link

      search template一种查询模版并且保存在Elasticsearch中-,你可以使用不同的变量覆盖search template中的变量。

      如果你使用Elasticsearch作为查询后端(search backend),你可以把用户在搜索框的输入作为search template的变量。这使得你不需要将Elasticsearch的查询语法暴露给用户而执行查询。

      如果你使用Elasticsearch用于自定义的应用,search template可以让你在不更改你的应用代码的情况下修改你的查询(DSL)。

    Create a search template

      可以使用create stored script API创建或者更新一个search template。

      请求中的source支持search API的请求body中相同的参数。source同样支持Mustache变量,通常用双括号包裹:{{my-var}}。当你允许某个template search,Elasticsearch会使用params中的值替换这些变量。

      search template必须使用mustache语法。

      下面的请求创建了一个idmy-search-template的search template。

      Elasticsearch存储search template作为集群状态中的Mustache scripts。Elasticsearch在template script context中编译search template。设置中限制或者关闭script同样会影响search template。

    Validate a search template

      使用render search template API以及不同的params测试一个模板。

      替换变量后(rendered),template输出一个search request body

      你也可以使用API来测试inline template。

      可以使用search template API运行一个search template。你可以在每一次的请求中指定不同的params

      响应中返回的属性跟search API的响应是一样的。

    Run multiple templated searches

      可以使用multi search template API在单个请求中运行多个template search。相较于多个独立的请求,这种方式的请求的开销更小并且速度更快。

    Get search templates

      可以使用get stored script API获取search template。

      可以使用cluster state API获取所有的search template列表以及其他存储的脚本。

    Delete a search template

      可以使用delete stored script API删除一个search template。

    Set default values

      使用下面的语法为变量设置一个默认值:

      如果某个template search中没有在params中指定一个值,那么查询会使用默认值。例如,下面的template中为fromsize设置了默认值。

    URL encode strings

      使用{{#url}}功能进行URL编码。

      填充后的值如下:

    Concatenate values

      使用{{#join}}功能对数组里面的值用逗号拼接。例如下面的例子中拼接了两个email地址。

      填充后的值如下:

      你也可以自定义指定一个分隔符。

      填充后的值如下:

    Convert to JSON

      使用{{#toJson}}功能将变量值用JSON表示。

      例如,下面的template中使用{{#toJson}}传递一个数组。为了保证请求体式一个合法的JSON,source的值需要为一个string format。

      填充后的值如下:

      你也可以{{#toJson}}传递object。

      填充后的值如下:

      你也可以传递一个object数组。

      填充后的值如下:

    Use conditions

      使用下面的语法来根据条件进行创建:

      如果条件变量为true。Elasticsearch会展示内容。例如,如果year_scope的值为true,下面的template search中会选择过去一年的数据。

      填充后的值如下:

      如果year_scopefalse。这个template search会查询任何时间段的数据。

      填充后的值如下:

      可以使用下面的语法创建if-else条件:

      例如,如果year_scopetrue,则获取过去一年的数据,否则获取过去一天的数据。

    Sort search results

    (8.2)link

      允许你添加一个或者多个字段用于排序。每一个排序即可以正序也可以是倒序。排序规则按字段定义,也可以指定一些特殊的字段名例如_score意味着根据打分排序,_doc意味着根据索引顺序排序。

      假设有以下的index mapping:

    NOTE:_doc不是很实用,但用于排序时,却是效率最高的。所以如果你不关心返回的文档顺序,那你应该使用_doc排序。特别有助于scrolling

    Sort Values

      查询响应中包含每一个文档的排序值(sort value)。可以使用format参数为datedate_nanos字段的sort value指定date format。下面的查询返回中,post_date字段的字段值作为排序值,并且使用format格式为:strict_date_optional_time_nanos

    Sort Order

      order选项有两个值可选:

      根据_score排序时,默认的order选项为desc,而根据其他字段排序时,order选项默认值为asc

    Sort mode option

      Elasticsearch支持根据数组或者多值字段(multi-valued field)排序。mode选项控制了选择数组中哪一个值用于作为文档的排序值。mode选项有以下的值可选:

      sort order为asc的默认sort mode为min,即选择最小值。sort order为desc的默认sort mode为max,即选择最大值。

    Sort mode example usage

      下面的例子中,price字段是一个多值字段。在这个例子中命中的结果会按照asc以及price中所有值的平均值排序。

    Sorting numeric fields

      对于数值类型的字段也是可以通过numeric_typ选项进行类型转换。该选项可选的值为:["double", "long", "date", "date_nanos"],使得可以跨多个data stream或者索引对不同mapping类型的相同字段名进行排序。

      如果有以下两个索引:

      由于field这个字段在两个索引中分别是doublelong类型,所以默认情况下不能在同时查询这两个索引时根据这个字段进行排序。然而你可以使用numeric_type选项强制转化为同一个类型使得可以用于排序:

      在上面的例子中,索引index_long中的值转化为一个double使得兼容索引index_double中的值。当然也可以将一个floating值转化为long,but note that in this case floating points are replaced by the largest value that is less than or equal (greater than or equal if the value is negative) to the argument and is equal to a mathematical integer。

      同样的也可以用于datedate_nanos字段。如果有以下两个索引:

      两个索引中field的值使用不同的格式(different resolution)存储使得date类型的值总是排在date_nanos之后(asc)。在使用了numeric_typ选项后,就可以将它们设置为单个格式(single resolution)。如果设置为date,那么date_nanos的值会被转化为millisecond,如果设置为date_nanos,那么date会被转化为nanoseconds。

    WARNING:为了防止出现溢出,对于1970年之前和2262年之后的date_nanos的转化不能表示为long。

    Sorting within nested objects.

      Elasticsearch同样支持根据object内部的字段或者更深层的字段进行排序。根据nested filed排序时使用的nested排序选项可以有以下的属性:

    NOTE:如果排序中定义了一个nested field但是没有nested 的上下文(见下面的例子),Elasticsearch会抛出错误异常

    Nested sorting examples

      在下面的例子中,offer是一个nested类型,需要指定path,否则Elasticsearch不知道选择哪一层的nested中的排序值进行排序

      在下面的例子中,parentchildnested字段。需要在每一层指定nested.path,否则Elasticsearch不知道选择哪一层的nested中的排序值进行排序。

      nested sorting 同样支持根据脚本或者地理位置排序。

    Missing Values

      missing参数指的是如何对哪些缺少排序字段的文档进行排序:missing的值可以设置为_last_first或者自定义的值(该值会被用于排序)。默认值为_last

      例如:

    NOTE:如果nested inner object没有匹配到nested.filter,则视为缺少排序字段,即使用missing value。

    Ignoring Unmapped Fields

      默认情况下,如果某个字段没有对应的mapping,那么根据这个字段排序的请求会失败。unmapped_type选项允许你忽略没有对应mapping的字段,不根据它们进行排序。这个参数的值可以用于determine what sort values to emit。下面是使用这个参数的例子:

      如果所有的索引都没有price对应的mapping,Elasticsearch将认为存在long类型的mapping(防止报错),并且所有的文档都没有这个字段的字段值。

    Geo Distance Sorting

      允许根据_geo_distance排序。下面的例子中,假设pin.locationgeo_point类型的字段:

      如果计算距离。可以是arc(默认值)或者plane(计算更快,但是长距离以及靠近两极时的计算的结果不精确)

      如果有多个字段值时选择哪一个用于排序。默认情况下,当按照ascending order时会采用最短距离,按照descending order时采用最长距离。支持的可选值有minmaxmedina以及avg

      计算排序时使用的单位。默认值为m(米)。

      unmapped filed是否视为missing value。设置为true后跟上文中的Ignoring Unmapped Fields是一样的处理方式,设置为false后,unmapped filed会导致查询失败。

    NOTE:geo distance sorting不支持配置missing value:当文档中没有字段值用于计算距离时总是被认为距离为Infinity

      下面提供的坐标格式都是支持的:

    Lat Lon as Properties
    Lat Lon as String

      latlon的格式。

    Geohash
    Lat Lon as Array

      [lon, lat]的格式,注意的时这里lon/lat的前后顺序是为了符合GeoJSON

    Multiple reference points

      可以使用数组提供多个geo points,数组元素的格式可以是上文中提到的所有的格式,例如

      最终一篇文档的距离是文档中所有点的 min/max/avg(取决于mode的值)到排序请求中给出的点的距离。

    Script Based Sorting

      允许基于自定义的脚本进行排序,见下面的例子:

    Track Scores

      当根据某个字段排序后,就不会对文档打分。设置track_scores为true后才会进行打分计算。

    Memory Considerations

      排序时,用于排序的字段会加载到内存中。这意味着每一个分片都应该有足够的内存来处理它们。对于用于排序的string类型,它不应该设置为analyzed / tokenized。对于数值类型,如果可以的话,建议显示的(explicit)设置为narrower types(例如shortingeger以及float)。

    Query DSL

    link

    Allow expensive queries(Query DSL)

    Query and filter context

    (8.2)link

    Relevance scores

      默认情况下,Elasticsearch根据相关性分数(relevance score)对匹配到的结果进行排序。相关性分数衡量每个文档与查询的匹配程度。

      relevance score是一个正浮点数,在search API_score元数据字段中返回。_score越高,跟文档越相关。每一个查询类型计算相关性分数是不同的,分数的计算也取决于query clause是在query还是filter的上下文(context)中运行。

    Query context

      在query context中,一个query clause会回答这个问题:文档跟这个query clause的匹配程度是多少?除了决定是否匹配文档,另外query clause还要计算一个相关性分数,这个分数在_source元数据字段中返回。

      query context通过参数query生效,见search API中的query参数。

    Filter context

      在filter context中,一个query clause会回答这个问题:文档跟这个query clause匹配吗?答案是简单的匹配或者不匹配。不会计算分数。filter context最常用于过滤结构化的数据:

      常用的filters会被Elasticsearch自动缓存来提高性能。

      filter context通过参数filter生效,比如bool query中的filter或者must_not参数,以及 constan_score query和 filter聚合中的参数filter

    Example of query and filter contexts

      下面的例子中是一个同时使用了query context和filter context的search API。这个查询将会匹配满足下面所有条件的文档:

      第3行,参数query说明使用了query context   第4行,boolmust在query context中用来描述文档的匹配程度   第8行,参数filter说明使用了filter context,termquery在filter context中用来过滤掉不匹配的文档,并且不会影响匹配的文档的分数。

    WARNING:query context中计算出的分数是一个精确的浮点型数值。只有24位的精度。超过有效数字精度的分数将被转换为浮点数,但会丢失精度。

    TIP:用于影响匹配的文档的分数(文档的匹配程度)的query clause放在query context中,其他的query clause放在filter context中。

    Compound queries

    (8.2)link

      复合查询(compound query)中封装了符合的或者叶子查询(compound or leaf query)。

      这组复合查询中有这些query:

    Boolean query

    (8.2)link

      Boolean query是一种组合了其他query用于匹配文档的query。bool query对应(map)Lucene中的BooleanQuery。通过一个或者多个boolean clause来构建Boolean query,这些clause各自有一个occur的类型。类型的种类包括:

    OccurDescription
    must匹配到的文档必须满足这个clause(query),同时这个query会对文档进行打分
    filter匹配到的文档必须满足这个clause(query),但是跟must不同的是,不会计算这个query对文档的打分值。Filter clause在filter context下执行,意味着忽略打分值并且这个query可以被缓存(Lucene中会缓存满足这个query的文档号)
    should在匹配到的文档中,存在满足这个clause(query)的查询条件的一个或者多个文档
    must_not匹配到的所有文档都不能满足这个clause(query) 的查询条件。这个clause在filter context下执行,意味着忽略打分值并且这个query可以被缓存。因为忽略了打分值,所有的文档分数都是0

      bool query采取的是more-matches-is-better的方法。所以如果某篇文档同时满足mustshould的查询条件,那么这篇文档的打分值会累加,最后在_sorce中返回。

    Using minimum_should_match

      你可以使用参数minimum_should_match来指定匹配到的文档必须满足至少minimum_should_match个(或者某个比例)occurshould的clause(query)。

      如果 bool query中至少包含一个should clause并且没有mustfilter的clause,这个参数的默认值为1

      minimum_should_match了解这个参数更多的可选值。

    Scoring with bool.filter

      在元素(element)filter下指定的query不会影响文档的打分—返回的打分值(score)都是0。只有在元素query中指定的query才会影响文档的打分值(下面例子中的bool query,不过这个query中的子query仍然是不用打分的query)。接下来的三个例子中都是返回那些满足status字段的字段值为active的文档。

      下面第一个query返回的所有文档的打分值都是0,因为没有指定用于打分的query。

      bool query中有一个match_all的query,这个query将另所有的文档的打分值为1.0

      constant_score这个query的行为跟上面第二个例子是一模一样的。这个query将另所有的文档的打分值为1.0

    Named queries

      每一个query都可以在顶层定义中设置一个_name。你可以使用被命名的query(named query)来追踪返回的文档被哪个query命中了。如果使用了named query,响应中的每一个结果中都会包含一个mathced_queries的属性。

    Boosting query

    (8.2)link

      返回匹配positive query的文档并且降低匹配negative query的文档的相关性分数(relevance score)。

      你可以通过boosting query来对相关文档进行降级(demote)而不是从查询结果中排除掉这些文档。

    Example request
    Top-level parameters for boosting

    Constant score query

    (8.2)link

      封装了一个 filter query 并且每一个匹配到的文档的相关性分数等于参数boos的值。

    Top-level parameters for constant_score

    Disjunction max query

    (8.2)link

      返回的文档匹配一个或者多个封装的query,成为query clause或者clause。

      如果一篇返回的文档匹配了多个query clause,dis_max query会将query clause中打分最高的值作为相关性分数,基于参数tie_breaker再加上其他匹配的子query(subquery)对应的打分值。

    Example
    Top-level parameters for dis_max

    Function score query

    link

    Full text queries

    link

      full text query可以查询analyzed text fields,例如邮件的内容。查询的内容会跟索引期间的内容一样使用相同的分词器处理。

      属于full text query的query包括:

    Intervals query

    (8.2)link

      基于匹配到的terms的顺序以及接近度(proximity。term之间在文档中的物理距离或位置接近程度)返回文档。

      intervals使用由一小组matching rules定义组成。这些规则会应用到指定的一个字段的字段值中。

      定义的规则会生成文本内容中term之间的最小间隔序列(也就是term的顺序跟接近度),并且还可以进一步跟父级中的定义进行组合

    Example request

      下面的intervals查询返回的文档中,字段名为my_text的字段值中包含my favorite food,这三个term(my、favorite、food)在文档中是先后有序紧挨着的,并且紧跟着hot water或者cold porridge

      这个查询会匹配字段名为my_text中包含my favorite food is cold porridge的文档,但是不会匹配when it's cold my favorite food is porridge(因为在cold porridge跟my favorite food没有顺序出现)。

    Top-level parameters for intervals
    match rule parameters

      match规则匹配被分词后的文本(analyzed text)

    prefix rule parameters

      prefix规则匹配以指定字符开头的term。最多可以扩展到128个term。如果匹配出超过128个term,Elasticsearch会返回一个错误。你可以使用字段的mapping中的index-prefixes选项避免这种限制。

    wildcard rule parameters

      wildcard规则使用通配符匹配term。最多可以扩展到128个term。如果匹配出超过128个,Elasticsearch会返回一个错误。

    WARNING:最高避免以*或者?为开头的通配符。为了能找到匹配 的term会会增加迭代次数,使得降低查询性能

    fuzzy rule parameters

      fuzzy规则用来匹配跟提供的term相似的term,基于Fuzziness中的编辑距离实现。如果模糊表达式匹配超过128个term,Elasticsearch会返回一个错误。

    all_of rule parameters

      all_of规则中由多个其他规则组成,这些规则都满足则返回对应文档

    any_of rule parameters

      any_of规则返回它包含的规则中的任意一个。

    filter rule parameters

      filter规则基于一个query来过滤intervals。见Filter example中的例子。

    Note
    Filter example

      下面的查询中定义了一个filter规则。返回的文档中有hot以及porridge,这两个term之间的位置距离不超过10,并且这两个term之间没有salty

    Script filters

      你可以使用一个脚本,基于开始、结束以及间隔来过滤intervals。下面的filter脚本中使用了interval变量以及startendgaps方法:

    Minimization

      intervals query总是最小化间隔,以确保查询可以在线性时间内运行。有时这可能导致意想不到的结果,尤其是在使用max_gaps限制或过滤器时。例如,考虑以下查询,搜索包含在短语hot porridge中的salty

      这个查询不会匹配包含这个短语的文档:hot porridge is salty porridge,因为只匹配到文档中最开始的hot porridge这两个term后就返回了,并且这两个term之间没有包含salty

      any_of规则中需要注意到另一个限制,那就是子规则出现重叠的情况。特别是其中一个规则是另一个规则的前缀,那么较长的规则不会被匹配,这使得在使用max_gaps时会带来一些意想不到的结果。下面的query中,查询the以及紧接着bigbig bad,紧接着wolf

      这个query不会匹配包含the big bad wolf的文档,因为any_of规则在bigbig bad中仅为big生成间隔。由于big bad的间隔比big的长但起始位置相同,因此它会被最小化处理而不被考虑。在这种情况下,建议重新编写查询,将所有选项在顶层明确列出:

    Match query

    (8.2)link

      返回匹配了查询条件中的文本、数值、日期或者布尔值的文档。如果查询条件中提供的是文本,那么在匹配前会对该文本进行分词。

      match query是一个用于全文检索的标准query,包含了可以用于模糊查询(fuzzy)的选项。

    Example request
    Top-level parameters for match
    Parameters for <field>
    Notes
    Short request example

      最简单的match query由<field>query参数组成。:

    How the match query works

      match query实际是boolean类型,意味着query中提供的文本会被分词并且构建一个Boolean query。operator参数可以设置为or或者and来控制boolean clause(默认值为or)之间的关系。可以设置minimum_should_match参数指定至少要匹配多少个should关系中的clause。

      下面是operator参数:

      设置analyzer可以用来控制如何对文本进行分析处理。默认是mapping定义中这个字段对应的设置,或者是默认的search analyzer。

      设置lenienttrue可以用来忽略数据类型不一致导致的异常,比如一个数值类型的字段,在query中提供了一个string。默认为false

    Fuzziness in the match query

      fuzziness根据待查询的字段的类型允许执行 fuzzy matching。见Fuzziness了解相关的设置。

      设置prefix_lengthmax_expansions用来控制模糊匹配的处理过程。如果设置了fuzzy选项,那么query会使用top_terms_blended_freqs_${max_expansions}作为rewrite methodfuzzy_rewrite参数允许控制如何对query进行重写(rewrite)。

      默认允许Fuzzy transpositions(ab -> ba),可以通过fuzzy_transpositions设置为false的方式关闭。

    NOTE:Fuzzy matching is not applied to terms with synonyms or in cases where the analysis process produces multiple tokens at the same position. Under the hood these terms are expanded to a special synonym query that blends term frequencies, which does not support fuzzy expansion.

    Zero terms query

      如果使用了stop filter后,分词器移除了所有的token,默认的行为是不匹配任何的文档。使用zero_terms_query设置为none(默认值)或者设置为all后,query就相当于match_all

    Synonyms(match)

      match query支持使用synonym_graph token filter实现multi-terms 同义词扩展(synonym )。使用这个filter后,解析器会对每一个multi-terms synonyms创建一个短语查询。例如,下面的同义词:"ny, new york"会产生:(ny OR ("new york"))

      同样的也可以匹配多个同义词,这些同义词之间的关系为AND,而不是这几个同义词作为短语查询。

      上面的例子创建出下面的boolean query:

      (ny OR (new AND york)) city

      满足条件的文档中要么匹配到ny,或者匹配到new AND york,或者都匹配到。auto_generate_synonyms_phrase_query默认值为true

    Match boolean prefix query

    (8.2)link

      match_bool_prefix query对输入进行解析后,会基于生成的term构造一个bool query。除了最后一个term,其他的每一个term构造为一个term query,最后一个term构造为prefix query。例如:

      对上面的输入进行解析后会生成quickbrownf这三个term,相当于下面的bool query:

      match_phrase_prefix query跟match_bool_prefix query一个很重要的不同点是,match_phrase_prefix query 将这些term作为一个短语,而match_bool_prefix query 则是在文档中的任意位置去分别匹配这些term。上面的例子中,match_bool_prefix query 可能会匹配quick brown fox,同时也可以匹配brown fox quick,甚至还会分别去匹配包含quickbrown、以f开头的term,并且这些term可以在文档的任意位置。

    Parameters

      默认情况下,match_bool_prefix query会对输入使用字段在mapping中的分词器(analyzer)。不过可以通过analyzer 参数在查询时配置一个分词器。

      match_bool_prefix query支持match query中提到的minimum_should_match以及operator参数。构造出来的bool query中的clause的数量大多数情况下和分词器对输入解析后生成的term的数量一样。

      fuzziness, prefix_length, max_expansions, fuzzy_transpositions, and fuzzy_rewrite这些参数都可以应用到所有term对应的 term query中,除了最后一个term。这些参数不会对最后一个term对应的prefix query有任何的应用。

    Match phrase query

    (8.2)link

      match_phrase query解析(analyze)文本后会基于分析后的文本创建一个短语查询(phrase query)。

      A phrase query matches terms up to a configurable slop (which defaults to 0) in any order. Transposed terms have a slop of 2。

      analyzer 可以用于控制如果对文本进行解析。默认使用该字段在mapping中定义的分词器,或者查询中默认使用的分词器:

      这个查询同样接收zero_terms_query参数,见match query中的介绍。

    Match phrase prefix query

    (8.2)link

      返回的文档中包含查询中提供的文本中的单词,并且要求有相同的单词间的先后顺序。提供的文本中的最后一个term会认为是一个prefix,匹配以这个term开头的其他term。

    Example request

      下面的查询返回的文档中包含了message字段中以quick brown f开头的短语。

      这个查询将会匹配message字段的quick brown fox or two quick brown ferrets,但是不会匹配the fox is quick and brown

    Top-level parameters for match_phrase_prefix
    Parameters for <field>
    Notes
    Using the match phrase prefix query for search autocompletion

      尽管使用起来很简单,但是将match_phrase_prefix query用于查询时的自动提示(search autocompletion)可能会返回一些让人困惑的结果。

      比如说,如果查询关键字是quick brown f。这个请求会创建一个quickbrown的短语查询(文档中quick必须存在紧接着它的下一个term必须是brown)。然后从sorted term dictionary中找到50个以f开头的term,最后将这些term添加到短语查询中。

      问题在于这前50个term可能没有fox这个term,使得没法找到quick brown fox这个短语。但这通常又不是一个问题,因为用户会继续输入更多的字母,直到出现它们想要查找的词。

      completion suggestersearch_as_you_type field type了解更多search-as-you-type更好的解决方案。

    Combined fields

    (8.2)link

      Combined fields query支持查询多个text字段,就像是这些字段的值索引到一个组合字段(combined fields)中。该query是一种"以term为中心"的(term-centric)的视角(见multi_match中以field为中心的内容):首先将待查询的字符串分词为一个个独立的term,然后在所有字段中去查找每一个term。这个query特别适用在多个text字段中进行匹配,例如一篇文章中的titleabstractbody中。

      combined_fields query基于simple BM25F(见The Probabilistic Relevance Framework: BM25 and Beyond)公式这个原则方法进行打分。在对匹配到的文档进行打分时,该query会跨多个字段结合term和收集到的统计值,就像是指定的这些字段索引到了单个的、组合字段中。This scoring is a best attempt。combined_fields makes some approximations and scores will not obey the BM25F model perfectly。

    WARNING:Filed number limit 默认情况下,某个query中包含的clause的数量是由限制的。定义在indices.query.bool.max_clause_count中。默认值为4096。对于combined fields query。clause的数量的计算方式为:字段的数量和term的数量的乘积。

    Per-field boosting

      每个字段的boost通过combined field model描述。例如,如果title的boost为2,就像是title中的每一个term在synthetic combined field中出现两次。

      第6行,每一个字段都可以通过^符号实现boost。

    NOTE:combined_fields query中字段的boost是一个大于等于1的值,可以是小数。

    Top-level parameters for combined_fields
    Comparison to multi_match query

      combined_fields query提供了一种在多个text字段中匹配和评分的有原则的方式。为了支持这一点,它要求所有字段具有相同的查询分词器analyzer

      如果你的某个查询要在不同类型的字段上进行,那么multi_match比较合适。他同时支持text和非text类型的字段,并且接受在不同的text字段上可以有不同的分词器。

      multi_match主要的两种模式best_fieldsmost_fields是种"以field为中心"视角(field-centric view)的查询。与之相反的combined_fields则是"以term为中心"视角。operatorminimum_should_match应用在每一个term上,而不是每个字段上。比如有这样的query:

      执行后如下:

      也就是说,一篇文档中至少有一个字段有这个term才能被匹配(换句话说,一篇文档中只要有database,system就满足匹配,这两个term可以分布在不同的字段上,最好的情况是这两个term在同一个字段上)。

      cross_fields multi_match模式同样是"以term为中心"的方法并且operatorminimum_should_match应用在每一个term上。与cross_fields相比,combined_fields的主要优势在于其基于BM25F算法的稳健且易于解释的评分方法。

    NOTE:Custom similarities combined_fields只支持BM25,他是默认的Similarity,可以通过custom similarity配置。同样也不允许Per-field similarities。否则使用combined_fields时报错。

    Multi-match query

    (8.2)link

      multi_match基于match query,允许在多个字段上查询:

      第5行是查询语句(query string)   第6行,查询的目标字段

    fields and per-field boosting

      可以使用通配符指定字段:

      第6行,在titlefirst_name以及last_name字段上查询

      不同的字段可以通过插入^符号来提高权重:

      第6行,在subject字段上得出的分数会乘以3,而在message字段上的打分则不变

      如果没有提供fieldsmulti_match默认在index.query.default_field中指定的字段上查询,默认是**会从mapping中提取出所有的合适的字段并且过滤掉metadata fields。所有提取出的字段随后组合构建成一个query。

    WARNING:Field number limit 默认情况下,某个query中包含的子query的数量(number of clauses)是有上限的。该上限在indices.query.bool.max_clause_count中定义。默认是4096。对于multi-match,计算子query数量的方式是:字段的数量*term的数量

    Types of multi_match query:

      multi_match在内部执行方式取决于type参数,可以设置为以下的值:

    best_fields

      当你搜索的多个关键字(word)在同一个字段中时,best_fields是非常有用的。比如说brown fox在单个字段中肯定比brown在一个字段而fox在另一个字段更有意义。

      best_fields会为每一个字段生成一个match query并且封装到一个dis_max query,来找出单个最佳匹配的字段。例如:

      将会按下面的方式执行:

      通常best_fields类型会采用匹配到的单个最佳的字段对应的打分值,但如果指定了tie_breaker,那会考虑下面的情况:

      同样支持这些参数:analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, fuzzy_rewrite, zero_terms_query, auto_generate_synonyms_phrase_query 以及 fuzzy_transpositions,见match query中的介绍。

    IMPORTANT:operator and minimum_should_match best_fieldsmost_fields这两个类型是以字段为中心,每一个字段都生成了一个match query。意味着operatorminimum_should_match参数是应用到字段之间,可能不是你期望的那样。例如下面的query: GET /_search { "query": { "multi_match" : { "query": "Will Smith", "type": "best_fields", "fields": [ "first_name", "last_name" ], "operator": "and" } } } operatorand说明每个字段中必须出现所有的term 这个query的执行相当于: (+first_name:will +first_name:smith)| (+last_name:will +last_name:smith) 换句话说,对于匹配到的文档,单个字段中必须出现所有的term

    combined_fields提供了"以term为中心"的视角,operatorminimum_should_match应用到每一个term之间。其他的multi-match模式cross_fields同样能解决这个问题

    most_fields

      most_fields类型最适合在多个字段中进行查询,并且每个字段都索引了相同的文本,但是使用了不同的分词器的情况。例如,主字段可能包含synonyms、stemming term和没有变音符号(diacritics)的term。第二个字段可能包含原始的term,第三个字段可能包含词缀(shingles)。通过结合来自所有这三个字段的分数,我们可以匹配尽可能多的与主字段相符的文档,同时利用第二和第三字段将最相似的结果推到列表的顶部:

      这个查询将通过以下的方式:

      汇总每一个match的打分值,然后除以match的数量就是最终的打分值。

      同样接受这些参数:analyzerboostoperatorminimum_should_matchfuzzinesslenientprefix_lengthmax_expansionsfuzzy_rewrite,以及 zero_terms_query

    phrase and phrase_prefix

      phrasephrase_prefix类型跟best_fields很像,只是它们使用了match_phrase或者match_phrase_prefix而不是match query。

      这个请求:

      这个查询将通过以下的方式:

      同样的接受参数analyzerboostlenient以及 zero_terms_query,见Match中的介绍。接受参数slop,见Match phrase中的介绍。另外phrase_prefix类型接受max_expansions参数。

    IMPORTANT:phrase, phrase_prefix and fuzziness phrasephrase_prefix不能使用fuzziness参数。

    cross_fields

      cross_fields类型对于在结构化的文档中期望在多个字段中进行匹配这种场景就特别的有用。例如,当在first_namelast_name中查找Will Smith,最好的匹配结果应该是Will在上面两个字段中的一个,并且Smith在另一个字段中。

      一种解决方式是简单的将first_namelast_name合成为一个full_name。当然,只能在索引期间完成。

      cross_field类型能够在查询时间通过一种"以term为中心"的方法解决。它首先将query string分词成单独的term,然后在每一个字段中为每一个term进行查找,就好像它们是一个big field。

      这个查询将通过以下的方式:

      换句话说,所有的term必须存在于至少一个字段中(所有的term分布在不同的字段中,最多一个字段中有所有的term)。而best_fieldmost_field则可能做不到这一点。

      这种类型解决了上述两个问题中的一个问题。term在不同字段中词频不同的问题通过混合词频(blending term frequencies)来平衡差异性。

      在实践中,first_name:smith被视为跟last_name:smith有相同的词频并且加1。这使得匹配first_namelast_name时有可比较的打分值,但last_name会有轻微优势,因为它更可能包含词smith

      cross_fields类型查询通常仅适用于短的字符串字段,且这些字段的boost值为1。如果字段有不同的boost、freq和length normalization,则混合词频统计可能失去意义

      如果你通过Validate运行上面的query,它会返回这种解释:

      接受这些参数:analyzer, boost, operator, minimum_should_match, lenient 以及 zero_terms_query

    WARNING:cross_fields类型的查询在混合字段统计时可能不总是产生合理的评分(例如评分可能变为负数)。作为替代,Ni可以考虑使用combined_fields查询,这种查询同样"以term为中心",但以更稳健的方式结合字段统计。这是针对跨字段查询的一种改进方法。

    cross_field and analysis

      查询的字段有相同的分词器才能"以term为中心"的模式工作。有相同分词器的字段会被划分为一个组。如果有多个组,查询将会使用这些组中打分值最高的那个。

      例如,如果firstlast字段有相同的分词器,而first.edgelast.edge有相同的edge_ngram分词器,如下所示:

      这个query会按下面的方式执行:

      换句话说,firstlast会被化为同一组,就像是单个字段一样,而而first.edgelast.edge会被化为同一组,就像是单个字段一样。

      存在多个组是没有问题的,但当使用了operatorminimum_should_match就会出现上文中提到使用most_fieldbest_field的问题。

      你可以很容易的使用dis_maxquery来组合两个cross_field类型的查询,并且只将minimum_should_match应用到其中一个就行了 :

      第11行,will或者smith必须出现在fristlast字段中。

      你可以通过在请求中指定分词器将所有的字段归为一个组:

      第7行,所有的字段使用standard分词器。

      这个请求按照下面的方式执行:

    tie_breaker

      默认情况下,一个组中每个term的blendedquery会返回最高的打分值。当跨多个组整合打分值时,会使用组中打分值最高的。tie_breaker参数能对这两个步骤进行更改:

    0.0Take the single best score out of (eg) first_name:will and last_name:will (default)
    1.0Add together the scores for (eg) first_name:will and last_name:will
    0.0 < n < 1.0Take the single best score plus tie_breaker multiplied by each of the scores from other matching fields/ groups

    IMPORTANT:cross_fields and fuzziness cross_fields类型不能使用fuzziness参数。

    bool_prefix

      bool_prefix类型的行为跟most_fields很像,但是使用了match_bool_prefix query而不是match query。

      可以接受analyzer, boost, operator, minimum_should_match, lenient, zero_terms_query以及 auto_generate_synonyms_phrase_query参数,见match query中的介绍。fuzziness, prefix_length, max_expansions, fuzzy_rewrite, fuzzy_transpositions用于terms来构造term query,但是不会对prefix query构造出的term生效。

      不支持slop参数。

    Query string query

    (8.2)link

    TIP:本节内容介绍的是query_string这个query类型,更多关于在Elasticsearch中运行一个查询query的内容见Search your data.

      基于提供的查询字符串(query string),使用一个语法严格的解析器并且返回文档。

      这个query使用一个syntax进行解析并且基于AND或者NOT操作符对query string进行切分。然后在返回匹配的文档前,这个query独立的 analyzer每一个切分的文本。

      你可以使用query_string query创建一个包含通配符,跨多个字段以及更多信息的复杂查询。虽然具备很多功能(versatile),但这个query的语法很严格,如果query string中包含任何无效语法,则返回错误。

    WARNING:由于任意非法语法都会导致这个query返回错误,我们不建议在搜索框(search boxes)中使用query_string中使用这个查询。 如果你不需要支持query syntax,可以考虑使用match query。如果你需要query syntax的功能,可以使用simple_query_string,这种query没有那么严格的语法。

    Example request

      当你运行下面的查询,query_string query会将(new york city) OR (big apple)划分两个部分:new york city 以及 big apple。随后在返回匹配到的文档前,content字段的分词器分别将每一部分的值分成token。由于query syntax没有使用whitespace作为一个操作符,new york city会原样的传给分词器。

    Top-level parameters for query_string
    Note
    Query string syntax

      这个query string:mini-language用于Query string以及search API中的q这个query string parameter。

      query string被解析为一系列的term以及操作符。term可以是单个Word,比如quick或者brown。也可以是一个短语,使用引号修饰,比如quick brown,这种将查找短语中所有的word,并且是有序的。

      操作符使得你可以自定义查询,可用选项如下所示:

    Field Names

      你可以在查询语法中指定字段名:

    Wildcards(query string)

      通配符查询可以运行在单个term上,使用?替换单个字符,使用*替换0个或多个字符:

      注意的是通配符查询会使用大量的内存,并且性能很差。你可以想象下匹配a* b* c*这个query string会有多少个term?

    WARNING:如果你只使用了*,那么会被重写为exists query。因此,field:*将会匹配空值(不是null): { "field": "" } 不会匹配缺失字段或者显示的设置字段值为null: { "field": null }

    WARNING:如果将*作为起始字符(leading wildcards)是特别开销大的,因为索引中所有的term都需要处理。可以通过设置allow_leading_wildcardfalse关闭。

    Regular expressions(query string)

      可以在query string中插入正则表达式,使用/修饰:

      正则表达式的语法支持见Regular expression syntax

    WARNING:allow_leading_wildcard参数不会应用于正则表达式。query string中包含下面的内容将会让Elasticsearch访问索引中的每一个term:/.*n/。请小心使用。

    Fuzziness(query string)

      你可以~操作符来允许fuzzy queries

      对于这些query,query string会被normalized(对query string进行处理,处理方式基于character filterstoken filters),不过只能使用部分filter,见Normalizers

      query使用Damerau-Levenshtein distance来找出所有最多有两处变化的term,这个变化可以是插入,删除,或者单个字符的替换或者两个相邻字符的位置互换。

      默认的编辑距离是2,但是编辑距离为1时能满足80%的人为拼写。通过下面的方式指定:

    WARNING:Avoid mixing fuzziness with wildcards 不支持混合使用fuzzywildcard操作符。如果出现了混合使用,其中一种操作不会被应用(apply)。例如,你可以查询app~1(fuzzy)或者app*(wildcard),但对于app~1,不会应用fuzzy中的操作符~

    Proximity searches

      短语查询(例如john smith)期望所有的term有精准的先后顺序,而Proximity searches允许指定的word可以离开它相邻的word距离更大或者先手顺序不同。同样的fuzzy query可以为一个word中的字符指定一个最大编辑距离,而proximity searches允许我们指定短语中一个word的最大编辑距离:

      相比于query string中原有的先手顺序越近,相关性则越高。如果比较上面的这个查询,短语quick foxquick brown fox更有相关性。

    Ranges(query string)

      可以对时间、数值或者字符串字段指定一个范围。包含上下界的范围使用中括号[min TO max],不包含上下界的范围使用花括号{min TO max}

      也可以组合使用花括号跟中括号:

      一边是无界的语法如下:

    NOTE:要使用简化语法同时结合上界和下界,你需要用AND操作符连接两个子句。这种方法允许你在查询中明确指定一个范围,确保结果符合两个条件的交集。 age:(>=10 AND <20) age:(+>=10 +<20)

      对query string中的范围语句进行解析可能复杂并且容易出错,最好直接使用rangequery。

    Boosting(query string)

      使用增强(boost)操作符^使得某个term比其他term更具相关性。例如,如果我们要找到所有关于fox的文档,但是我们又特别对quick fox感兴趣,那么就可以:

      boost的默认值为 1,它可以是任意的正浮点数。0到1之间的boost值会降低相关性。

      boost同样可以应用在短语或者组:

    Boolean operators(query string)

      默认情况下,所有的term都是optional。如果查询foo bar baz,那么包含一个或者多个其中一个term(foo或者bar或者baz)的文档都是满足匹配的。上文中我们已经讨论过default_operator,它使得必须所有的term都要匹配到。但可以在query string中使用boolean operator来提供更多的控制。

      首选的操作符是+(文档中必须有所有的term)以及-(文档中不能出现term)。其他的term则是可有可无的。例如这个query:

      表示:

      虽然也支持常见的布尔操作符ANDORNOT(也可以写作&&||!),但要注意它们不遵循通常的优先级规则,所以当一起使用多个操作符时应使用括号。例如,上述查询可以重写为:

      这种形式正确解释了原始查询的逻辑,但相关性评分与原始查询相去甚远。相比之下,使用match重写的同一个查询将会是这样的:

    Grouping(query string)

      多个term或者clause可以通过括号组合在一起形成子query(sub-query):

      分组还可以用于应用到某个特定的字段上,或者boost这个子query的打分:

    Reserved characters(query string)

      如果在你的查询中,某些字符(保留字符reversed character)的功能是作为操作符或者不作为操作符,那你可以使用反斜杠进行转移控制。例如,若要查询(1+1)=2,那么你的query应该是\(1\+1\)\=2

      请求body中使用JSON时,需要用到两个反斜杠(\\),注意在JSON中反斜杠是保留的转义字符。

      需要进行转义的保留字符有:+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /

      没有正确对这些特殊字符进行转义会导致语法错误并且阻止query的运行。

    NOTE:<>通常不能被转义,因为它们用来描述范围查询,唯一防止被解析为范围查询的方式就是从query string中完全的移除

    Whitespaces and empty queries(query string)

      空格不认为是一个操作符。

      如果query string是空的或者只包含空格,那么这个query被认为是空的结果集。

    Avoid using the query_string query for nested documents(query string)

      query_string查询会不会返回nested 文档。如果搜索nested文档,则应使用nested query

    Search multiple fields(query string)

      你可以使用field参数在多个字段上执行quert_string query。

      多个字段上执行quert_string query的设计是能query term能实现OR的查询:

      例如有以下的查询:

      相当于:

      由于多个独立的查询term(search term)生成了多个query,因此自动的使用dis_max以及tie_breaker实现。例如(name字段使用^5提高了(boost)权重):

      简单的通配符可以用于查询文档内部的元素(inner elements of the document)。例如,如果我们有一个city字段,它有多个子字段(或者它是一个object),我们可以自动的在city的所有字段上查询:

      还有一种方式就是在query string自身里面提供通配符字段(wildcard fields)(正确的对*进行转义)。例如:city.\*:something

    NOTE:由于反斜杠在json字符串中是一个特殊字符,所以它需要被转移术,因此上面的query_string中有两个反斜杠。

      field参数中可以有基于字段名的pattern,允许自动扩展到相关的字段(会自动的引入包含的字段)。例如:

    Additional parameters for multiple field searches

      在多个字段上运行query_string query时,支持以下额外的参数:

      注意的是,基于type值的不同,multi_match查询可能支持额外的顶级参数。

    Synonyms and the query_string query

      query_string query支持使用synonym_graph token filter对multi-terms synonyms进行扩展。在使用filter之后,解析后会为每一个multi-terms synonyms创建一个短语查询(下面用双引号修饰了new york)。例如下面的同义词ny,new york会生成如下的查询:

      也可以通过conjunction方式(也就是使用AND)进行匹配:

      上面的例子会创建一个boolean query:

      匹配到的文档中有term ny或者new AND yorkauto_generate_synonyms_phrase_query参数默认为true

    How minimum_should_match works

      query_string 会分割成多个query,然后使用操作符创建一个boolean query作为整个输入。你可以使用minimum_should_match来控制结果中应该匹配多少个clause

      上面的例子创建了一个boolean query:

      满足匹配的文档中至少在单个title字段上要匹配thisthatthus中的两个。

    How minimum_should_match works for multiple fields

      上面的例子创建了一个boolean query:

      titlecontent上使用disjunction max来匹配文档。这里的minimum_should_match并没有生效。

      每一个term之间显示的指定操作后会被认为是独立的clause。

      上面的例子创建了一个boolean query:

      匹配到的文档至少要包含上面3个should clause中的两个。每一个term之间使用了disjunction max。

    How minimum_should_match works for cross-field searches

      type参数使用了cross_files值后,意味着所有字段使用使用了相同的分词器。

      上面的例子创建了一个boolean query:

      匹配到的文档中至少满足有三个per-tem blended query中的两个。

    Allow expensive queries(Query string query)

      query_string query会被自动的转化为一个prefix query,意味着如果禁用了prefix query(见这里的说明)。那么这个query就不会被执行并且会抛出一个异常。

    Simple query string query

    (8.2)link

      根据提供的query string,使用有限的(比如不能使用AND,而应该使用+)但可以容错语法的解析器返回匹配的文档。

      这个query使用simple syntax进行解析并且根据指定的操作符将query string切分为term。随后这个query在返回匹配文档之前分别analyzer每一个term。

      尽管这个query中的语法比query_string query更具有限制性,但是simple_query_string query不会在遇到非法语法时返回错误。而是忽略query string中非法的部分。

    Example request
    Top-level parameters for simple_query_string

      这个例子中,quote_field_suffix的值就是exact。如果指定了 quote_field_suffix。那么相当于在body.exact字段上查询query string。   你可以根据后缀来使用一个不同的分词器使得可以进行精准匹配。见Mixing exact search with stemming

    Note
    Simple query string syntax

      simple_query_string query 支持以下的操作符:

      若要使用这些字符的字面值,需要用反斜杠进行转义。

      基于default_operator的值,操作符的行为可能有所不同,例如:

      这个查询想要返回的文档中,包含foo或者 包含bar并且不能包含baz。然而由于default_operator的值为OR,这个查询实际上返回的文中包含foo或者bar,但是所有的文档不能包含baz。若要按照你想要的结果返回,需要将query string中的内容改为foo bar +-baz

    Limit operators

      你可以使用flags参数限制simple query string语法中支持指定操作符。

      若要显示的只开启指定操作符,使用|操作符。例如,flags的值为OR|AND|PREFIX时将禁用所有操作符,除了OR, ANDPREFIX

      合法的flags值包括:

    Wildcards and per-field boosts in the fields parameter

      字段名可以指定为通配符:

      第6行,请求titlefirst_name以及last_name字段

      每个字段可以分别使用^符号进行boost,提高该字段的相关性:

      第6行,subject字段的重要性是message的3倍。

    Multi-position tokens(Simple query string query)

      默认情况下simple_query_string在解析后会为query string中的每一个multi-position token创建一个match_phrase。例如,会为这个multi-word synonym:ny, new york创建一个match_phrase

      同样的也可以匹配多个同义词,这些同义词之间的关系为AND,而不是这几个同义词作为短语查询。

      上面的例子创建出下面的boolean query

      满足条件的文档中要么匹配到ny,或者匹配到new AND york,或者都匹配到。

    Joining queries

    link

    Nested query

    (8.2)link

      封装了其他query,用于查询nested字段的一种query。

      nested query查询nested对象时,就像这些对象分别索引在不同的文档中一样(见下面中must_not clauses and nested queries的介绍)。如果某个对象满足匹配查询,nested query返回所在的root parent document。

    Example request
    Index setup

      若要使用nested query,你必须有一个mapping类型为nested的字段。例如:

    Example query

    Top-level parameters for nested

    Notes

    Context of script queries

      如果在nested query中运行script query,你只能访问nested文档中的doc value,而不能parent或者root document中获取。

    Multi-level nested queries

      若要了解multi-level的nested query是如何工作的,首先你有一个含有nested类型的字段的索引。下面的请求在索引drivers中定义了含有makemodel nested字段的mapping。

      下一步,像drivers中索引一些文档。

      你可以基于makemodel使用multi-level的nested query。

      查询请求返回下面的响应:

    must_not clauses and nested queries

      如果nested query匹配了文档中的一个或多个nested 对象(因为把对象数组中的每一个对象看成了独立的对象,就像这些对象各自属于独立的文档),就返回命中的文档。即使对象数组中的其他对象不满足匹配也会返回。当在nested query中使用must_not clause时要额外注意。

    TIP:使用inner_hits参数了解nested query匹配了哪些nested对象

      例如,下面的查询使用了一个外层的nested query并且使用了must_not

      响应:

      第25行,这个nested对象满足匹配,因此,会将这个对象的parent document返回   第28行,这个nested对象不满足匹配。由于其他的nested object满足匹配,因此这个查询仍然返回parent document

      若任意一个nested对象不满足匹配就排除这篇文档,可以使用另一个外层的must_not

      响应:

    Match all query

    link

      最简单的一个Query,它将匹配所有的文档,并且所有文档的打分值_score都为1.0。

      可以通过boost参数修改_score的值。

    Match None Query

      这是与match_all相反的Query,它不匹配任何文档。

    Specialized queries

    link

    More like this query

    link

    Rank feature query

    link

    Script query

    link

    Script score query

    link

    Term-level queries

    (8.2)link

      你可以使用term-level queries基于结构化数据中精确(precise)的值来查找文档。结构化数据包括日期范围、IP地址、价格或者产品ID。

      full-text queries不同的是,term-level queries不会对查询词(search term)分词。而是跟字段值精确匹配。

    NOTE:对于mapping类型为keyword并且含有normalizer属性的字段,Term-level queries查询该字段时仍然会标准化查询词。更多信息见normalizer

    Types of term-level queries

    Exists query

    (8.2)link

      返回的文档中包含待查询的字段,不关心字段值是什么。

      索引一个文档后,文档中的字段没有被索引的原因有以下几种:

    Example request
    Top-level parameters for exists
    Notes
    Find documents missing indexed values

      若要查找的文档中某个字段是缺失的,可以在must_not boolean query中使用exists query:

      下面的查询返回的文档中缺失了user.id字段。

    Fuzzy query

    (8.2)link

      返回的文档中,待查询的字段包含跟查询词相似的term。Elasticsearch 使用 Levenshtein edit distance来衡量相似性或模糊度。

      编辑距离是将一个term转为其他term时字符变化的数量。这些变化可以是:

      若要找到相似的term,fuzzy query根据指定的编辑距离创建了查询词一系列可能的变体、扩展。这个query最后返回每一个扩展后的term的精确匹配结果。

    Example requests
    Simple example
    Example using advanced parameters
    Top-level parameters for fuzzy
    Parameters for <field>
    Notes

      如果search.allow_expensive_queries设置为false则不允许执行这个query。

    IDs

    (8.2)link

      基于IDs返回文档,这个查询使用了文档的IDs,IDs被存储在_id字段中。

    请求示例
    Top-level parameters for ids

    Prefix query

    (8,2)link

      返回的文档中,待查询的字段的字段值包含指定的前缀。

    Example request

      下面的查询中,将返回user.id字段的字段值以ki为前缀的文档。

    Top-level parameters for prefix
    Parameters for <field>
    Notes
    Short request example

      你可以通过组合<field>value简化prefix的语法。

    Speed up prefix queries

      你可以通过使用mapping 参数ndex_prefixes提高prefix query的查询。开启这个参数后,Elasticsearch会将前缀索引到一个字段中。这样能让Elasticsearch在大型索引中能更快的执行prefix query。

    Allow expensive queries(Prefix query)

      如果将search.allow_expensive_queries设置为false则不允许执行prefix query。然而如果开启了index_prefixes,则认为构建了优化的Query,不认为这种查询会很慢,因此允许执行。

    Range query

    (8.2)link

      返回的文档中,待查询的字段的字段值属于指定的范围。

    Example request

      下面的查询中,返回age字段的字段值在1028之间的文档。

    Top-level parameters for range
    Parameters for <field>
    Notes
    Using the range query with text and keyword fields

      如果search.allow_expensive_queries设置为false,则不会运行在textkeyword类型的字段上的range query。

    Using the range query with date fields

      如果<field>date类型,下面的参数可以使用date math

      例如,下面的查询中根据timestamp字段返回今天跟昨天的文档

    Missing date components

      对于range query以及date range aggregation,Elasticsearch使用下面的值替换缺失的date components。不能替换缺失的year component:

      比如说如果format是yyyy-MM,那么Elasticsearch会将gt2099-12转化为099-12-01T23:59:59.999_999_999Z。这个日期使用了年(2099)跟月(12)。但是使用了默认的日(01)时(hour)分(59)秒(59)以及纳秒(999_999_999)。

    Numeric date range value

      如果没有指定date format并且range query作用在一个date类型的字段上,那么在查询中提供了数值类型的值后,它会被用自纪元以来的毫秒数(milliseconds-since-the-epoch)表示。如果你提供的数值希望是用来表示年份,比如说2020,那么你需要将其作为字符串,Elasticsearch会根据默认的format或者mapping中定义的format进行转化。

    Date math and rounding

      Elasticsearch根据以下参数来舌入(round)date math值:

    Example query using time_zone parameter

      你可以使用time_zone参数使用UTC偏移值将其转化为UTC。例如:

      第8行,指明使用+01:00这个UTC偏移   第9行,根据UTC偏移,Elasticsearch会将这个日期转化为2019-12-31T23:00:00 UTC   第10行,time_zone参数不会影响now

    Regexp query

    (8.2)link

      返回的文档中,待查询的字段的字段值匹配了一个正则表达式

      正则表达式是一种使用称为操作符的占位符字符来匹配数据中模式的方法。有关 regexp 查询支持的操作符列表,请参见正则表达式语法

    Example request

      下面的请求中,返回满足user.id的字段值以k开头并且以y结尾的文档。.*操作符匹配任意长度的任意字符,包括没有字符。可以匹配kykay以及kimchy

    Top-level parameters for regexp
    Parameters for <field>
    NOTES
    Allow expensive queries(Regexp query)

      如果search.allow_expensive_queries设置为false,则不允许执行regexp Query。

    Term query

    (8.2)link

      返回的文档中,待查询的字段的字段值精确匹配查询词

      你可以使用term query基于精确的值来超找文档。比如价格、产品ID或者用户名。

    WARNING:避免对text类型的字段使用term query。 默认情况下,默认情况下,text类型的字段作为analysis的一部分,Elasticsearch 会更改文本字段的值。这可能会使得为text类型精确匹配变得困难。 若要查询text类型的字段,应该使用match

    Example request
    Top-level parameters for term
    Parameters for <field>
    NOTES
    Avoid using the term query for text fields

      默认情况下,Elasticsearch在分词阶段会修改text类型的字段的字段值。比如,默认的standard analyzertext类型的字段的字段值作以下的修改:

      若要更好的查询text字段,match总是在执行查询前先对你提供的查询词(search term)进行分词。意味着match query是对分词后的token而不是整个查询词对text类型的字段查询。

      term query不会对查询词分词。term query而是根据你提供的查询词作精确匹配。意味着在text字段上执行term query可能返回很差甚至没有结果。

      若要查看两者的区别,可是尝试下下面的例子:

    1. 创建一个名为full_texttext类型的字段

    1. 索引一篇文档,full_text的字段值为Quick Brown Foxes!

      注意的是,full_texttext类型,Elasticsearch会在分词阶段将Quick Brown Foxes!修改为[quick, brown, fox]。

    1. 使用term qeury在full_text字段上查询Quick Brown Foxes!,包含pretty参数,使得响应中的内容更加易读。

      因为full_text中不包含精确的(exact)Quick Brown Foxes!,所以term query不会返回结果

    1. 使用match query在full_text上查询Quick Brown Foxes!

      term query不同的是,match query在执行查询前会先对你提供的查询词Quick Brown Foxes!进行分词。match query会返回full_field的字段值中包含quickbrown或者fox的文档。

      match query的响应中包含了上文中索引的文档。

    Terms query

    (8.2)link

      返回的文档中,待查询的字段的字段值精确匹配一个或多个查询词。

      terms query跟term query是相同的,差别就是你可以查询多个值。

    Example request

      下面的请求中,返回的文档中的user.id的字段值是kimchy或者elkbee

    Top-level parameters for terms
    Notes
    Highlighting terms queries

      Highlighting is best-effor only。Elasticsearch可能不会为term query返回高亮结果的原因可能有:

    Terms lookup

      Terms lookup获取现有的文档中的字段值。Elasticsearch随后使用这些值作为查询词。当查询大量的term集合时可能比较有用。

      若要运行一个terms lookup。必须开启字段的_source。你不能再远端索引中使用cross-cluster search运行terms lookup。

    NOTE:默认情况下,Elasticsearch限制terms query的term数量为65536。包括通过terms lookup获取的term。你可以使用index.max_terms_count修改这个限制

      为了能降低网络压力,terms lookup会尽可能在本地的分片中获取文档的值。如果你的terms data不是很大,可以考虑使用单个主分片并复制到所有适用的数据节点上来最小化网络流量。

      若要执行一个terms lookup,可以实现下面的参数。

    Terms lookup Parameters
    Terms lookup example

      若要查看terms lookup是如何工作的,尝试下面的例子:

    1. 创建一个索引,包含名为colorkeyword类型的字段

    1. 索引一篇文档,ID为1,color字段的值为["blue", "green"]

    1. 再索引一篇文档,ID为2,color的字段值为blue

    1. 使用terms query以及terms lookup参数找出跟第2篇文档中有一个或多个相同字段值的文档。包含pretty参数,使得响应中的内容更加易读。

      由于文档2跟文档1在color中都包含blue,因此Elasticsearch同时返回这两篇文档。

    Terms set query

    (8.2)link

      返回的文档中,待查询的字段的字段值精确匹配一个或多个查询词,你可以使用一个字段或者脚本定义至少要匹配的查询词数量。

      terms_setterms query是一样的,差别是你可以定义一篇文档至少要匹配term的数量:

    Example request
    Index setup

      大多数情况下,你需要包含一个numeric类型的字段来使用terms_set query。这个字段的字段值为满足匹配的文档要求匹配的term数量。

      若要查看如何为terms_set query设置一个索引,尝试下面的例子

    1. 创建一个名为job-candidates的索引,该索引有以下的字段

    1. 索引一篇文档,ID为1以及这些内容:

      添加?refresh参数使得索引后马上对搜索可见。

    1. 索引另一篇文档,ID为2以及这些内容:

      现在你可以使用required_matches作为在terms_set query中,满足匹配的文档需要匹配的term数量。

    Example query

      下面的查询返回的文档中,programming_languages中至少包含下面两个term:

      minimum_should_match_fieldrequired_matches。意味着匹配term的数量为2,也就是required_matches的字段值。

    Top-level parameters for terms_set
    Parameters for <field>
    Notes
    How to use the minimum_should_match_script parameter

      你可以使用minimum_should_match_script,使用脚本定义满足匹配的文档必须匹配的term数量。如果你需要动态的设置数量时,使用这个参数就非常有用。

    Example query using minimum_should_match_script

      下面的查询返回的文档中,programming_languages中至少包含下面两个term:

      参数source描述的是:

    Wildcard query

    (8.2)link

      返回的文档中,待查询的字段的字段值匹配了一个通配符模式(wildcard pattern)。

      通配符的操作符是一个占位符来匹配一个或多个字符。例如,通配符操作符*匹配0个或多个字符。你可以组合通配符的操作符来创建一个通配符模式。

    Example request

      下面的请求中,返回满足user.id的字段值以k开头并且以y结尾的文档。.*操作符匹配任意长度的任意字符,包括没有字符。可以匹配kykay以及kimchy

    Top-level parameters for wildcard
    Parameters for <field>
    NOTES
    Allow expensive queries(Wildcard query)

      如果search.allow_expensive_queries设置为false,则不允许执行Wildcard query。

    minimum_should_match parameter

    link

    rewrite parameter

    link

    Regular expression syntax

    (8.2)link

      regular expression是一种使用占位符(称为操作符)匹配数据的方式。

      Elasticsearch支持在下面的请求中使用regular expression:

      Elasticsearch使用Apache Lucene的正则表达式引擎来解析这些query。

    Reserved characters

      Lucene的正则表达式引擎支持搜友的Unicode字段,然而下面的字符会被保留用作操作符:

    . ? + * | { } [ ] ( ) " \

      根据开启的optional operators,下面的字符可能也会被保留:

    # @ & < > ~

      若要字面上使用这些字符,需要用反斜杠进行转移或者用双引号修饰

    \@ # renders as a literal '@' \\ # renders as a literal '\' "john@smith.com" # renders as 'john@smith.com'

    Standard operators

      Lucene的正则表达式引擎不使用Perl Compatible Regular Expressions (PCRE)库,但支持下面标准的操作符:

    Optional operators

      你可以使用flags参数开启更多可选的操作符用于Lucene的正则表达式引擎中。

      若要开启多个操作符,可以使用|分隔符。例如,flagCOMPLEMENT|INTERVAL开启了COMPLEMENT以及INTERVAL两个操作符。

    Valid values

    Unsupported operators

      Lucene的正则表达式引擎不支持锚点运算符(anchor operator)。比如^(行的开头)或$(行的结尾)。要匹配一个term,正则表达式必须匹配整个字符串。

    Aggregations

    (8.2)link

      聚合(aggregation)能汇总你的数据用于指标、统计以及其他的分析。聚合能帮助你回答类似下面的问题:

      Elasticsearch将聚合组织成三类:

    Run an aggregation

      你可以在search API中指定agg参数,将其作为search的一部分。下面的查询在名为my-field的字段上运行一个term aggregation

      聚合的结果在响应中的aggregations对象中:

      第19行,my-agg-name聚合的结果。

    Change an aggregation’s scope

      使用query参数限制聚合的目标文档:

    Return only aggregation results

      默认包含聚合操作的查询结果同时返回查询命中和聚合结果。若只要返回聚合结果,将size设置为0即可:

    Run multiple aggregations

      你可以在同一个请求中指定多个聚合操作:

    Run sub-aggregations

      Bucket aggregation支持bucket or metric sub-aggregation。例如,一个带有avg sub-aggregation的term aggregation会计算每一个分桶中的平均值。对于嵌套的sub-aggregation没有层数或深度的限制。

      响应中嵌套的sub-aggregation结果位于parent aggregation中:

      第4行,名为my-agg-name的parent aggregation的结果。   第11行,名为my-sub-agg-name的聚合结果,它是名为my-agg-name的parent aggregation的sub-aggregation。

    Add custom metadata

      在聚合中使用meta对象关联自定义的元数据:

      响应中会原样返回meta对象:

    Return the aggregation type

      默认情况下,聚合结果中包含了聚合名称但没有聚合类型。若要返回聚合类型,可以使用请求参数typed_keys

      响应中,聚合类型会作为聚合名称的前缀。

    IMPORTANT:一些聚合返回跟请求中不同的聚合类型。例如,terms、significant termspercentiles aggregations 会返回不同的聚合类型,这取决于被聚合的字段的数据类型。

      第4行,聚合类型就是histogram后面紧跟#以及聚合名称,即my-agg-name

    Use scripts in an aggregation

      当某个字段不能完全满足你想要的聚合目的,你应该在runtime field上聚合:

      脚本中字段值的计算是动态的,他会额外增加一点点聚合的开销。除了计算的时间开销,一些比如termsfilters的聚合不能在使用runtime field时使用一些优化。总之,使用runtime field的开销根据不同的聚合类型而不同。

    Aggregation caches

      为了能快速响应,Elasticsearch在shard request cache中缓存了频繁的聚合操作的结果。若要获取缓存结果,可以在每一次查询中使用相同的preference string。如果不需要查询命中,可以将size设置为0来避免缓存查询命中。

      Elasticsearch根据相同的preference string将查询路由到相同的分片上。如果在查询时分片的数据没有发生变化,分片会返回缓存的聚合结果。

    Limits for long values

      当运行聚合时,Elasticsearch使用double值来处理并且代表数值类型的数据。使得对超过2^53long数值的聚合结果是近似值。

    Bucket aggregations

    (8.2)link

      Bucket aggregation不像metric aggregation那样对字段计算指标,而是对文档进行分桶。使用对应的规则(取决于聚合类型)进行分桶,决定某篇文档是否要"落入"当前的分桶中。换句话说,分桶有效的定义了文档集。除了分桶本身,bucket aggregation还计算"落入"到每一个分桶中的文档数量。

      Bucket aggregation跟metric aggregation不同的是,它可以包含sub-aggregation。这些sub-aggregation可以对由它们的"parent" bucket aggregation创建的分桶,在桶内进行聚合操作。

      不同的bucket aggregation有不同的"bucketing"策略。有些定义了单个分桶,有些定义了固定数量的多个分桶,还有的能在聚合处理期间动态的创建分桶。

    NOTE:search.max_buckets这个集群设置限制了在单个响应中分桶的数量

    Adjacency matrix aggregation

    (8.2)link

      一种返回邻接矩阵(adjacency matrix)形式的桶聚合。请求提供了一系列命名的过滤表达式集合,类似于filters aggregation请求。响应中的每个桶代表了交叉过滤器矩阵中的一个非空单元格。

      给定名为ABC的过滤名,响应中会返回以下名字的分桶:

     ABC
    AAA&BA&C
    B BB&C
    C  C

      交叉的桶,例如A&C,使用两个过滤器名称的组合以及默认的分隔符&进行标记。注意,响应中不会包含C&A桶,因为这会是与A&C相同的一组文档。这个矩阵被认为是对称的,所以我们只返回其中的一半。为了做到这一点,我们对过滤器名称字符串进行排序,并且总是使用一对中较小的值作为分隔符左侧的值。

    Example

      下面的名为interactionsadjacency_matrix aggregation哪些人群交换了电子邮件:

      响应中包含每一个过滤条件以及其组合的分桶和文档数量。不匹配的文档被排除在响应中。

    Parameters
    Response body
    Usage

      仅凭这个聚合就可以提供创建无向加权图所需的所有数据。然而,当与子聚合(如日期直方图)一起使用时,结果可以提供执行动态网络分析(dynamic network analysis)所需的额外数据层级,在这种分析中,检查随时间变化的交互变得非常重要。

    Filter limits

      对于N个过滤条件会生成N^2 / 2个分桶。断路器( circuit breaker)会组织结果生成太多的分桶来避免过多的磁盘寻道(disk seek)。请使用indices.query.bool.max_clause_count来限制过滤条件的数量。

    Auto-interval date histogram aggregation

    (8.2)link

      它属于multi-bucket aggregation。 类似Date histogram,Date histogram aggregation使用了间隔(interval)作为每一个分桶之间的"宽度"。而Auto-interval date histogram aggregation则是指定了分桶的数量,来告知需要返回的分桶数。它能自动的选择分桶之间的"宽度"来满足要求。返回的分桶数量将总是不大于指定的分桶数量。

      参数buckets是可选的,如果未指定则使用默认值:10

      要求返回10个分桶:

    Keys

      在Elasticsearch内部实现中,日期用64位的时间戳表示,也就是milliseconds-since-the-epoch(01/01/1970 midnight UTC)。这些时间戳将作为分桶的key。key_as_string则是使用相同的时间戳根据format转化成格式化后的日期字符串:

    TIP:如果你不指定format,则使用字段的mapping中第一个date format

      第8行,支持expressive date format pattern

      响应:

    Intervals

      返回的分桶之间的间隔基于被聚合的数据进行选择,因此返回的分桶数量将总是不大于指定的分桶数量。可能的间隔如下所示:

     

    seconds以1、5、10和30的倍数
    minutes以1、5、10和30的倍数
    hours以1、3和12的倍数
    days以1和7的倍数
    months以1和3的倍数
    years以1、5、10、20、50和100的倍数

      最坏的情况下,当指定的分桶数量由于是按天分桶导致分桶数量过多的话,返回的分桶数量是指定数量的1/7。

    Time Zone

      Elasticsearch用Coordinated Universal Time (UTC)存储日期时间。默认使用UTC进行分桶和舌入。使用time_zone字段来告知应该使用不同的时区。

      你也可以用 ISO 8601 UTC 偏移来指定时区(+01:00 or -08:00)或者 IANA time zone ID,比如America/Los_Angeles就是在TZ 数据库中使用的标识符。

      比如有这样的例子:

      如果未指定时区则使用UTC,返回了3个间隔为1个小时的分桶,第一个分桶从2015年10月1日午夜开始:

      如果指定time_zone-01:00,那么分桶的开始时间就是UTC午夜时间的前一个小时。

      现在分桶之间的间隔仍然是1个小时,但是第一个分桶的开始时间为2015年9月30号下午11点。这是指定时区的本地时间:

      第7行,The key_as_string value represents midnight on each day in the specified time zone.(感觉说的不对)

    WARNING:许多时区会因夏令时而调整时钟。在这些变更发生时附近的桶可能比你根据calendar_interval或fixed_interval预期的大小略有不同。例如,考虑CET时区的夏令时开始:2016年3月27日凌晨2点,时钟向前调整1小时至当地时间3点。如果你使用day作为calendar_interval,那么覆盖那天的桶将只包含23小时的数据,而不是其他桶的常规24小时。对于更短的间隔,如fixed_interval的12小时,当夏令时变更发生时,3月27日早上你将只有一个11小时的桶

    Minimum Interval parameter

      minimum_interval参数允许使用者指定应该使用的最小舌入间隔(rounding interval)。这使得收集过程更加效率,因为聚合不会尝试在小于minimum_interval的任何间隔上进行舍入。

      可接受的minimum_interval单位有:

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第8行,没有date字段的文档会落入相同的分桶中,并且把这些文档看成有date字段,并且值为2000/01/01

    Categorize text aggregation

    link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      它属于multi-bucket aggregation,将半结构化(semi-structured)的文档分组到分桶内。每一个text类型的字段使用自定义的analyzer重新分析。产生的token随后被分组,创建出格式相似的文本值桶。这种聚合最适合机器生成的文本,如系统日志。仅使用前100个分词后的token来分组文本。

    Children aggregation

    (8.2)link

      它属于特殊的single bucket aggregation,选择有指定了类型的子文档(child document),该类型在join filed中定义。

      这个聚合有单个选项:

      比如,我们有关系为questionanswer的索引(questionanswer的parent)。answer类型在mapping的定义如下所示:

      下面的例子中,parent文档中包含一个名为tag 字段并且answer文档中包含一个名为owner的 字段。children aggregation能在单个请求中将tag bucket映射到owner bucket中,尽管这两个字段在不同类型的文档中。

      question的文档:

      answer的文档:

      下面的请求能将他们连接在一起:

      第12行,type指向了名为answer的类型。

      上面的例子返回了top question tags以及每一个tag的top answer owners。

      第67行, tag为file-transfer, windows-server-2003等question文档的数量   第69行, tag为file-transfer, windows-server-2003等关联的answer文档的数量

    Composite aggregation

    link

    WARNING:composite aggregation开销是昂贵的。在你生产中部署composite aggregation前先进行测试。

      它属于multi-bucket aggregation,会根据不同的source创建composite buckets。

      跟其他multi-bucket aggregation不同的是,你可以使用composite aggregation有效地对来自多层次聚合(multi-level)aggregation的所有桶进行分页。这个聚合提供了一个方法流式处理一个指定的聚合的所有分桶,跟scroll处理文档类似。

      composite buckets通过对提取/创建出的每一篇文档中的值进行组合(combination),并且每一种组合都认为是一个composite bucket。

      例如,在下面这个文档中:

      下面的composite bucket中,使用keywordnumber作为聚合结果的source filed。

    Value sources

      sources参数定义了构建compost bucket时使用的source filed。在sources中的定义先后顺序控制了key的返回顺序。

    NOTE: 当你定义sources时,你必须使用一个唯一键

      sources参数的类型只能是下列中的一种:

    _Terms

      terms这个value source类似一个简答的terms aggregation。这个值从一个字段中提出出来,跟terms aggregation一样。

      例子:

      terms aggregation一样,可以为composite bucket通过runtime field创建一个值:

      尽管很相似,但是terms这个 value source 不支持terms aggregation中的参数。对于支持的value source参数,见:

    Histogram(Composite)

      histogram 这个value source可以应用在数值类型的值上,构建值之间固定大小的间隔。interval参数定义数值类型的值如何被转化(transform)。比如说一个interval为5时,任何数值都会转到其最接近的间隔,101这个值会被转化为100。这个key用于描述100到105的值。

      例如:

      histogram aggregation 一样,可以为composite bucket通过runtime field创建一个值:

    Date histogram(Composite)

      date_histogram 类似与histogram,只是间隔值用的是date/time。

      上面的例子创建了一个按天作为时间间隔,并将所有timestamp的值转化成最近的时间间隔。可用的间隔表达式有:year, quarter, month, week,day, hour,minute, second

      时间值也可以缩写为目前支持的time units。注意的是小数点的时间值是不支持的,但是你可以转化为其他单位来解决这个问题(比如说1.5h可以替换为90m)。

      在内部实现中,日期会用一个64位的milliseconds-since-the-epoch数字表示。这些时间戳返回后会作为bucket key。可以返回格式化的日期字符串,而不是使用格式参数指定的格式:

       第13行,见format pattern

      Elasticsearch用Coordinated Universal Time (UTC)存储日期时间。默认使用UTC进行分桶和舌入。使用time_zone字段来告知应该使用不同的时区。

      你也可以用 ISO 8601 UTC 偏移来指定时区(+01:00 or -08:00)或者 IANA time zone ID,比如America/Los_Angeles就是在TZ 数据库中使用的标识符。

      使用offset参数,指定正负号(+-)的时间修改每一个分桶的开始值,比如1h就是一小时,1d就是一天。见time units了解更多的选项。

      比如,当使用了day的间隔,每一个分桶从每天的午夜开始,下一个午夜结束,将offset设置为+6h后,每一个分桶从早上6点到下一个早上6点:

      上面的请求会将6am开始的文档分组到分桶内,而不是从凌晨开始。

    NOTE: 每一分桶开始的offse已经用time_zone进行了调整。

    GeoTile grid(Composite)
    Order(Composite)
    Missing bucket(Composite)

    Date histogram aggregation

    (8.2)link

      它属于multi-bucket aggregation,类似与普通的histogram。但是它只能用于日期或者日期类型的范围值(range value)。由于日期在Elasticsearch内部用long值表示,因此histogramaggregation 也可以用于日期,但准确性不如data histogram。这两个聚合的区别在于这个聚合的间隔(interval)可以指定为date/time 表达式。Time-based的数据要求特殊支持,因为time-based的interval不总是一个固定长度(比如间隔为1M,那么不同月份的一个月的天数是不一样的)。

      跟histogram一样的是,字段值会被下舍入到最近的分桶中,例如,如果间隔是一个日历日(calendar day),那么2020-01-03T07:00:01Z会下舍入到2020-01-03T00:00:00Z。字段值按照以下方式舌入:

    Calendar and fixed intervals

      在配置一个date histogram aggregation时,有两种方式指定间隔:calendar-aware time(日历感知,也就是自然时间,比如一个月,一年这种)以及fixed time(固定时间)。

      calendar-aware time能根据夏令时会改变特定日子的长度,不同的月份有不同数量的天数,而闰秒可以加到特定的年份上。

      相比之下,固定间隔总是国际单位制的倍数,并且不会根据日历情境发生变化。

    Calendar intervals

      calendar-aware interval通过calendar_interval配置。你可以使用单位名称,比如month、或者单个单位数量,比如1M。例如day1d是同等的。多个数量,比如2d是不支持的。

      可接受的日历间隔(calendar interval)包括:

    Calendar interval examples

      下面的例子中,按照间隔为一个月的日历时间进行分桶:

      如果你尝试使用多个日历单元(calendar unit),那么聚合将会失败,因为只支持单个单位数量。

    Fixed intervals

      固定间隔使用fixed_interval配置。

      与Calendar aware intervals不同,固定间隔是固定数量的国际单位制(SI)单位,不会偏离(也就是不受日历上的变化(如月份长度不同、闰年等)或特殊时间调整(如夏令时)的影响),不管它们落在日历上的哪个位置。一秒钟总是由1000毫秒组成。这允许固定间隔以支持单位的任何倍数来指定。

      然而,这意味着固定间隔不能表示像月份这样的单位,因为一个月的持续时间不是一个固定数量。尝试指定一个像月或季度这样的日历间隔将会抛出异常。

      固定间隔接受的单位有:

    Fixed interval examples

      如果我们尝试重新创建一个之前calendar_interval的一个月,我们可以使用固定的30天来近似实现。

      但如果我们尝试使用日历单位时是不支持的,比如多个周,我们会得到一个异常:

    Date histogram usage notes

      在所有情况下,当指定的结束时间不存在时,实际的结束时间是指定结束后最接近的可用时间。

      广泛分布的应用程序还必须考虑到一些变数,比如一些国家在凌晨12:01开始和停止夏令时(daylight savings time),因此一年中会有一分钟的星期日后接着是额外的59分钟的星期六,以及那些决定跨越国际日期变更线的国家。这样的情况可能会让不规则的时区偏移看起来简单。

    NOTE:一分钟的星期日后接着是额外的59分钟的星期六 夏令时是一种在夏季月份调整时钟以便更好地利用日照的做法,通常涉及在春季将时钟向前调整一小时,在秋季再将其调回

    • 夏令时结束前:时间进入到凌晨12:01 AM,接着是星期日的第一分钟。

    • 夏令时结束:在凌晨12:01 AM,时钟后退一小时到前一个小时的开始,即回到11:01 PM。

    • 夏令时结束后:时间再次经历11:02 PM到11:59 PM的59分钟,这些时间实际上是“重复”的,因为它们在夏令时期间已经发生过一次。这导致了一个有趣的现象,即夏令时结束的那一天会比标准的24小时多出一个小时,总计25小时。 因此,这种情况下,看似在星期日的第一分钟后,实际上是回到了星期六的最后一个小时,从而造成了“一分钟的星期日后接着是额外的59分钟的星期六”的现象。

      一如既往,严格的测试,特别是在时间变更事件周围,将确保您的时间间隔规范是您所期望的。

    WARNING:为了避免意外结果,所有连接的服务器和客户端都必须同步到一个可靠的网络时间服务。

    NOTE:不支持小数时间值,但您可以通过转换到另一个时间单位来解决这个问题(例如,1.5小时可以指定为90分钟)。

    NOTE:您还可以使用时间单位解析支持的缩写来指定时间值。

    Keys

      在Elasticsearch内部实现中,日期用64位的时间戳表示,也就是milliseconds-since-the-epoch(01/01/1970 midnight UTC)。这些时间戳将作为分桶的key。key_as_string则是使用相同的时间戳根据format转化成格式化后的日期字符串:

    TIP:如果你不指定format,则使用字段的mapping中第一个date format

      第7行,支持expressive date format pattern

      响应:

    Time zone

      Elasticsearch用Coordinated Universal Time (UTC)存储日期时间。默认使用UTC进行分桶和舌入。使用time_zone字段来告知应该使用不同的时区。

      例如,如果间隔是calendar day并且时区是America/New_York(西五区),那么2020-01-03T01:00:01Z转化为2020-01-02T18:00:01(应该是2020-01-02T20:00:01吧?),舌入到2020-01-02T00:00:00然后转回到UTC的2020-01-02T05:00:00:00Z。最终以America/New_York显示分桶名称,所以变成了2020-01-02T00:00:00

      也就是:

      你也可以用 ISO 8601 UTC 偏移来指定时区(+01:00 or -08:00)或者 IANA time zone ID,比如America/Los_Angeles

      看这个例子:

      如果不指定一个时区,则使用UTC。这将导致这两个结果放到同一个分桶中,开始于:midnight UTC on 1 October 2015

      如果你指定的时区为-01:00,那么午夜时间是UTC午夜的前一个小时:

      注意的是第一个文档会落入到2015年9月30的桶,而另一个落入到2015年10月1号的桶

      key_as_string描述了指定时区中每天的午夜时间。

    WARNING:许多时区会因夏令时而调整时钟。在这些变更发生时附近的桶可能比你根据calendar_interval或fixed_interval预期的大小略有不同。例如,考虑CET时区的夏令时开始:2016年3月27日凌晨2点,时钟向前调整1小时至当地时间3点。如果你使用day作为calendar_interval,那么覆盖那天的桶将只包含23小时的数据,而不是其他桶的常规24小时。对于更短的间隔,如fixed_interval的12小时,当夏令时变更发生时,3月27日早上你将只有一个11小时的桶

    Offset

      使用offset参数,指定正负号(+-)的时间修改每一个分桶的开始值,比如1h就是一小时,1d就是一天。见time units了解更多的选项。

      比如,当使用了day的间隔,每一个分桶从每天的午夜开始,下一个午夜结束,将offset设置为+6h后,每一个分桶从早上6点到下一个早上6点:

      上面的请求将文档分别落入到两个从早上6点开始的分桶中,而不是落入到同一个从午夜开始的单个分桶中:

    NOTE:在调整时区后,在根据offset计算

    Keyed Response

      keyed设置为true,分桶的key_as_string的值将作为key,响应中所有的分桶用hash展示而不是用数组。

      响应:

    Script

      如果文档中的数据不完全满足你聚合的目的,可以使用runtime filed。比如,如果促销销售的收入应该在销售日期的后一天确认:

    Parameters

      你可以使用order参数控制返回的分桶的顺序,以及根据min_doc_count过滤分桶(默认第一个和最后一个之间的所有分桶都会返回,意思是即使是空的分桶也会返回)。histogram同样支持extended_bounds。使得histogram的范围可以超过数据自身。hard_bounds可以限制histogram的范围。更多信息见Extended BoundsHard Bounds

    Missing value

      missing参数定义了文档中缺失被聚合的字段时,如何进行聚合。默认这些文档会被忽略但也可以把这些文档看成有一个值。

      第8行,没有date字段的文档会落入相同的分桶中,并且把这些文档看成有date字段,并且值为2000/01/01

    Order

      默认情况下分桶按照他们的key升序排序,不过可以通过order来控制这个行为。它跟Terms Aggregation中的order有相同的功能。

    Using a script to aggregate by day of the week

      当你需要按星期几聚合结果时,可以在一个runtime field上执行terms聚合,该字段返回星期几。这种方法允许你根据日期数据的特定部分(即星期几)来组织和分析聚合结果

      响应:

      响应中包含了一周中相关星期几的分桶:1代表星期一,2代表星期二……7代表星期日。

    Date range aggregation

    (8.2)link

      专门为日期值(date value)使用的range aggregation。这个聚合根range aggregation的主要不同是fromto可以用Date Math表达式。也可以在返回的fromto使用格式化后的日期。注意的是在这个聚合中,每一个范围的from是包含并且to是不包含的。

      例子:

      第8行,< now minus 10 months,下舍入到月份的开始时间   第9行,>= now minus 10 months,下舍入到月份的开始时间

      在上面的例子中,我们创建了两个范围的分桶,10个月前的文档将划分到第一个捅,10个月前开始到现在的文档划分到第二个分桶。

      响应:

    WARNING:如果format或者日期值不完整,date range aggregation使用默认值替换缺失的部分。见Missing date components

    • 你进行日期范围聚合时,如果你指定的日期没有包含所有需要的信息(比如,年、月、日、时、分、秒等),Elasticsearch会自动用一些预设的值来填充这些缺失的部分,以确保日期值是完整的

    Missing Values

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。可以通过添加字段名集合完成:字段值被映射为一个默认值

      第11行,没有date字段的文档会被划分到"Older"的分桶中,因为它们的字段值为1976/11/30

    Date Format/Pattern

    NOTE:以下的内容拷贝于DateTimeFormatter

      所有ASCII字母都被保留作为format pattern letter,其定义如下:

    SymbolMeaningPresentationExamples
    GeratextAD; Anno Domini; A
    uyearyear2004; 04
    yyear-of-erayear2004; 04
    Dday-of-yearnumber189
    M/Lmonth-of-yearnumber/text7; 07; Jul; July; J
    dday-of-monthnumber10
    Q/qquarter-of-yearnumber/text3; 03; Q3; 3rd quarter
    Yweek-based-yearyear1996; 96
    wweek-of-week-based-yearnumber27
    Wweek-of-monthnumber4
    Eday-of-weektextTue; Tuesday; T
    e/clocalized day-of-weeknumber/text2; 02; Tue; Tuesday; T
    Fweek-of-monthnumber3
    aam-pm-of-daytextPM
    hclock-hour-of-am-pm (1-12)number12
    Khour-of-am-pm (0-11)number0
    kclock-hour-of-am-pm (1-24)number0
    Hhour-of-day (0-23)number0
    mminute-of-hournumber30
    ssecond-of-minutenumber55
    Sfraction-of-secondfraction978
    Amilli-of-daynumber1234
    nnano-of-secondnumber987654321
    Nnano-of-daynumber1234000000
    Vtime-zone IDzone-idAmerica/Los_Angeles; Z; -08:30
    ztime-zone namezone-namePacific Standard Time; PST
    Olocalized zone-offsetoffset-OGMT+8; GMT+08:00; UTC-08:00;
    Xzone-offset Z for zerooffset-XZ; -08; -0830; -08:30; -083015; -08:30:15;
    SymbolMeaningPresentationExamples
    GeratextAD; Anno Domini; A
    uyearyear2004; 04
    yyear-of-erayear2004; 04
    Dday-of-yearnumber189
    M/Lmonth-of-yearnumber/text7; 07; Jul; July; J
    dday-of-monthnumber10

      pattern字母的数量决定了format。

    Time zone in date range aggregations

      可以通过time_zone参数将日期从UTC转化到另一个时区。

      你也可以用 ISO 8601 UTC 偏移来指定时区(+01:00 or -08:00)或者 IANA time zone ID,比如America/Los_Angeles就是在TZ 数据库中使用的标识符。

      time_zone参数也用于date math表达式中的舍入操作。举个例子,如果你想要按照中欧时间(CET)时区来舍入到当天的开始,你可以这么做:

      第8行,这个日期将被转化为2016-02-01T00:00:00.000+01:00   第9行,now/d将被舌入到欧时间(CET)时区当天的开始

    Keyed Response

      keyed设置为true,每个分桶名会关联一个唯一的string key,响应中所有的分桶用hash展示而不是用数组:

      相应:

      也可以为每一个范围自定义key:

      响应:

    Diversified sampler aggregation

    (8.2)link

    Geo-distance aggregation

    (8.2)link

      它属于multi-bucket aggregation。应用在geo_point类型的字段上,概念上跟range aggregation十分相似。用户可以定义一个名为origin的点以及距离范围集合。该聚合根据origin中指定的 point计算每一个文档跟这个点的的距离,然后根据范围(如果文档跟origin的距离属于定义的某个距离范围,那么就落入到对应的分桶中)决定文档落在哪个分桶中。

      响应:

      待聚合的字段必须是geo_point类型(只能在mapping中显示的指定该类型)。geo_point类型也可以包含一个geo_point字段的数组,在聚合时候所有的点都会考虑进去。origing的值可以有跟geo_point一样的格式:

      默认情况下,距离单位是m(meters)但也可以是:mi (miles), in (inches), yd (yards), km (kilometers), cm (centimeters), mm (millimeters).

      第8行,按照千米进行计算

      有两种计算模式:arc(弧度,默认计算方式)和plane(平面)。平面计算是最快但最不准确的。当你的搜索上下文是“狭窄的”且跨越较小的地理区域(约5公里)时,考虑使用平面计算。对于跨越非常大的区域(例如,跨洲搜索)的搜索,平面计算将返回更高的误差范围。距离计算类型可以使用distance_type参数来设置:

    Keyed Response

      keyed设置为true,每个分桶名会关联一个唯一的string key,响应中所有的分桶用hash展示而不是用数组:

      响应:

      也可以为每一个范围指定自定义的key:

      响应:

    Filter aggregation

    (8.2)link

      它属于single bucket aggregation(一个过滤条件只会生成一个分桶),将满足query的文档落入到单个桶内。

      这个例子尖酸了所有衣服的平均价格同时将t-shirt类型的衣服划分为一个桶,并且计算了桶内的平均价格。

      响应如下:

    Use a top-level query to limit all aggregations

      若要限制在查询运行时目标文档数量,可以使用一个top-level query。这样能加快带有sub-aggregation的filter aggregation。

      使用下面的例子:

      而不是使用下面的例子:

    Use the filters aggregation for multiple filters

      若要使用多个filter对文档进行分组,可以使用filters aggregation,它比使用多个filter aggregations更快。

      例如应该这个例子:

      而不是使用这个例子:

    Filters aggregation

    (8.2)link

      它属于multi-bucket aggregation,每一个分桶中的文档满足定义的query

      例子:

      上面的例子中,我们对日志信息进行解析。该聚合会构建两类日志信息的分桶,一个是包含error的,另一个是包含warning的。

      响应:

    Anonymous filters

      可以将多个过滤条件作为一个filters数组。如下所示:

      响应中两个分桶的先后顺序跟请求中定义的顺序一样。这个例子的响应如下:

    Other Bucket

      可以设置参数other_bucket将不满足所有过滤条件的文档落入到一个桶中并添加到响应中。这个参数的值可以是:

      可以定义other_bucket_key参数指定other_bucket的名字,而不是使用默认的_other_(如果过滤条件没有指定名字,设置这个参数不会生效)。设置这个参数会默认将other_bucket设置为true

      下面的片段中other bucket的名字设置为other_messages

      响应差不多是这样的:

    Geohash grid aggregation

    link

    Geohex grid aggregation

    link

    Geotile grid aggregation

    link

    Global aggregation

    link

    Histogram aggregation

    (8.2)link

      它属于multi-bucket Values Source aggregation,作用到从文档中提取出的数值类型或者数值类型范围值。他动态在值之间构建固定大小(bucket size,也就是间隔interval)。例如,如果文档中有一个名为价格的字段(数值),我们可以将这个聚合自动的配置为5的间隔(因为价格可以是5$)当执行聚合时,每一个文档中的价格会被评估并且下舍入(rounded down)到最近的分桶。比如说价格为32并且间隔为5,那么32被下舍入到30,因此"落入"到key为30的分桶中。正式点的表达就是,使用了以下的舌入函数:

      对于range values,一篇文档可以落入到多个分桶中。第一个分桶根据range value的下界值计算,计算方式跟单值是一样的。最后一个分桶根据range value的上界值计算。且range value中的所有被计入从首个桶到最后一个桶之间的所有桶内,包括这两个桶。

      间隔interval必须是正整数,并且offset必须是[0, interval)之间的整数(左闭右开)。

      下面的片段基于price字段以及间隔50进行分桶:

      响应差不多应该是:

    Minimum document count

      上面的响应中显示在[100, 150)的分桶中没有文档有这个价格。默认情况下会使用空的分桶来填充。不过有min_doc_count参数使得分桶中的文档数量必须高于该值,那么就不会返回空的分桶。

      响应:

      默认情况下,histogram根据数据自身情况返回所有的分桶,拥有最小值的文档决定了最小的分桶(第一个分桶,key最小的分桶),拥有最大值的文档决定了最大的分桶(最后一个分桶,key最大的分桶)。通常在要求返回空的分桶时,这样会造成一定的困惑,特别是在数据被过滤时。

      要理解上面这段话,可以看下这个例子:

      比如说你的请求中要求过滤出值为0500的所有文档,另外你还想要使用间隔为50的histogram的来划分数据。因为你想要获取所有的分桶,包括空的分桶,所以你同时还指定了min_doc_count: 0。如果所有的文档的价格都大于100,那么第一个分桶的key将会是100。这可能会给你带来困惑,因为你也想要获取在0-100之间空的分桶。

      通过extended_bounds参数,你可以指定minmax(即使某些区间没有对应满足的文档)来构建分桶。使用extended_bounds只有当min_doc_count0时才有意义(因为如果min_doc_count大于0,不会返回空的分桶)。

      注意的是extended_bounds不是用来过滤分桶的,也就说,如果extended_bounds.min大于文档中提取出的值,仍然会根据文档中的最小值来决定第一个分桶(extended_bounds.max小于文档中的最大值也是一样处理)。若要过滤分桶,应该在histogram中嵌套一个range filter aggregation并使用合适的from/to

      例子:

      分桶会根据返回的文档的值来聚合范围。也就是说响应中可能包含在query范围外的分桶。比如说,如果你的query查看大于100,并且你有50到150的文档,并且间隔为50,那么文档落入3个分桶中:50、100以及150。你可以理解为query跟aggregation的步骤是独立的。query用来选择文档,而聚合分桶不会考虑这些文档是否被query过滤。见note on bucketing range fields查看更多信息以及例子。

      hard_bounds对应于extended_bounds可以限制histogram中分桶的范围。在开放的data ranges中使用这个参数非常有用,因为它会导致大量的分桶。

      例子:

      这个例子中尽管query中指定了to 500,histogram只有两个分桶,分别是100跟150,其他的分桶会被忽略,即使有文档会落入到这些分桶内并且应该呈现出来。

    Order

      默认情况下分桶按照他们的key升序排序,不过可以通过order来控制这个行为。它跟Terms Aggregation中的order有相同的功能。

    Offset

      默认情况下,分桶的key从0开始,然后以间隔的等距一步步继续,例如,如果间隔是10,前三个桶(假设它们内部有数据)将是[0, 10),[10, 20),[20, 30)。可以通过使用offset来移动桶边界。

      这可以通过一个例子最好地说明。如果有10个文档,其值范围从5到14,使用10作为间隔将导致两个各含5个文档的桶。如果使用额外的offset为5,那么将只有一个单一的桶[5, 15),包含所有10个文档。

    Response Format

      默认情况下分桶是一个有序的数组。可以要求响应中用分桶的key值作为hash的key。

      响应:

    Missing value

      missing参数定义了文档中缺失被聚合的字段时,如何进行聚合。默认这些文档会被忽略但也可以把这些文档看成有一个值。

      第7行,没有quantity字段的文档会落入相同的分桶中,并且把这些文档看成有quantity字段,并且值为0

    Histogram fields(Histogram aggregation)

      对于histogram fields进行histogram aggregation时,将计算每个间隔的总数。

      比如对以下不同网络中已经预先聚合过的延迟指标进行histogram aggregation时:

      histogram aggregation会根据values累计每一个间隔(counts)的数量并返回以下结果:

    IMPORTANT: Histogram aggregation是一种bucket aggregation,它将文档分配到桶中,而不是像metric aggregation那样对字段进行计算。每个桶代表了一组文档,可以在其上运行sub-aggregation。另一方面,Histogram field是一种预聚合字段,表示单个字段内的多个值:数值数据的桶和每个桶的项目/文档计数。这种在histogram聚合预期输入(期望原始文档)和Histogram field(提供摘要信息)之间的不匹配,限制了聚合的结果仅为每个桶的文档计数。 因此,当在Histogram field上执行直方图聚合时,不允许进行sub-aggregation。

    IP prefix aggregation

    link

    IP range aggregation

    link

    Missing aggregation

    link

      它属于single bucket aggregation,它创建一个包含当前文档集上下文(根据query过滤后的文档集合)中所有缺少字段值的文档的桶(实际上,是缺少一个字段或已设置了配置的NULL值的文档)。这种聚合器通常与其他字段数据桶聚合器(如range aggregation)结合使用,以返回无法因缺少字段数据值而放置在任何其他桶中的所有文档的信息。

    Multi Terms aggregation

    link

      它属于multi-bucket value source based aggregation,分桶自动构建(每一个分桶键为多个字段的字段值的组合)。multi terms aggregation跟terms aggregation很类似,然而大多数情况下比terms aggregation慢并且会消耗更多的内存。因此如果经常需要使用固定的字段组合(mapping中定义一个runtime field),那么可以将其字段组合在索引时作为单独一个字段,然后使用terms aggregation。

    Nested aggregation

    link

      它属于特殊的single bucket aggregation,用于对嵌套文档(nested document)聚合。

    Parent aggregation

    link

    Random sampler aggregation

    link

    Range aggregation

    (8.2)link

      它属于multi-bucket value source based aggregation,允许用户定义一个范围集合,每一个范围代表一个分桶。在聚合过程中,从每个文档中提取出的值会根据分桶对应的范围进行检查,然后把文档分到这个桶内。注意的是在这个聚合中,每一个范围的from是包含并且to是不包含的。

      例如:

      响应:

    Keyed Response

      keyed设置为true,分桶的key_as_string的值将作为key,响应中所有的分桶用hash展示而不是用数组:

      响应:

      也可以为每一个范围自定义key:

      响应:

    Script

      如果文档中的数据不完全满足你聚合的目的,可以使用runtime filed。这个例子中,你如果要应用一个特殊的货币汇率:

    Sub Aggregations

      下面的例子中,不仅仅将文档分到桶内,还同时统计了在每一个价格区间内价格的统计信息。

      响应:

    Histogram fields

      Histogram fields运行range aggregation会计算每一个配置的范围的counts数量。

      这一过程不会在histogram之间进行插值。因此,可能存在一个范围位于两个histogram的值“之间”,导致该范围桶的文档计数为零。

      例如,对存储不同网络的延迟指标(以毫秒为单位)的预聚合直方图的索引执行范围聚合。

      range aggregation根据values对将每一个范围内的counts进行累加并返回以下结果:

    IMPORTANT: Histogram aggregation是一种bucket aggregation,它将文档分配到桶中,而不是像metric aggregation那样对字段进行计算。每个桶代表了一组文档,可以在其上运行sub-aggregation。另一方面,Histogram field是一种预聚合字段,表示单个字段内的多个值:数值数据的桶和每个桶的项目/文档计数。这种在histogram聚合预期输入(期望原始文档)和Histogram field(提供摘要信息)之间的不匹配,限制了聚合的结果仅为每个桶的文档计数。 因此,当在Histogram field上执行range aggregation时,不允许进行sub-aggregation。

    Rare terms aggregation

    link

    Reverse nested aggregation

    link

    Sampler aggregation

    link

    Significant terms aggregation

    link

    Significant text aggregation

    link

    Terms aggregation

    link

      它属于multi-bucket value source based aggregation,分桶自动构建,每一种字段值作为一个分桶key。

    Execution hint

    Variable width histogram aggregation

    link

    Subtleties of bucketing range fields

    link

    Metrics aggregations

    (8.2)link

      聚合家族中的这类聚合基于以某种方式从正在被聚合的文档中提取的值来计算指标。提取的值通常来自文档中的字段值,但也可以由脚本生成。

      数值类的metric aggregation是一种特殊的聚合,它们输出的结果是数值类型的值。一些聚合的输出是单个数值类型的指标(比如avg)并且称为single-value numeric metrics aggregation,其他生成多个指标(比如stats)的聚合称为multi-value numeric metrics aggregation。这两者的区别在于,当这些聚合作为某些bucket aggregation的直接sub-aggregation时扮演为不同的角色(一些bucket aggregation允许你根据每个桶中的数值指标对返回的桶进行排序)

    Avg aggregation

    (8.2)link

      单值的指标聚合(Single-value metric aggregation)计算是从被聚合的文档中提取出数值的平均值。可以指定文档中数值类型的字段(numeric filed)或者histogram字段用于avg aggregation。

      假设下面的文档描述的是学生的考试成绩(0~100分),我们可以使用下面的请求计算考试成绩平均值:

      上面的聚合会计算所有文档下的平均成绩。聚合的类型是avg并且field定义为一个数值类型的字段,计算这个字段的平均值。上述请求会返回下面的内容:

      聚合的名称avg_grade作为一个key,我们可以从返回的响应中读取这个字段的值获取聚合结果。

    Script

      如果说这次的考试难度非常大,你需要做一个成绩修正(grade correction)。在runtime field中进行"平均化"处理来得到一个修正后的平均值:

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Histogram fields

      如果对histogram字段进行聚合计算,聚合的结果会结合value数组中的值以及对应在count数组中的数量进行计算。

      例如,下面的索引存储了预先聚合好的、不同网络的延迟指标直方图:

      在每一个histogram field中,avg aggregation会累加value数组以及对应count数组中的乘积值。最终计算所有histogram field的平均值,如下所示:

      计算过程:

    Boxplot aggregation

    (8.2)link

      箱线图指标聚合(boxplot metric aggregation)计算的是从被聚合的文档中提取出的数值的箱线图数据。可以指定文档中数值类型的字段(numeric filed)或者histogram字段用于boxplot aggregation。

      boxplot aggregation返回必要的信息用于成为一个箱线图:最小值(minimum)、最大值(maximum)、中位数(median、Q2)、下四分位数/第一四分位数(first quartile,25th percentile、Q1)、上四分位数/第三四分位数(third quartile,75th percentile、Q3)。

    Syntax

      单独的boxplot aggregation如下所示:

      用于表示加载时间(load time)的boxplot aggregation如下所示:

      第7行,load time字段必须是数值类型的字段。

      响应如下所示:

      在这个例子中,下触须/下边缘(lower whisker)和上触须/上边缘(upper whisker)分别等同于最小值(min)和最大值(max)。一般情况下,这两个字段的值取值范围为:1.5* IQR,IQR = Q3 - Q1,也就是分别最接近Q1 - (1.5 * IQR)Q3 + (1.5 * IQR)的值。这是一个近似值(approximation value),所给出的数值可能并非实际从数据中观察到的值,但它们应该与实际值的误差范围相符。虽然箱线图聚合不直接返回异常值点(outlier point),但你可以通过检查lower whisker是否大于最小值或upper whisker是否小于最大值来判断是否存在任何一侧的异常值,然后直接查询它们。

    Script

      如果你需要将没有准确索引(indexed exactly)的数据用于创建箱线图,那你可以创建一个runtime field来调整这些数据。例如,如果你的加载时间(load time)的单位是毫秒,但是你想要使用秒作为单位来创建箱线图,那么可以使用runtime field来进行调整:

    Boxplot values are (usually) approximate

      箱线图指标使用的算法称为TDigest(见Computing Accurate Quantiles using T-Digests

    WARNNING:boxplot跟其他的percentile aggregation一样都是非确定性的(non-deterministic)的,所以使用相同的数据得到的结果会有轻微的不同

    Compression

      近似算法(approximate algorithm)必须平衡内存使用和估算准确性(estimate accurate),可以使用compression参数控制:

      第8行,compression参数控制内存使用和近似错误(approximate error,与实际值的差异)。

      TDigest算法使用许多“节点”来近似百分位数 —— 可用的节点越多,准确性越高(并且与数据量成比例地增加内存占用)。compression参数将节点的最大数量限制为20 * compression。

      因此,通过增加compression的值,你可以在牺牲更多内存的代价下提高百分位数的准确性。更大的compression还会使算法变慢,因为底层的树状数据结构在大小上增长,导致操作成本更高。默认的compression为100。

      一个“节点”大致使用32字节的内存,所以在最坏的情况下(大量的数据按顺序排序并按顺序到达),默认设置将产生一个大约64KB大小的TDigest。在实际应用中,数据往往更为随机,TDigest将使用更少的内存。

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Cardinality aggregation

    link

      它属于single-value aggregation。计算不同值的近似数量(approximate count)。

      假设你正在索引商店销售数据并且想要统计满足Query的不同的售卖的产品的数量:

      响应:

    Precision control

      这个聚合支持precision_threshold参数:

      第7行,precision_threshold 选项允许在内存与准确性之间进行权衡,并定义了一个独特的计数阈值,低于此阈值时,计数预计将接近准确。超过这个值,计数可能会变得有些模糊。支持的最大值是40000,高于这个数字的阈值将会产生与阈值为40000相同的效果。默认值是3000。

    Counts are approximate

      计算精确的计数需要将值加载到一个哈希集中并返回其大小。在处理高基数(high-cardinality)集合和/或大值时,这种方法不具可扩展性,因为所需的内存使用量以及在节点之间通信这些每个分片的集合会消耗太多集群资源。

      这种基数聚合基于HyperLogLog++算法,该算法基于值的哈希进行计数,并具有一些有趣的特性:

      对于精度阈值c,我们使用的实现大约需要c * 8字节的内存。

      下图显示了阈值前后误差如何变化:

      对于所有3个阈值,计数在配置的阈值范围内都保持了准确性。虽然没有保证,但这很可能是常见情况。实际的准确性取决于具体的数据集。一般来说,大多数数据集显示出一致的良好准确性。还要注意,即使阈值低至100,当计数达到数百万个项目时,误差仍然非常低(如上图所示,为1-6%)。

      HyperLogLog++算法依赖于哈希值前导零的数量,数据集中哈希的具体分布可以影响基数的准确性。

    Pre-computed hashes

      对于具有高基数的字符串字段,将字段值的哈希存储在索引中然后在此字段上运行cardinality aggregation可能会更快。这可以通过从客户端提供哈希值来完成,或者通过使用mapper-murmur3插件让Elasticsearch为您计算哈希值来实现。

    NOTE:Pre-computed hashes通常只在非常大和/或高基数字段上有用,因为它节省了CPU和内存。然而,在数值字段上,哈希运算非常快速,并且存储原始值所需的内存与存储哈希值相比,需要的内存量相同或更少。在低基数的字符串字段上也是如此,特别是考虑到为了确保每个唯一值每个段最多只计算一次哈希,这些字段有一个优化。

    Script

      如果你要计算的目标是两个字段的组合值,可以使用runtime field

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有tag字段的文档被划分到相同分桶中并且认为tag的值为N/a

    Execution hint

      您可以通过不同的机制运行基数聚合:

      此外,还有两种基于启发式的模式。这些模式将导致Elasticsearch使用一些关于索引状态的数据来选择合适的执行方法。这两种启发式是:

      如果未指定,Elasticsearch将应用启发式来选择适当的模式。还要注意,对于某些数据(non-ordinal fields),direct是唯一的选项,在这些情况下将忽略提示。一般而言,不需要设置这个值。

    Extended stats aggregation

    (8.2)link

      extended stats aggregation属于多值的指标聚合(multi-value metric aggregation),计算的是从被聚合的文档中提取出的数值的统计数据。

      extened_stats aggregation 是 stats aggregation的扩展版本,添加了例如sum_of_squaresvariancestd_deviationstd_deviation_bounds这些额外的指标。

      假设数据由代表学生考试成绩(0到100分)的文档组成:

      上文的聚合基于所有的文档计算了考试成绩的统计数据。聚合的类型为exteneed_stats并且field定义了文档中的数值类型的字段并计算该字段的统计数据。上面中请求的响应如下所示:

      std_deviationvariance是基于总体指标(population metric)计算的,所以它们的值分别跟std_deviation_populationvariance_population相同。

      聚合的名称(上文中的grades_stats)可以作为key,使得返回的响应中作为key来获取聚合结果。

    Standard Deviation Bounds

      默认情况下,extened_stats指标会返回一个名为std_deviation_bounds的对象,它提供了一个区间,该区间是平均值加减两个标准偏差。使得可视化数据的变化。如果你想要一个不同的边界,例如三个标准偏差,你可以在请求中设置sigma的值:

      第8行的,sigma 控制应显示均值的正负多少个标准偏差。

      sigma可以是任何非负双精度值,这意味着你可以请求非整数值,如1.5。 0也是一个有效的值,但它将只返回平均值作为上下限(uppperlower边界)。

      上下限(uppperlower边界)基于总体指标计算得来,所以它们的值分别跟upper_populationlower_population相同。

    NOTE:计算标准偏差和界限(bounds)需要数据服从正态分布 标准偏差及其边界默认会被显示,但它们并不总是适用于所有数据集。你的数据必须呈正态分布,这样这些指标才有意义。标准偏差背后的统计学假设数据是正态分布的,因此如果你的数据严重向左或向右偏斜,返回的值将是误导性的。

    Script

      如果你想要聚合的数据没有索引,可以使用runtime field假设我们发现我们一直在处理的这些成绩是来自一场超出学生水平的考试,我们想要对它进行纠正:

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Max aggregation

    (8.2)link

      单值的指标聚合(Single-value metric aggregation)计算是从被聚合的文档中提取出数值的最大值。

    NOTE:minmax aggregation是对用double表示的数据进行计算。因此,当计算long类型的数值并且绝对值大于等于2^53时,结果是一个近似值

      基于所有的文档计算price的最大值:

      响应:

      由此可见,上文中聚合的名称max_price可以作为一个key,用于在返回的响应中获取聚合结果。

    Script

      相较于在一个字段上计算max,你可以通过runtime field执行更复杂的聚合。

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Histogram fields

      如果对histogram字段进行聚合计算,聚合的结果是value数组中所有元素的最大值。注意的是,这个直方图的counts数组会被忽略。

      例如,下面的索引存储了预先聚合好的、不同网络的延迟指标直方图:

      max aggregation返回所有histogram字段中的最大值 :

    Min aggregation

    link

      单值的指标聚合(Single-value metric aggregation)计算是从被聚合的文档中提取出数值的最小值。

    NOTE:minmax aggregation是对用double表示的数据进行计算。因此,当计算long类型的数值并且绝对值大于等于2^53时,结果是一个近似值

      基于所有的文档计算price的最小值:

      响应:

      由此可见,上文中聚合的名称min_price可以作为一个key,用于在返回的响应中获取聚合结果。

    Script

      相较于在一个字段上计算min,你可以通过runtime field执行更复杂的聚合。

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Histogram fields

      如果对histogram字段进行聚合计算,聚合的结果是value数组中所有元素的最小值。注意的是,这个直方图的counts数组会被忽略。

      例如,下面的索引存储了预先聚合好的、不同网络的延迟指标直方图:

      min aggregation返回所有histogram字段中的最小值 :

    Percentile ranks aggregation

    link

    Percentiles aggregation

    link

      它属于multi-value metrics aggregation,对从文档中提出的数值类型的值计算一个或多个百分位数。可以对文档中数值类型或者histogram field的值计算。

      百分位数展示了观察值中某一特定百分比的点。例如,第95百分位数是大于95%观察值的值。

      百分位数常用于发现异常值。在正态分布中,第0.13和第99.87百分位数代表了距离平均值三个标准差。任何落在三个标准差之外的数据通常被认为是异常的。

      当获取一系列百分位数时,它们可以用来估计数据分布并确定数据是否偏斜(skewed)、双峰(bimodal)等。

      假设你的数据包含了网站加载时间。平均和中位数加载时间对管理员来说并不特别有用。最大值可能很有趣,但它很容易被单一的慢响应所偏斜。

      我们看下代表加载时间的百分位数范围:

      第7行,load_time字段必须是数值类型的字段。

      默认情况下,percentile aggregation会生成一个百分位数的范围:[ 1, 5, 25, 50, 75, 95, 99 ]。上面对应的响应可能就是:

      可见该聚合在一个默认的范围内计算每一个百分位数。如果我们假设响应时间的单位是毫秒,那么就能立刻观察到网页加载时间通常在10~725ms内,偶尔945-985ms。

    (未完成)

    Scripted metric aggregation

    link

    Scope of scripts

    Stats aggregation

    (8.2)link

      stats aggregation属于多值的指标聚合(multi-value metric aggregation),计算的是从被聚合的文档中提取出的数值的统计数据。

      统计数据包括minmaxsumcountavg

      假设数据由代表学生考试成绩(0到100分)的文档组成:

      上文的聚合基于所有的文档计算了考试成绩的统计数据。聚合的类型为stats并且field定义了文档中的数值类型的字段并计算该字段的统计数据。上面中请求的响应如下所示:

    Script

      如果你需要获取相较于单个字段、更复杂的统计数据,你可以在对一个runtime field进行聚合计算。

    Missing value

      当文档缺失聚合字段时,missing参数定义了在这篇文档中聚合字段的值。默认情况下,它们会被忽略,但是可以将它们视为具有某个值的文档。

      第7行,没有grade字段的文档被划分到相同分桶中并且认为grade的值为10。

    Sum aggregation

    link

    Top metrics aggregation

    link

    Value count aggregation

    link

    Pipeline aggregations

    link

    Bucket script aggregation

    link

    Bucket selector aggregation

    link

    Scripting

    (8.2)link

      通过编写脚本,你可以在Elasticsearch中计算自定义的表达式。比如,你可以使用脚本为一个字段返回字段值或者为一个query计算自定义的打分。

      默认的脚本语言是Painless。另外lang插件允许运行其他的余燕语言。你可以任何运行脚本的地方指定脚本语言。

    Available scripting languages

      Painless是专为Elasticsearch设计的,可以在脚本API中用于任何目的,并提供最大的灵活性。其他语言则不那么灵活,但对于特定的用途可能很有用。

    LanguageSandboxedRequired pluginPurpose
    painlessYesBuilt-inPurpose-built for Elasticsearch
    expressionYesBuilt-inFast custom ranking and sorting
    mustacheYesBuilt-inTemplates
    javaNoYou write it!Expert API

    Painless scripting language

    (8.2)link

      Painless是一种高性能、安全的脚本语言,专门为Elasticsearch设计。你可以在Elasticsearch支持脚本的任何地方安全地编写内联和存储脚本。

      Painless提供了许多功能,围绕以下核心原则:

    Start scripting

      准备开始使用Painless编写脚本了吗,见how to write your first script.

      如果你已经熟悉了Painless,可以查看Painless Language Specification 了解Painless语法和功能的详细介绍。

    How to write scripts

    (8.2)link

      无论在哪个API中编写脚本,总是按照下面的模式编写;你要指定脚本语言,提供脚本逻辑(或者脚本源,即通过标识符获取之前存储过的脚本),以及传入到脚本的参数:

    Write your first script

      Painless是Elasticsearch的默认脚本语言。它既安全又高效,并为具有一点编程经验的人提供了自然的语法。

      一个Painless脚本由一个或多个语句构成,并且在开头可选地包含一个或多个用户定义的函数。脚本必须至少包含一个语句。

      Painless execute API提供了使用简单的用户定义参数测试脚本并接收结果的能力。让我们从一个完整的脚本开始,并审查其组成部分。

      首先,索引一个只有单个字段的文档,这样我们就有了一些可以操作的数据:

      我们然后就可以编写一个脚本,并且在my_field上操作并且运行脚本,其作为查询的一部分。下面的请求使用了Search API中的script_fields参数来获取一个脚本结果。这个查询会发生很多事情,但我们会进行拆解然后一个一个的去理解。现在,你只需要知道脚本获取了my_field然后对这个字段进行操作。

      第5行,script对象   第6行,script的source,也就是脚本本身的内容

      script是一个标准JSON对象,在Elasticsearch中大多数APIs中定义。这个对象指定了source字段来提供脚本自身内容。这个脚本没有指定脚本语言,因此默认就是Painless。

    Use parameters in your script

      Elasticsearch首次遇到一个新脚本时,它会编译该脚本并将编译后的版本存储在缓存中。编译可能是一个繁重的过程。与其在脚本中hard-code,不如将它们作为在params参数中指定并传递。

      例如,在之前的脚本中,我们本可以直接hard-code,并编写一个看似较为简单的脚本。我们可以直接获取my_field的第一个值,然后将其乘以2

      虽然这个方法可行,但这个解决方案相当不灵活。我们必须修改脚本源码以改变乘数,而且每次乘数改变时,Elasticsearch都必须重新编译脚本。

      与其hard-code,不如使用params参数来使脚本灵活,并且在脚本运行时减少编译时间。现在,你可以更改乘数参数而无需Elasticsearch重新编译脚本。

      默认每5分钟可以编译最多150个脚本。对于ingest contexts,则默认没有限制:

    IMPORTANT:如果你短时间内编译太多脚本,Elasticsearch会reject新的动态脚本(dynamic)并且抛出circuit_breaking_exception错误

    Shorten your script

      利用Painless固有的语法能力,你可以减少脚本中的冗长表达,使它们更加简洁。这里有一个我们可以简化的简单脚本:

      现在我们给出一个更简短的版本看下相比较之前的有哪些提升:

      这个版本的脚本移除了几个组成部分,并显著简化了语法:

    在Elasticsearch支持脚本的任何地方使用这种简化的语法(abbreviated syntax),比如当你创建runtime fields时。

    Store and retrieve scripts

      你可以通过stored script APIs来保存和获取脚本。保存的脚本能降低编译时间使得查询更快。

    NOTE:不同于直接提供脚本自身内容,存储的脚本需要你使用lang参数显示的指定脚本语言

      你可以使用create stored script API创建一个脚本。比如,下面的请求创建了一个名为calculate-score来存储脚本。

      你可以通过get stored script API获取脚本。

      如要在query中使用存储的脚本,需要在script中指定脚本的id

      第11行,存储的脚本id

      若要删除一个脚本,则提交一个delete stored script API 请求。

    Update documents with scripts

      你可以使用update API 使用一个脚本更新文档。脚本可以更新,删除或者跳过修改文档。update API还支持传递部分文档,这部分文档将被合并到现有文档中。

      比如我们索引一篇文档:

      若要增加counter值,你可以使用下面的脚本提交一个更新请求:

      同样地,你可以使用更新脚本新增一个tag到tags列表中。因为这是一个列表,因此即使已经存在也可以添加进去:

      你也可以从tags列表中移除一个tag。Java中的remove方法在Painless也可以使用。它根据数组下标来移除。若要防止可能的runtime error,你首先需要保证tags是存在的。如果列表中包含重复的tag,这个脚本只会移除一次。

      你也可以从一篇文档中添加并且移除字段。例如下面的脚本中添加一个名为new_field的新字段:

      同样的也可以移除new_field

      你也可以根据脚本中执行的内容来修改操作。例如,下面的请求中,如果tags中包含green则删除该文档,否则什么也不做(noop):

    Scripts, caching, and search speed

    link

    Grokking grok

    link

    Common scripting use cases

    (8.2)link

      你可以编写一个脚本做大多数的事情,但有时候它也是一个麻烦。要想知道脚本能做哪些事情是比较有难度的。因此下面的例子争对了真正有帮助的常见例子进行说明:

    Field extraction

    (8.2)link

      field extraction的目的简单:你的数据有很多携带了大量信息的字段,但你只是想要提取出部分内容。

      你有两个选项可以使用:

      我们先从一个简单的例子开始,添加@timestampmessage字段作为索引字段添加到my-index索引的mapping中。为了保持灵活,message使用wildcard类型:

      定义了你想要用来检索的字段mapping后,从你的日志数据中索引一些数据到Elasticsearch。下面的请求使用了bulk API将原始的日志数据索引到my-index中。你可以使用少量的样例体验下runtime fields而不是使用你所有的日志数据。

    Extract an IP address from a log message (Grok)

      如果你想要在查询结果中包含clientip,你可以在mapping中添加runtime field。下面的runtime脚本定义了一个grok pattern从messsage字段中提取出结构化的字段。

      这个脚本匹配了%{COMMONAPACHELOG}的日志模式,它能理解Apache日志的结构。如果模式匹配了(clientip != null)。那么脚本会输出匹配到的IP地址。如果没有匹配只会返回字段值而不会出现问题

      第8行,这个条件保证了即使没有匹配到也不会输出任何信息

      你可以定义一个简单的query来查询指定的IP地址并且返回相关的字段。在search API中使用fields参数可以返回http.clientip这类runtime field。

      下面的响应中满足http.clientip的值为40.135.0.0

    Parse a string to extract part of a field (Dissect)

      相比较上面的例子中使用一个log pattern进行匹配,你可以自定义一个dissect pattern来包含你想要丢弃的string。

      比如说,日志数据开头有一个message字段。这个字段包含多个数据片段:

      你可以在runtime field定义一个dissect pattern提取出HTTP response code,也就是上面例子中的304

      你随后可以使用http.response这个runtime field检索指定的HTTP响应:

      响应中包含了单个文档,其中HTTP响应为304

    Split values in a field by a separator (Dissect)

      如果你想要像上面的例子一样提取字段中部分内容,但是你想要在指定的值上进行切分。你可以使用一个dissect pattern来只提取你想要的信息,并且以某个制定的格式返回。

      例如,比如Elasticsearch中有一些垃圾回收的日志数据,格式如下:

      你只想要提取usedcapacity以及committed对应的数据。我们先索引一些包含日志数据的文档:

      我们再次观察下数据,里面有时间戳以及其他一些你不感兴趣的数据,然后才是usedcapacity以及committed对应的数据.

      你可以在gc字段的数据中每个部分分配一个变量,然后只返回你想要的部分。用{}包含内容都是为一个变量。例如,变量[%{@timestamp}][%{code}][%{desc}]将会匹配前三个数据块,这些数据都在[]中。

      你的dissect pattern可以包含usedcapacitycommitted这些term而不是使用变量,因为你只想要返回这些term。当然你也可以分配变量给你想要返回的值,比如%{usize}%{csize}%{comsize}。在日志中的分隔符是逗号,因此你的dissect pattern同样需要使用这个分隔符。

      现在你有一个dissect pattern,你可以在Painless 脚本呢中包含它并作为runtime field的一部分。这个脚本使用你这个dissect pattern将gc字段内容分割,然后返回你在emit中定义的丝逆袭。由于dissect使用了简单的语法,你只需要准确告知你想要的东西。

      下面的pattern告诉dissect返回used这个term、空格、gc.usize的值以及一个逗号,以及其他你想要的数据。虽然这种pattern在生产环境中可能不那么有用,但它提供了大量的灵活性来实验和操作你的数据。在生产环境中,你可能只想使用emit(gc.usize),然后对该值进行汇总或在计算中使用。

      我们将上面的内容一起放在查询请求中。使用field option,你可以检索gc_size这种runtime field类型的值。这个请求同样包含了一个bucket aggregation对你的数据分组。

      响应中包含了来自gc_size的数据,跟你在dissect pattern中定义的格式完全一样。

    Accessing document fields and special variables

    (8.2)link

      根据你脚本运行的位置,有不同的可以访问的变量以及文档字段。

    Update scripts

      updateupdate-by-queryreindex中使用脚本时可以访问ctx变量:

    Search and aggregation scripts

      除了每次搜索命中时执行一次的script field外,用于搜索和聚合的脚本将对可能匹配查询或聚合的每个文档执行一次。根据你拥有的文档数量,这可能意味着执行了数百万次或数十亿次:这些脚本需要快速执行!

      字段值可以通过使用文档值(doc-values)、_source字段或stored fields从脚本中访问,每种方式如下所述。

    Accessing the score of a document within a script

      function_score queryscript-based sortingaggregations中使用脚本时,可以访问_score变量,它代表了一篇文档的相关性打分。

      下面的例子中在function_score query 中使用了脚本来修改每一篇文档的相关性打分:

    Doc values

      目前为止在脚本中访问字段最快的方式就是使用doc['field_name']语法,它从doc values中提取字段值。Doc Values是列式存储,除了analyzed text field,其他类型字段mapping都是默认开启的。

      Doc-values可以返回"简单的"字段值比如数值、日期、地理值、term等等或者当字段是多值字段时返回一个数字。不能返回JSON对象。

    NOTE:Missing fields 如果field缺失的话,doc['field']会抛出异常。在painless中,可以首先通过doc.containsKey('field')进行检查使得安全访问doc。不过无法在expression中检查mapping中的字段在文档中是否存在

    NOTE:Doc Values and text fields doc['field']语法同样可以用于analyzed text fields,前提是开启了fielddata注意的是,开启后会将所有的term加载到JVM堆中,对于内存和CPU的开销都很大。在脚本中访问text字段往往没有什么意义

    The document _source

      可以通过_source.field_name语法访问文档的_source_source作为map-of-maps的方式加载,因此在对象字段(object field)中的属性也可以访问。比如_source.name.first

    IMPORTANT:Prefer doc-values to_source 访问_source往往比doc-values要慢,_source字段在每一个结果中用于返回一些字段时有优化,而doc values在许多文档中访问某个字段的值时有优化。

    在查询结果中为前10个命中生成script field时使用_source比较合适,而在其他查询和聚合用例中,通常使用doc valus更合适。

      比如:

    Stored fields

      Stored fields也即是mapping参数定义了"store": true,可以使用_fields['field_name'].value或者_fields['field_name']的语法。

    TIP:Stored vs _source _source字段其实是一个特殊的stored field,因此性能上跟其他的stored fields是相似的。_source可以访问原始的文档内容(包括原始文档中某些因为空值而在索引过程中被移除,简单的标量值在索引后变成单值的数组)

    只有在_srouce特别大时使用stored fields才有意义,因为这样只会加载指定的较小的stored field而不是加载整个_source

    Data management

    (8.2)link

      你在Elasticsearch中存储的数据通常是下面类别中的一种:

      Content可能会经常更新,但是Content的价值随着时间的流逝仍然是相对不变的。你可能想要快速的获取items,并且不关心这些数据的新旧。

      时序数据(Time series data)随着时间的流逝(over time)不断的增长(accumulate),所以你需要平衡存储开销和数据的价值的策略。这些数据随着时间的推移(as it ages),变的不重要并且很少被访问。所以你可以将数据移动到更低成本,更低性能的硬件中。对于最旧的数据(for your oldest data),最重要的是你仍然可以访问它,但是如果查询时间很长也是可以接受的。

      Elasticsearch可以基于下面的内容帮你管理你的数据:

    ILM: Manage the index lifecycle

    (8.2)link

      你可以通过配置index lifecycle management(ILM),根据你的性能、弹性(resiliency)、保留(retention)需求来自动的管理索引。你可以使用ILM用于:

      你可以通过Kidddbana Management或者ILM接口来创建管理索引生命周期策略。当你使用Elastic Agent、Beats、或者Logstash时会自动创建默认的ILM策略。

    Tips: 使用snapshot lifecycle policies自动备份你的索引以及管理snapshot。

    Tutorial: Customize built-in ILM policies

    (8.2)link

      Elasticsearch包含了下列内置的ILM策略

      Elastic Agent使用这些策略为data streams管理backing索引。这个教程展示如何基于你的性能、弹性(resiliency)、保留(retention)需求使用Kibana的Index Lifecycle Policies来自定义策略。

    Scenario

      你想要将日志文件发送给Elasticsearch集群用于可视化和分析数据,这些数据有下列的保留需求(retention requirement)

    Prerequisites

      要完成这个教程,你需要准备下面的内容:

      例如,在warm tier中的每一个节点的elasticsearch.yml中包含data_warm的节点角色:

      安装Elastic Agent并配置为将日志发送到你的Elasticsearch集群。

    View the policy

      Elastic Agent使用index pattern为logs-*-*的data streams来存储日志监控数据。内置的logsILM策略自动的为data stream管理backing indices。

      若要在Kibana中查看logs策略:

    1. 打开菜单并进入Stack Management > Index Lifecycle Policies

    2. 选择logs策略

      logs策略使用了默认推荐的rollover:当前write index的大小达到50GB或者30天后就开始写入到新的索引。

      若要查看或者修改rollover设置,点击hot阶段的Advanced settings 。然后关闭Use recommended defaults来展示rollover设置。

    Modify the policy

      默认的logs策略设计为防止生成很多小的按日创建的索引。你可以修改这个策略来满足你的性能要求以及资源使用管理。

    1. 激活warm阶段并点击Advanced settings

      1. 设置Move data into phase when30 days old。这个索引在滚动后的30天移动到warm阶段

      2. 开启Set replicas并修改Number of replicas1

      3. 开启Force merge data并设置Number of segments1

    1. 在warm阶段,点击trash 图标来开启delete阶段。

      在delete阶段,将Move data into phase when设置为90 days old。这个索引在滚动后30天被删除。

    1. 点击Save Policy

    Tutorial: Automate rollover with ILM

    (8.2)link

      当你不停的将带有时间戳的文档索引到Elasticsearch中,你通常会使用data stream,使得你可以周期性的滚动(roll over)到一个新的索引。能让你实现一个 hot-warm-cold的架构,为你的最新数据满足性能要求,控制随着时间增加的成本,执行保留策略,并且能最大力度利用你的数据(get the most out of your data)。

    TIP:Data streams最适合用于append-only的用例。如果你需要跨多个索引经常更新或者删除现有的文档,我们建议你使用一个index alias和index template。你仍然可以用ILM来管理并且rollover alias indices。直接跳到Manage time series data without data streams

      若要使用ILM自动的rollover并且管理一个data stream,你可以:

    1. Create a lifecycle policy来定义合适的阶段和动作

    2. Create an index template来创建data stream以及应用ILM策略, 为backing index配置索引设置和mapping

    3. Verify indices are moving through the lifecycle phases as expected

      rollover了解rolling indices。

    IMPORTANT:When you enable index lifecycle management for Beats or the Logstash Elasticsearch output plugin, lifecycle policies are set up automatically. You do not need to take any other actions. You can modify the default policies through Kibana Management or the ILM APIs.

    Create a lifecycle policy

      生命周期策略指定了索引生命周期的阶段以及在每一个阶段中需要执行的动作。一个生命周期可以有最多5个阶段:hotwarmcoldfrozendelete

      例如,你可能定义了一个timeseries_policy,它有两个阶段:

    NOTE:min_age是相对于滚动的时间而不是索引的创建时间。

      你可以通过Kibana或者create or update policy API来创建策略。若要通过Kibana创建策略,打开菜单并进入Stack Management > Index Lifecycle Policies,点击Create policy

      API例子:

      第5行,min_age默认值是0ms,所以新的索引会马上进入到hot阶段   第8行,满足任意一个后就触发rollover动作   第14行,滚动后90天将索引移动到delete阶段   第16行,当索引进入到delete阶段后触发delete动作

    Create an index template to create the data stream and apply the lifecycle policy

      若要建立一个data stream, 首先创建一个index template来定制生命周期策略。因为模板用于data stream,所以它必须包括data_stream的定义。

      例如,你可能创建一个名为timeseries_template的模板用于一个名为timeseries的data stream。

      你可以使用Kibana创建模板向导程序来添加模板。在Kibana中,打开菜单并进入Stack Management > Index Management。在Index Templates页,点击Create template

      向导程序调用create or update index template API并使用你指定的选项创建index template。

      API例子:

      第3行,当文档索引到timeseries中时应用这个模板   第8行,使用ILM策略的名称来管理data stream

    Create the data stream

      索引一篇文档到index template中定义的名称或定义在index_patterns中的wildcard pattern中。只要现有的data stream,索引或者index alias没有使用这个名称,那么索引请求会自动的创建单个backing index和其对应的data stream。Elasticsearch自动的将请求的文档索引到backing index中,这个backing index作为这个流的write index

      例如,下面的请求创建了名为timeseries的data stream并且首先创建了first generation名为.ds-timeseries-2099.03.08-000001的backing index。

      当生命周期策略中的rollover条件满足后,rollover动作就会:

      每次rollover 条件满足后就重复上面的处理过程。你可以跨data stream中所有的backing indices进行查询。由名为timeseries的data steam,名为timeseries_policy的策略管理。写操作被路由到当前的write index。读操作由所有的backing indices处理。

    Check lifecycle progress

      若要获得管理中的索引(managed index)的状态,你可以使用ILM explain API,能让你获得:

      例如,下面的请求获取了名为timeseries 的data stream的backing indices的信息:

      下面的响应显示data stream的first generation backing index正在等待hot阶段中的rollover动作。它仍在这个状态并且ILM继续调用check-rollove-ready直到rollover的条件满足:

      第6行,age of the index,用于跟max_age计算出rollover的时间   第8行,管理这个索引的策略名称   第10行,age of the indexed,用于转移到下一个阶段(在这个例子中跟age of the index一样)   第15行,ILM在这个索引上正在执行的步骤   第19行,当前阶段的定义(hot阶段的定义)

    Manage time series data without data streams

      尽管data streams是用于扩展和管理时序数据的一种便捷方式,它们被设计为用于append-only。我们认识到存在一些用例需要就地(in place)更新或者删除数据并且data streams不支持直接删除跟更新请求,所以Index APIs需要直接用于data stream的backing indice上。

      在这些情况下,你可以使用index alias来管理包含时序数据的索引并且周期性的roll override到一个新的索引。

    若要使用ILM并使用index alias来自动的rollover以及管理时序数据,你需要:

    1. 创建一个生命周期策略,定义合适的阶段和动作,见Create a lifecycle policy

    2. Create an index template将策略应用到每一个新的索引

    3. Bootstrap an index作为最开始的write index

    4. Verify indices are moving through the lifecycle phases as expected

    Create an index template to apply the lifecycle policy

      若要在rollover上自动的将生命周期策略应用到新的write index上,那么在用于创建新索引的index template中指定策略。

      例如,你可能创建了一个timeseries_template的模板,它将应用到索引名匹配了timeseries-*index pattern的索引。

      若要自动的rollover,那么在模板中配置两个ILM设置:

      你可以使用Kibana创建模板向导程序来添加模板。若要访问向导程序,打开菜单并且进入Stack Management > Index Management。在Index Templates页面,点击Create template

      创建模板请求:

      第3行,模板将应用到索引名以timeseries-开头的索引上   第8行,生命周期策略的名称,将应用到每一个新的索引上   第9行,alias的名称用于引用这些索引,要求策略使用rollover动作。

    Bootstrap the initial time series index with a write index alias

      你需要引导一个最开始的索引并且为你模板中的rollover alias将这个索引指为write index。这个索引的名称必须匹配模板中的index pattern并且以数字结尾。在滚动时,这个数字会递增用于生成新的索引的名称。

      例如,下面的请求创建了一个名为timeseries-000001的索引,并且让它作为名为 timeseries 的alias的write index。

      当满足了rollover的条件,rollover动作就会:

    Check lifecycle progress(index)

      对管理中的索引获取其状态信息类似于data stream,见check progress section 了解更多信息。唯一的不同是 indices namespace,so retrieving the progress will entail the following api call:

    Index management in Kibana

    (8.2)link

      Kibana的Index Management 功能是一种简单方便的用于管理你集群的索引,data streamsindex template的方法。实践良好的(practising)索引管理可确保以最具成本效益的方式正确存储数据。

    What you’ll learn

      你将会学习到如何:

    Required permissions

      如果你使用了Elasticsearch security feature,则需要下面的security privileges

      若要在Kibana中添加这些privilege,进入Stack Management > Security > Roles

      Index Management页面包含了你的索引概览。索引名旁边的标签(badge)告知这个索引是一个follower indexrollup index,还是一个frozen

      点击某个标签后将只显示这个标签类型的索引。你也可以用搜索框过滤索引。

      你也可以下钻每一个索引来查看index settingsmapping和statistic。在这个视图中,你也可以编辑index settings。

    Perform index-level operations

      使用Manage菜单执行index-level的操作。这个菜单在索引详情视图中可见,或者当你在索引概览页面选择一个或多个索引时可见。菜单包含了下面的动作:

    Manage data streams

      Data Streams视图中列出了你的data steams并且能让你测试或者删除它们。

      若要查看data stream的更多的信息,比如它当前的generation或者当前的索引生命周期策略,那么点击流的名称。

      若要查看backing index的信息,点击该索引即可。

    Manage index templates

      Index Templates视图中列出了你的模板以及测试,编辑,克隆和删除。对某个index template的更改不会影响现有的索引。

      如果你还没有任何的模板,你可以使用Create template向导程序创建模板。

    Try it: Create an index template

      在这个教程中,你将会创建一个模板然后使用它配置两个新的索引。

    1. Index Templates视图中,打开Create template的向导程序

    1. Name中,输入my-indeex-template

    2. 设置Index patternmy-index-*,使得模板匹配这种Index pattern的索引

    3. 不填写Data streamPriorityVersion以及_meta field

    1. 添加component templates到你的index template中

      Component templates是预先配置好的mappings, index settings, and aliases的集合,你可以跨多个Index template使用。标签指出了某个component template是否包含mappings(M),Index settings(S),aliases(A),或者是三者都有。

      Component templates是可选的,对于这个教程,不要添加任何的component templates。

    1. 定义Index settings(可选)。对于这个教程,可以不填

    2. 定义一个mapping,它包含一个名为geo类型为object字段,以及名为coordinates类型为geo_point的子字段(child filed)

      或者你可以点击Load JSON,用JSON形式定义mapping:

      你可以在Dynamic templatesAdvanced options页面创建额外的mapping配置。对于这个教程,不创建任何额外的mappings。

    1. 定义名为my-index的alias:

    1. 在review 页面,检查整体的配置。如果一切看起来没有问题就点击Create template

      你现在可以使用你的index template来创建新的索引

    1. 索引下面的文档创建两个索引:my-index-000001my-index-000002

    1. 使用get index API查看新索引的配置,这个索引使用了你之前创建的index template。

    ILM overview

    (8.2)link

      你可以创建以及应用(apply)索引生命周期管理(ILM:index lifecycle management)并依据性能、弹性(resiliency)、保留(retention)需求来管理你的索引。

      索引生命周期策略能触发下列的动作:

      ILM使得在热-暖-冷数据架构中管理索引变得更加容易。这种架构在处理比如日志(logs)、指标(metrics)这类时序数据中非常常见。

      你可以这么指定:

      例如,当你将成群的ATMs的指标数据写入到Elasticsearch中时,可以定义下面的策略:

    IMPORTANT:想要使用ILM必须保证每个节点的版本号是一致的。在一个版本号混在的集群中使用ILM可能可以创建并应用策略,但是不能保证可以按照预期运行。在集群中尝试使用一个策略时,如果其对应的动作(action)不是所有节点都支持的话会引发错误。

    ILM concepts

    (8.2)link

    Index lifecycle

    (8.2)link

      ILM定义了五个生命周期阶段:

      一个索引的生命周期策略指定了哪个阶段是适用的(applicable)、在每一个阶段执行哪些动作、什么时候转变阶段(transition between phases)。

      在你创建索引时可以手动应用一个生命周期策略。对于时序索引(time series indices),你需要用index template在时序中创建新的索引,并且将生命周期策略关联到index template。当(rollover)索引时,手动应用的策略不会自动应用到新索引。

      如果你使用Elasticsearch的安全功能。ILM将以最后更新策略的用户的身份执行操作。ILM only has the roles assigned to the user at the time of the last policy update。

    Phase transitions

      ILM根据生命周期中的寿命(age)来移动索引(move index)。你可以在每一个阶段设置一个寿命最小值(maximum age)来控制转变的时机(the timing of transition)。对于一个索引移动到另一个阶段来说,当前阶段的所有动作都必须已经完成并且the index must be older than the minimum age of the next phase。下一个阶段配置的最小寿命必须高于当前阶段。比如说warm阶段的寿命设置为10天,那么下一个阶段,即cold阶段的寿命要么不设置,要么设置成一个大于等于10天的值。

      寿命最小值默认值为0,意味着当前阶段所有的动作都完后就马上转变到下一个阶段。

      如果索引有未分配的分片,并且cluster health status的状态为yellow,仍然可以根据生命周期策略转移到下一个阶段。然后由于Elasticsearch只会在状态为green的集群上执行相关的clean up工作,所以可能会有不可预料的副作用。

      为了避免不断增加的磁盘使用量和可靠性问题,请及时处理集群运行状况问题。

    Phase execution

      ILM控制了一个阶段中所有动作的执行顺序以及执行步骤来执行必要的索引操作。

      当索引进入到一个阶段,ILM缓存索引元数据(index metadata)中的阶段定义(phase definition)。这使得不会因为更新策略将索引置入一个用于无法退出阶段的状态。如果可以安全的应用变更,ILM会更新已经缓存的阶段定义。如果不能,则使用缓存的定义继续执行下去。

      ILM会周期的运行检查某个索引是否满足策略规则(policy criteria)并执行必要的步骤。为了避免race condition,ILM可能需要执行多次才能执行所有的步骤,每一个步骤都需要完成一个动作。例如,如果ILM检测到一个索引满足滚动规则,它开始执行这个步骤并且要求完成这个滚动动作。如果它到达了一个点使得不能安全的进行入到下一步骤,那么终止执行。下一次ILM运行后,它会继续执行(pick up execution where it left off)。这意味着即使indices.lifecycle.poll_interval设置为10分钟并且索引满足滚动规则。也有可能需要20分钟来完成滚动。

    Phase actions

      ILM支持每一个阶段中以下的动作,ILM有序执行这些动作。

    Rollover(concept)

    (8.2)link

      当索引日志或者指标这类时序数据的时候,你不能往单个索引中无限的写入。为了能满足你的索引和查询性能要求以及资源使用的管理,你往一个索引中写入数据直到满足阈值,然后再创建一个新的索引,并开始写到这个索引中。使用 rolling indices可以让你:

      我们建议使用data streams来管理时序数据。Data streams自动的跟踪write index并且保持配置最小化。

      每一个data stream要求一个index template,模板中包括:

      Data streams为append-only data设计,data stream name可以用于作为操作(read,write,shrink等等)目标。如果你的用例要求就地(in place)更新数据。你可以使用index aliases来管理你的时序数据。然而需要一些配置步骤以及概念:

    Automatic rollover

      ILM能让你自动的基于索引大小(index size)、文档数量(document count),寿命(age)滚动(roll over)到一个新的索引。当触发了一个rollover,就会创建一个新的索引。write alias会被更新指向新的索引,接下来的更新都会写入到新的索引中。

    TIP:基于大小,文档数量,或者寿命的滚动比基于时间(time-based)的更可取(prefer)。在任意的时间(arbitrary time)进行rolling over经常会生成小的索引,对性能和资源使用有负面的影响。

    Lifecycle policy updates

    (8.2)link

      你可以通过修改当前的策略或者切换到一个不同的策略来改变索引的生命周期或者rolling indices的收集的管理。

      为了保证更新策略后不会让某个索引进入到某个状态后无法退出当前的阶段,因此在进入阶段后,阶段定义(phase definition)缓存在index metadata中。如果能安全的应用变更,ILM就更新缓存的阶段定义。如果不能,使用缓存的定义继续阶段的执行。

      当索引进入到下一个阶段,它会使用更新后的策略中的阶段定义。

    How changes are applied

      当某个策略最开始应用到某个索引时,索引获取到了最新的策略版本号。如果你更新了策略,策略的版本号将被变更,ILM能检测侧到索引正在使用一个较早版本的策略,这个策略需要更新。

      min_age的更改不会propagate到缓存的定义。修改一个阶段的min_age不会影响当前正在执行那个阶段的索引。

      例如,如果你创建了一个策略包含了一个hot 阶段并且没有指定min_age。当应用策略后,索引马上进入到这个阶段。如果你随后更新了策略并指定了值为一天的min_age。那不会影响已经进入到hot阶段的索引。策略更新后,新创建的索引只有等到一天后才能进入hot阶段。

    How new policies are applied

      当你应用一个策略来管理索引,索引会使用上一个策略来完成当前的策略。索引会在进入到下一个阶段时使用新的策略。

    Index lifecycle actions

    (8.2)link

    Allocate将分片移到性能特征(performance characteristic)不同的节点上并减少副本的数量
    Delete永久移除索引
    Force Merge减少索引中段的数量并且清楚(purge)被删除的文档。索引被置为只读
    Migrate将索引的分片迁移到当前ILM阶段对应的数据层(data tier)中
    Read-Only阻塞索引的写入操作
    Rollover为rollover alias移除作为write index的索引,并开始为新索引建立索引
    Searchable Snapshot在配置好的仓库中添加一个被管理的索引的快照,挂载这个快照使其成为一个可以用于搜索的快照。
    Set Priority降低索引在生命周期中的优先级,以确保首先恢复hot索引
    Shrink收缩到新的索引中并减少主分片的数量
    Unfollow将一个follower index转化为常规索引。会在执行rollover、shrink、searchable snapshot动作前自动执行该动作
    Wait For Snapshot保证在删除索引前已经创建好了snapshot

     

    Allocate

    (8.2)link

      可以在warm、cold阶段使用该动作(action)。

      更新(update)索引设置来变更(change)哪些节点允许存放(host)索引分片以及变更副本分片(replica)的数量。

      不允许在hot阶段执行这个allocate动作。索引最初的分配必须通过手动或者index template实现。

      你可以配置这个动作来同时修改分配规则(allocation rules)和副本数量,只修改分配规则或者只修改副本数量。见Scalability and resilience了解更多Elasticsearch如何使用副本来实现伸缩性(scaling)的信息。见index-level shard allocation filtering了解更多Elasticsearch如何控制指定索引的分片分配。

    Options

      你必须指定副本的数量或者至少包含一个includeexcluderequire选项。空的allocate动作是非法的。

      Index-level shard allocation filtering了解更多使用自定义属性进行分片分配的信息。

    Example

      下面的策略中的allocate动作将索引的副本分片数量更改为2。在任何单个节点上放置的索引分片不超过200个。否则不改变索引分配规则。

    Assign index to nodes using a custom attribute

      下面策略中的allocate动作将索引分配到一些节点,这些节点需要包含值为hot或者warmbox_type属性。

      为了指明(designate)一个节点的box_type,你可以在节点配置(node configuration)中设置这个自定义的属性。例如说,在elasticsearch.yml中设置node.attr.box_type: hot。见Enabling index-level shard allocation filtering了解更多信息。

    Assign index to nodes based on multiple attributes

      allocate动作可以基于多个节点属性将索引分配到节点。下面的allocate动作基于box_typestorage这两个节点属性进行索引的节点分配。

    Assign index to a specific node and update replica settings

      下面策略中的allocate动作会将索引的副本分片数量更新为1个并且索引会被分配到带有值为coldbox_type属性的节点中。

      为了指明(designate)一个节点的box_type,你可以在节点配置(node configuration)中设置这个自定义的属性。例如说,在elasticsearch.yml中设置node.attr.box_type: cold。见Enabling index-level shard allocation filtering了解更多信息。

    Delete

    (8.2)link

      可以在delete阶段使用该动作。

      永久移除索引。

    Options
    Example

    Force merge(action)

    (8.2)link

      可以在hot、warm阶段使用该动作。

      Force merge将索引合并到指定数量的segments中,这个动作会另索引变为read-noly

    NOTE:forcemerge这个动作属于best effort。这个动作有可能在一些分片正在分配时执行,在这种情况下这些分片不会进行合并。

      hot阶段使用forcemerge动作需要有rollover动作。如果没有配置rollover动作,ILM会reject这个策略。

    Performance considerations

      Force merge是一个资源密集型(resource-intensive)的操作。如果一次性触发太多的force merge,将会对你的集群造成负面的影响。这种情况经常发生在你将一个包含force merge动作的ILM策略应用到现有的(existing)索引中。如果这些索引满足min_age规则(criteria),它们会马上被处理并经历多个阶段。你可以通过提高min_age或者设置index.lifecycle.origination_date来修改计算索引寿命的方式来阻止这种情况。

      如果发生了force merge任务队列堆积,你可能需要增加force merge线程池的大小,使得索引可以并行的进行force merge。你可以通过配置thread_pool.force_merge.size 进行更改cluster setting

    IMPORTANT:这种操作会造成持续性的(cascading)性能影响,监控好集群的性能并且提高线程池的大小慢慢的减少堆积。

      Force merge动作会根据索引处于的阶段在对应的节点执行。处于hot阶段的forcemerge会在潜在较快的hot节点执行,同时对提取(ingestion)影响更大。处于warm阶段的forcemerge会在warm节点执行,执行时间会潜在较长,但是不会影响hot层的提取(ingestion)。

    Option

    WARNING:如果使用best_compression,ILM将在force merge之前先close并且re-open。当关闭后,索引的读写操作将不可见。

    Example

    Migrate

    (8.2)link

      可以在warm、cold阶段使用该动作。

      通过更新索引设置index.routing.allocation.include._tier_preference将索引移动到当前阶段对应的data tier中。ILM自动在warm和cold阶段注入(inject)该动作。如果要阻止自动迁移(migration),你可以显示指定migrate动作,并且将enabled参数设置为false

      If the cold phase defines a searchable snapshot action the migrate action will not be injected automatically in the cold phase because the managed index will be mounted directly on the target tier using the same _tier_preference infrastructure the migrate actions configures。

      warm阶段,如果index.routing.allocation.include._tier_preference设置为data_warmdata_hot,会将索引移动到warm tier的节点上。如果没有一个节点是warm tier,那么就移动到 hot tier

      cold阶段,如果index.routing.allocation.include._tier_preference设置为data_colddata_warmdata_hot,会将索引移动到Cold tier的节点上。如果没有一个节点是cold tier,那么就移动到warm tier,否则移动到hot tier。

      frozen阶段不允许执行migrate动作。这个阶段会直接将searchable snapshot挂载到data_frozen,data_cold,data_warm,data_hot中的一个。先移动到frozen tier,如果没有一个节点是frozen tier,则移动到cold tier,否则移动到warm tier,最终移动移到hot tier。

      hot阶段不允许执行migrate动作。最初索引的分配是自动执行的,可以通过手动或者index template配置。

    Option
    Example

      下面的策略中,ILM将索引迁移到warm node前先通过allocate动作减少副本的数量。

    NOTE:显示指定开启migrate动作是不需要的,ILM会自动执行migrate动作除非你关闭迁移。

    Disable automatic migration

      下面的策略中关闭了migrate动作并且将这个索引分配那些配置了rack_id的值为one或者two的节点。

    Read only

    (8.2)link

      可以在hot、warm、cold阶段使用该动作。

      使得索引变成只读,不再允许写入和元数据变更(metadata changes)操作。

      hot阶段使用readonly动作必须同时配置rollover动作。如果没有配置rollover动作,ILM会reject这个策略。

    Options

      

    Example

    Rollover(action)

    (8.2)link

      可以在hot阶段使用该动作。

      当现有的索引满足一个或者多个滚动(rollover)条件后滚动到一个新的索引。

    IMPORTANT:如果rollover动作应用在一个follower index,执行策略前需要等待leader index滚动结束(或者otherwise marked complete),然后通过unfollow动作将follower index转化为一个常规索引(regular index)。

      滚动对象可以是data stream或者index alias。当滚动对象是数据流(data stream)时,新的索引会变成数据流的write index并且提高它的generation。

      要滚动一个index alias,alias和它的的write index必须满足下面的条件:

      例如如果my-index-000001是名为my_data的alias。那么必须配置下面的设置:

    Options

      你必须至少指定一个rollover条件。没有条件的rollover动作是非法的。

    Example
    Roll over based on largest primary shard size

      下面的例子中,当最大的主分片的大小达到50gb则滚动这个索引。

    Roll over based on index size

      下面的例子中,当索引大小至少100g则滚动这个索引。

    Roll over based on document count

      下面的例子中,当索引中包含了至少了100000000篇文档后滚动这个索引。

    Roll over based on document count of the largest primary shard

      在这个例子中,当这个索引中最大的主分片中的文档数量至少有一千万时滚动这个索引。

    Roll over based on index age

      在这个例子中,索引在创建后已经至少过了7天后滚动这个索引。

    Roll over using multiple conditions

      当你指定了多个滚动条件时,任何一个条件满足都会触发滚动。这个例子中,要么索引在创建后已经至少过了7天后或者当索引大小至少100g时触发滚动。

    Rollover condition blocks phase transition

      只有至少一个滚动条件满足才会完成rollover动作,这意味着任何接下来的阶段在滚动成功前都会被阻塞住。

      例如,下面的策略在索引滚动后就删除索引。在索引创建后的一天内不会去删除这个索引。

    Searchable snapshot

    (8.2)link

      可以在hot、cold、frozen阶段使用该动作。

      在配置好的仓库中对被管理的索引(managed index)生成一个快照并且挂载它作为一个searchable snapshot。如果这个索引是data stream的一部分,被挂载的索引将替换流中的原来的索引(original index)。

      searchable_snapshot动作需要数据层(data tiers),这个动作使用index.routing.allocation.include._tier_preference参数来挂载不同阶段对应的数据层(data tiers)的索引。在frozen阶段,这个动作会挂载到frozen层中前缀为partial-partially mounted index。在其他阶段,这个动作会挂载到对应数据层中前缀为restored-fully mounted index

    WARNING:不要同时在hot跟cold阶段包含searchable_snapshot动作。这样会导致在cold阶段索引无法自动迁移(migrate)到cold tier。

      如果在hot阶段使用了searchable_snapshot动作,那么接下来的阶段中不能包含shrink或者forcemerge动作。

      这个动作不能在数据流的write index上执行。尝试这种操作会导致失败。为了可以将数据流中的索引转化为searchable snapshot,可以先manually roll over数据流,这将创建一个新的write index。因为这个索引不再是流的write index,所以当前动作可以将其转化为searchable snapshot。使用一个策略,在这个策略中的hot阶段使用rollover动作可以避免这种情况以及不需要为未来被管理的索引作手动滚动。

    IMPORTANT:挂载并且重分配searchable snapshot的分片涉及到从snapshot仓库中拷贝分片内容。This may incur different costs from the copying between nodes that happens with regular indices。这些开销通常很低,但是在有些环境可能会很高。见Reduce costs with searchable snapshots了解更多内容。

      默认情况下,snapshot会在delete阶段被delete动作删除,可以通过在delete动作中设置delete_searchable_snapshotfalse的方式来保留这个snapshot。

    Options

      合并操作在searchable_snapshot动作之前执行。如果在hot阶段使用searchable_snapshot动作,force merge将在hot节点上执行。如果在cold阶段使用searchable_snapshot动作,force merge将在hot或者warm阶段执行。

    Example

    Set priority

    (8.2)link

      可以在hot、warm、cold阶段使用该动作。

      一旦策略进入hot、warm或cold阶段,就设置索引的priority。节点重启后,优先级高的索引会在优先级低的索引之前恢复。

      通常来说在hot阶段的索引应该有最高的优先级并且在cold阶段的索引应该有最低的优先级。例如:hot阶段的值为100,warm阶段的值为50,cold阶段的值为0。没有设置的话则优先级的默认值为1。

    Options
    Example

    Shrink

    (8.2)link

      可以在hot、warm阶段使用该动作。

      将源索引(source index)设置为read-only并且收缩(shrink)到一个新的索引中,这个索引有很少的主分片(fewer primary shards)。生成的索引名称为shrink-<random-uuid>-<original-index-name>。这个动作对应于 shrink API

      shrink动作执行后,那些指向源索引的aliases会指向收缩后的索引(shrunken index)。如果ILM在一个数据流(data stream)的backing index上执行收缩操作时,收缩后的索引会替代流中的源索引。你不能在一个写索引(write index)上执行shrink动作。

      如果要在hot阶段使用shrink动作,必须同时配置rollover动作。如果没有配置rollover动作,ILM会reject这个策略。

      shrink动作会移除索引的index.routing.allocation.total_shards_per_node设置,意味着将取消限制。这个操作能保证索引的所有分片都被拷贝到同一个节点上。This setting change will persist on the index even after the step completes。

    IMPORTANT:如果收缩动作在follower index上使用,执行策略前需要等待leader index滚动结束(或者otherwise marked complete),然后在执行shrink动作前先通过unfollow动作将follower index转化为一个常规索引(regular index)。

    Shrink options
    Example
    Set the number of shards of the new shrunken index explicitly
    Calculate the optimal number of primary shards for a shrunken index

      下面的策略使用max_primary_shard_size参数基于源索引中的存储大小自动的计算新的收缩后(shrunken)的索引的主分片的数量。

    Shard allocation for shrink

      shrink动作执行期间,ILM将源索引的主分片分配到一个节点。在收缩完索引后,ILM基于你的分配规则将收缩后的索引分片分配给合适的节点。

      这些分配步骤会因为下面的一些原因而导致失败,包括:

      当分配步骤的其中一步失败后,ILM会等待index.lifecycle.step.wait_time_threshold,默认值为12小时。这个阈值会周期性让集群去解决任何导致分配失败的问题。

      如果过了这个周期性的字段值时间并且ILM还没有收缩完索引,ILM会尝试将源索引的主分片分配到其他节点。如果ILM收缩完索引但是不能在这个周期性的字段值时间内重新分配收缩后的索引,ILM会删除收缩后的索引并且重新尝试整个shink动作。

    Unfollow

    (8.2)link

      可以在hot、warm、cold、frozen阶段使用该动作。

      将一个CCR follower index转变为常规索引(regular index),使得shrink、rollover、以及searchable snapshot动作可以在follower index上安全的执行。你可以在生命周期中移动follower index时直接使用unfollow。该动作不会对非follower index产生影响,阶段中执行该动作只是继续做下一个动作。

    NOTE:如果是应用在follower index上,这个动作会被rollovershrink以及searchable snapshot动作自动触发。

      这个动作会一直等到安全的将一个follower index转化为常规索引才会执行,必须满足下面的条件:

      一旦满足条件,unfollow动作将执行下面的操作:

    Options

      

    Example

    Wait for snapshot

    (8.2)link

      可以在delete阶段使用该动作。

      在移除索引前等待指定的SLM策略执行结束。使得被删除的索引的snapshot是可见的。

    Options
    Example

    Configure a lifecycle policy

    (8.2)link

      为了让ILM能够管理一个索引,必须在索引设置 index.lifecycle.name中指定一个合法的策略。

      若要为rolling indices配置一个生命周期策略,你需要创建一个策略然后添加到index template中。

      若要使用策略来管理一个不进行roll over的索引,你可以在创建索引的时候指定一个生命周期策略,或者将一个策略应用到已存在的索引上。

      ILM 策略存储在全局cluster state中,当你take the snapshot时,你可以将include_global_state设置为true,使得在snapshot中包含策略。当存储snapshot后,会存储全局state中的所有策略并且任意相同名称的本地策略会被覆盖。

    IMPORTANT: When you enable index lifecycle management for Beats or the Logstash Elasticsearch output plugin, the necessary policies and configuration changes are applied automatically. You can modify the default policies, but you do not need to explicitly configure a policy or bootstrap an initial index.

    Create lifecycle policy

      若要从Kibana中创建一个生命周期策略,打开菜单然后跳转到Stack Management > Index Lifecycle Policies。点击 Create policy

      为策略指定生命周期策略的阶段以及每一个阶段中的动作(action)。

      create or update policy被调用后,策略被添加到Elasticsearch 集群中。

      第8行,当索引大小达到25G后进行滚动(roll over)   第16行,在滚动后的30天后删除索引

    Apply lifecycle policy with an index template

      若要使用策略来触发rollover动作,你需要在index template中配置策略用于创建每一个新的索引。你指定策略的名称和alias用于引用rolling indices。

      你可以使用Kibana创建模板向导程序来创建一个模板。若要访问向导程序,打开菜单并且进入Stack Management > Index Management。在Index Template页面,点击Create template

      向导程序调用了create or update index template API将模板添加到集群。

      第3行,使用这个模板用于所有索引名以test-开头的新的索引   第8行,应用my_policy到使用这个模板创建的索引上   第9行,定义一个index alias用于引用被my_policy管理的索引

    Create an initial managed index

      当为你自己的rolling indices设置策略时,你需要手动创建由策略管理的第一个索引,并且授权(designate)这个索引为write index。

    IMPORTANT: When you enable index lifecycle management for Beats or the Logstash Elasticsearch output plugin, the necessary policies and configuration changes are applied automatically. You can modify the default policies, but you do not need to explicitly configure a policy or bootstrap an initial index.

      索引的名称必须匹配定义在index template中的pattern并且以数字结尾。递增这个数字来生成由rollover动作创建的索引的名称。

      例如,下面的请求创建了一个名为test-00001的索引。因为它匹配到了my_template中的index pattern,Elasticsearch自动的从这个应用这个模板中的设置。

      第5行,为这个alias设置最初的索引作为write index

      现在你可以开始将数据索引到生命周期策略中指定的rollover alias中。对于这个样例策略my_policy,rollover的动作是在最初的索引大小超过25GB后就触发动作。ILM随后为test-alias创建一个新的索引并作为write index。

    Apply lifecycle policy manually

      你可以通过Kibana或者update settings API在创建索引时指定一个策略或者将某个策略应用到现有的索引上。在你应用某个策略后,ILM会马上开始管理索引。

    IMPORTANT:不要手动应用一个使用rollover动作的策略。使用rollover的策略必须由index template应用。否则当rollover动作闯将一个新的索引时不能carry forward这个策略。

      index.lifecycle.name这个设置用于指定索引的一个策略。

      第6行,为索引指定生命周期策略

    Apply a policy to multiple indices

      当你使用update settings API时,你可以使用索引名的通配符将某个策略应用到多个索引中。

    WARNING:当心无意中(inadvertent)匹配到了你不想修改的索引。

      第1行,更新所有以mylogs-pre-ilm开头的索引。

    Switch lifecycle policies

      若要切换某个索引的生命周期策略,可以按照下面的步骤:

    1. 使用remove policy API移除现有的策略。目标是一个data stream或者alias,移除它的所有索引的策略。

    1. 移除策略的API会移除索引中所有的ILM metadata并且不会考虑索引的生命周期状态。这会让索引处于一个不希望(undesired)的状态。

      例如,forcemerge动作会在重新打开一个index前先关闭它。在forcemerge期间移除一个索引的ILM的策略会让索引永久的(indefinite)关闭。

      移除策略后,使用get index API 检查索引的状态。目标是一个data stream或者alias来获得所有它的索引的状态。

      随后你可以按需来变更索引。比如你可以使用open index API重新打开任何被关闭的索引。

    1. 使用update settings API分配(assign)一个新的策略。目标是一个data stream或者alias的所有索引

    WARNING:首先移除现有的策略再分配一个新的策略。否则会导致phase execution出现故障。

    Migrate index allocation filters to node roles

    (8.2)link

      如果你正在一个hot-warm-cold的架构中使用自定的节点属性(custom node attribution)和attribute-based allocation filters将索引移动到data tiers。我们建议你转而使用内置的节点属性并且自动的data tier allocation。使用节点角色能让ILM自动的将索引在data tiers间移动。

    NOTE:尽管我们建议在hot-warm-cold架构中使用自动化的data tier allocation来管理你的数据,你依然可以出于其他的目的使用 attribute-based allocation filters来控制分片的分配。

      Elasticsearch Service和Elastic Cloud Enterprise能自动的执行迁移(migration)。对于self-managed 的部署,你需要手动的更新你的配置,ILM策略,以及索引来切换到节点角色。

    Automatically migrate to node roles on Elasticsearch Service or Elastic Cloud Enterprise

      在Elasticsearch Service和Elastic Cloud Enterprise中,如果你使用默认部署模板中的节点属性,you will be prompted to switch to node roles when you:

      这些动作自动的更新你的集群配置和ILM 策略以使用节点角色。另外,更新到7.14或者更高版本后,每当部署应用任何配置更改时,都会自动更新ILM策略。

      如果你使用自定义的index template,在自动迁移完成后检查这个模板并移除每一个attribute-based allocation filters

    NOTE:自动迁移后你不需要再执行任何的步骤。下文手动的步骤只有在你不允许自动迁移或者自己管理部署时才需要。

    Migrate to node roles on self-managed deployments

      若要切换到(switch to)使用节点角色:

    1. 分配(assign)data node到合适的data tier

    2. 从你的ILM中Remove the attribute-based allocation settings

    3. 在新的索引上Stop setting the custom hot attribute

    4. 更新现有的索引用于set a tier preference

    Assign data nodes to a data tier

      为每一个data node配置一个合理的角色,分配给这些节点一个或者多个data tiers:data_hot, data_content, data_warm, data_cold, 或者 data_frozen。节点也可以有其他的role。默认情况下,新的节点配置为有所有的角色。

      当你添加一个data tier到一个Elasticsearch Service deployment,一个或多个节点会被自动的配置对应的角色。你可以显示的通过Update deployment API修改Elasticsearch Service deployment中的节点的角色。用合适的node_roles代替节点的node_type配置。例如,下面的配置将节点添加到hot和content tiers,并让这个节点作为一个ingest node,remote 和transform node。

      如果你直接管理自己的集群,在每个节点的elasticsearch.yml中配置合适的角色。例如下面的设置将节点配置为一个位于hot和content tier的data-only的节点。

    Remove custom allocation settings from existing ILM policies

      更新每一个生命周期中allocate动作来移除attribute-base allocation settings。ILM会在每一个阶段中inject一个migrate动作来自动的在data tiers上转移(transition)索引。

      如果allocate动作不设置副本分片(replica)的数量,则移除整个allocate动作。(空的allocate动作是非法的)

    IMPORTANT: The policy must specify the corresponding phase for each data tier in your architecture. Each phase must be present so ILM can inject the migrate action to move indices through the data tiers. If you don’t need to perform any other actions, the phase can be empty. For example, if you enable the warm and cold data tiers for a deployment, your policy must include the hot, warm, and cold phases.

    Stop setting the custom hot attribute on new indices

      当你创建了一个data stream,它的第一个backing index自动的被分配到data_hot节点。同样的,当你直接创建了一个索引,自动的分配到data_content节点。

      Elasticsearch Service deployments,移除index template cloud-hot-warm-allocation-0,它会在所有节点上设置hot shard allocation attribution。

      如果你正在使用一个自定义的模板,更新这个模板来移除用于分配新的索引到hot tier的attribute-based allocation filters

      To completely avoid the issues that raise when mixing the tier preference and custom attribute routing setting we also recommend updating all the legacy, composable, and component templates to remove the attribute-based allocation filters from the settings they configure.

    Set a tier preference for existing indices

      ILM通过在每一个阶段中inject一个migrate动作来自动的将管理的索引转移到可用的data

      为了能让ILM将现有的索引移动到data tier,更新下面的index settings:

      例如,如果在你的旧模板中设置属性data的值为hot将分片分配到hot tier,那么将属性data设置为null并且设置_tier_preferencedata_hot

      对于已经从hot阶段转移出去的索引,tier preference必须包含了一个合适的回滚tier(fallback tier)使得期望用于分配的(prefer)tier如果不可见的话也能分配它。例如为已经在warm阶段中的索引指定一个回滚tier。

      如果索引已经在cold阶段,回滚tier可以是cold,warm和hot阶段。

      如果索引同时配置了_tier_preferencerequire.data,但是_tier_preference 是outdated(比如说,节点属性的配置比配置的_tier_preference更"colder")。那migration必须要移除require.data属性并且将_tier_preference更新为正确的tier。

      例如,有以下路由配置的索引:

      路由配置应该修复为:

      这种情况有可能发生在默认是data tiers的系统中。例如ILM使用了存储的节点属性并将管理的索引从hot阶段转移到warm阶段,在这种情况下,节点属性的配置指出了索引应该被分配到的正确的tier。

    Troubleshooting index lifecycle management errors

    (8.2)link

      当ILM执行一个生命周期策略时,有可能在某个步骤中执行必要的索引操作时候发生错误。发生错误后,ILM将索引移动到ERROR。如果ILM不能自动的解决错误,执行过程将被暂停直到你解决了策略,索引,或者集群的问题才能继续。

      例如你可能有一个shink-index的策略:一旦索引的寿命达到5天,其分片数量收缩到4个:

      不会有任何的障碍阻止你应用shrink-index策略到一个新的索引上,尽管这个索引只有两个分片:

      五天后,ILM试图将索引my-index-000001的分片数从两个分片收缩到四个分片。因为shrink动作不会增加分片的数量,所以这个操作会失败,ILM将my-index-000001移动到ERROR

      你可以使用ILM Explain API来获取发生错误的相关信息:

      上述请求返回如下的信息:

      第8行,用于管理索引的策略:shrink-index   第10行,索引寿命:5.1天   第11行,索引当前位于warm阶段   第13行,当前的动作:shrink   第15行,索引当前位于ERROR步骤   第17行,执行失败时位于shrink步骤   第19行,错误类型和错误的描述   第24行,shrink-index策略中当前阶段的定义   若要解决这个问题,你可以更新策略:在5天后将索引收缩为单个分片:

    Retrying failed lifecycle policy steps

      一旦你解决位于ERROR步骤的索引的问题,你可能需要显示的告知ILM进行重试:

      ILM接下来尝试重新运行刚刚失败的步骤。你可以使用ILM Explain API查看处理进程。

    Common ILM errors

      以下是一些常见在ERROR步骤中报出的错误以及解决方案。

    TIP: Problems with rollover aliases are a common cause of errors. Consider using data streams instead of managing rollover with aliases.

    Rollover alias [x] can point to multiple indices, found duplicated alias [x] in index template [z]

      index template的index.lifecycle.rollover_alias指定了目标rollover alias。你需要在bootstrap the initial index时显示的配置一次这个alias。rollover动作才能管理设置并更新alias来对接下来的索引进行roll over

    index.lifecycle.rollover_alias [x] does not point to index [y]

      要么索引使用了错误的alias或者alias不存在。

      检查index settingindex.lifecycle.rollover_alias。若要查看alias配置的内容,可以使用_cat/aliases

    Setting [index.lifecycle.rollover_alias] for index [y] is empty or not defined

      必须为rollover动作配置index.lifecycle.rollover_alias

      更新index settings来设置index.lifecycle.rollover_alias

    Alias [x] has more than one write index [y,z]

      对于某一个alias,只能有一个索引可以被指派(designate)为write index。

      使用aliases API,将除了某一个索引以外的其他索引都设置is_write_index:false

    index name [x] does not match pattern ^.*-\d+

      为了rollover动作可以工作,索引名必须匹配regex pattern "^.*-\d+"。最常见的问题是索引名不包含尾随数字(trailing digits)。例如,my-index不匹配pattern要求。

      索引名称尾部追加一个数值,例如my-index-000001

    CircuitBreakingException: [x] data too large, data for [y]

      说明集群达到了资源限制。

      在继续设置ILM前,你需要采取方式来缓和(alleviate)资源问题。见Circuit breaker errors了解更多信息。

    High disk watermark [x] exceeded on [y]

      说明cluster的磁盘空间快满了。当你的ILM中没有设置从hot节点滚动到warm节点时可能会发生。

      考虑添加节点,更新你的硬件,或者删除不要的索引。

    security_exception: action [<action-name>] is unauthorized for user [<user-name>] with roles [<role-name>], this action is granted by the index privileges [manage_follow_index,manage,all]

      说明ILM动作不能执行的原因是因为用户没有合适的privilege。在更新完ILM策略后用户的privilege可能被drop。ILM动作是以最后一个修改策略的用户运行的。创建或者修改策略的用户应该有这个策略中所有操作的权限。

    Start and stop index lifecycle management

    (8.2)link

      默认情况下,ILM服务处于RUNNING的状态并且管理所有有生命周期策略的索引。你可以停止index lifecycle management为所有的索引暂停管理操作。例如,当执行定期维护或者对集群作变更且会对ILM动作的执行造成影响时关闭ILM。

    IMPORTANT:When you stop ILM, SLM operations are also suspended. No snapshots will be taken as scheduled until you restart ILM. In-progress snapshots are not affected

    Get ILM status

      使用Get Status API查看当前ILM服务的状态:

      正常条件下,响应会显示ILM处于RUNNING

    Stop ILM

      若要停止ILM服务并且暂停所有生命周期策略的执行,使用Stop API

      ILM服务将所有的策略运行到某个点使得可以安全的停止。当ILM服务正在关闭中,状态API会显示ILM处于STOPPING模式:

      一旦所有的策略处于一个安全的停止点,ILM就进入STOPPED模式:

    Start ILM

      若要启动ILM并且恢复执行策略,使用Start API。这将ILM服务置为RUNNING的状态,ILM开始从离开的地方执行策略。

    Manage existing indices

    (8.2)link

      如果你使用了Curator或者其他机制来管理周期性(periodic)的索引,那么迁移到ILM时有两个选项:

    NOTE:Starting in Curator version 5.7, Curator ignores ILM managed indices.

    Apply policies to existing time series indices

      转移(transition)管理你周期性的索引的最简单的方式就是使用ILM ,configure an index template,将生命周期策略应用到新的索引上。一旦你正在写入的索引由ILM管理,你可以对你的旧索引manually apply a policy

      为你的旧索引定义一个不同的策略,策略中omit rollover动作。Rollover用于管理新的数据,所以不适用旧数据。

      注意的是对现有的索引应用策略后,每一个阶段的min_age会跟索引的创建时间作比较,所以有可能会立即处理多个阶段。如果你的策略属于资源密集型的操作比如force merge,当切换到ILM时你不会想要让很多的索引马上一下子都执行这些操作。

      你可以为现有的索引指定不同的min_age,或者设置index.lifecycle.origination_date来控制索引寿命(age)的计算。

      Once all pre-ILM indices have been aged out and removed, you can delete the policy you used to manage them。

    NOTE:If you are using Beats or Logstash, enabling ILM in version 7.0 and onward sets up ILM to manage new indices automatically. If you are using Beats through Logstash, you might need to change your Logstash output configuration and invoke the Beats setup to use ILM for new data.

    Reindex into a managed index

      另一种applying policies to existing indices就是将你的数据reindex到一个ILM-managed index中。如果创建了数据很小导致过多的(excessive)分片数量的周期性索引或者一直往相同的索引中写入导致大分片以及性能问题,那么你可能就想要reindex。

      首先,你需要设置新的ILM-managed 索引:

    1. 更新index template来包含必要的ILM 设置

    2. 引导(bootstrap)一个最初的索引作为write index

    3. 停止往旧索引中写入数据并且使用指向引导索引的alias来索引新的文档

      若要reindex到ILM管理的索引中:

    1. 如果你不想要将新旧索引混合到ILM-managed index中,那么先停止索引新的文档。将新旧索引混合到一个索引是安全,但是混合的索引需要被保留直到你准备删除新的数据。

    2. 降低ILM的拉取间隔时间(poll interval)来保证索引的大小在等待rollover的检查时不会增长的太大。默认情况下,ILM每十分钟会检查要执行哪些动作:

      第4行,每隔一分钟就检查下例如rollover的ILM动作是否要执行。

    1. 使用reindex API来reindex你的数据。如果你想要根据写入的时间有序的拆分数据,你可以运行多个reindex请求。

    IMPORTANT:Documents retain their original IDs. If you don’t use automatically generated document IDs, and are reindexing from multiple source indices, you might need to do additional processing to ensure that document IDs don’t conflict. One way to do this is to use a script in the reindex call to append the original index name to the document ID.

      第4行,匹配现有的索引。为新的索引使用前缀使得index pattern更加简单   第7行,alias指向了你的bootstrapped index   第8行,如果多个文档有相同的ID就暂停reindex。这种做法是推荐的,能防止在不同的源索引中出现ID相同的文档时覆盖文档的问题

    1. reindex完成后,将ILM的拉取时间间隔(poll interval)设置回默认的值,避免master node上没必要的负载:

    1. 使用相同的alias恢复索引新的数据。

      使用这个alias进行查询时会获取你的新数据跟所有的reindex的数据。

    1. 一旦你已经验证了在新的managed index中所有的reindex数据都是可用的,你就可以安全的移除旧的索引。

    Skip rollover

    (8.2)link

      index.lifecycle.indexing_complete设置为true,ILM不会在这个索引上执行rollover动作,即使满足了rollover的标准。当rollover成功完成后,ILM会自动的设置该参数。

      如果你需要在正常的生命周期策略中有一个例外以及更新alias来强制rollover,但是想要ILM能继续的管理索引,那你可以手动的设置该参数来跳过rollover。如果你使用了rollover API,那就不需要手动的配置这个设置。

      如果索引的生命周期策略被移除了,这个设置也会被移除。

    IMPORTANT:当index.lifecycle.indexing_complete设置为true,ILM会核实(verify)这个索引不再是index.lifecycle.rollover_alias中指定的write index。如果索引仍然是write index或者rollover alias没有设置,这个索引就被移动到ERROR step

      例如,如果你需要在一个series中更改新索引的名称同时还要保留根据配置的策略生成的之前的索引的数据,你可以:

    1. 为新的index pattern创建一个新的模板并且使用新的策略

    2. 引导最初的索引(bootstrap the initial index)

    3. 使用aliases API为alias修改引导索引为write index

    4. 在旧的索引上将index.lifecycle.indexing_complete设置为ture告知它不需要被rollover

      ILM继续使用你现有的策略来管理旧的索引。新的索引根据新的模板进行命名并且根据相同的策略进行管理without interruption。

    Restore a managed data stream or index

    link

    Data tiers

    (8.2)link

      数据层(data tier)是具有相同数据角色(data role),通常享有相同硬件配置(hardware profile )的节点集合。

      当你直接往指定索引中写入文档,这些文档将无期限(indefinitely)的一直保留(remain on)在content ties节点上。

      当你往data stream中写入文档,这些文档最开始会常驻(reside on)在hot tier节点上。你可以根据性能、弹性(resiliency)、数据保留(data retention)的要求,通过配置index lifecycle management 策略自动的将文档转移到hot ties、warm ties以及cold ties。

    Content tier

      存储在content tier上的数据通常是iterm的集合比如说产品目录(product catalog)或者文章归档(article archive)。跟时序数据不同的是,这些内容的价值随着时间的流逝相对保持不变的,所以根据这些数据的寿命(age)将它们移到性能不同的数据层是不合理的。Content data通常有长时间保留(retention)的要求,并且也希望无论这些数据的寿命的长短,总是能很快的检索到。

      Content tier是必须要有的(required)。系统索引以及其他不是data stream的索引都会被自动分配到content tier。

    Hot tier

      hot tier是Elasticsearch中时序数据的入口点(entry point),并且保留最近,最频繁搜索的时序数据。hot tier节点上的读写速度都需要很快,要求更多的硬件资源和更快的存储(SSDs)。出于弹性目的,hot tier上的索引应该配置一个或多个副本分片。

      hot tier是必须要有的。data stream中新的索引会被自动分配到hot tier。

    Warm tier

      一旦时序数据的访问频率比最近索引的数据(recently-indexed data)低了,这些数据就可以移到warm tier。warm tier通常保留最近几周的数据。允许更新数据,但是infrequent。warm tier节点不需要像hot tier一样的快。出于弹性目的,warm tier上的索引应该配置一个或多个副本分片。

    Cold tier

      当你不再经常(regular)搜索时序数据了,那可以将它们从warm tier移到cold tier。数据仍然可以被搜索到,在这一层的通常会被优化成较低的存储开销而不是查询速度。

      为了更好的节省存储(storage saveing),你可以在cold tier保留fully mounted indicessearchable snapshots。跟常规索引(regular index)不同的是,这些fully mounted indices不需要副本分片来满足可靠性(reliability),一旦出现失败事件,可以从底层(underlying)snapshot中恢复。这样可以潜在的减少一般的本地数据存储开销。snapshot仓库要求在cold tier使用fully mounted indices。Fully mounted indices只允许读取,不能修改。

      另外你可以使用cold tier存储常规索引并且使用副本分片的方式,而不是使用searchable snapshot,这样会帮你在较低成本的硬件上存储较老的索引,但是相较于warm tier不会降低磁盘空间。

    Frozen tier

      一旦数据不需要或者很少(rare)被查询,也许就可以将数据从cold tier移到frozen tier,where it stays for the rest of its life。

      frozen tier需要用到snapshot repository。frozen tier使用partially mounted indices的方式存储以及从snapshot repository中载入数据。这样仍然可以让你搜索frozen数据并且可以减少本地储存(local storage)和操作开销(operation cost)。因为Elasticsearch必须有时从snapshot repository中提取(fetch)数据,在frozen tier的查询速度通常比cold tier慢。

    Configure data tiers on Elasticsearch Service or Elastic Cloud Enterprise

      Elastic Cloud部署中默认配置了包含hot、content data的一个共享层(shared tier)。这层是必须要有的并且不能被移除。

      要增加一个warm。cold。或者frozen tier,你可以创建这么一个部署(deployment):

    1. Create deployment页面,点击 Advanced Settings

    2. 点击Add capacity增加任意数据层

    3. 页面底部点击Create deployment保存你的更改

      如果要移除一个数据层,见Disable a data tier

    Configure data tiers for self-managed deployments

      对于自己管理的部署,每个节点的data role配置在elasticsearch.yml中。例如,集群中性能最高的节点应该同时分配hot和content tier:

    NOTE:我们强烈建议你在frozen tier中使用 dedicated nodes

    Data tier index allocation

      当你创建一个索引时,Elasticsearch默认设置index.routing.allocation.include._tier_preferencedata_content来自动的在content tier上分配索引分片。

      当Elasticsearch创建一个索引,该索引作为 data stream的一部分时,Elasticsearch默认设置index.routing.allocation.include._tier_preferencedata_hot来自动的在hot tier上分配索引分片。

      你可以显示指定index.routing.allocation.include._tier_preference的值,不使用(opt out of)默认的tier-based的分配方式。

    Automatic data tier migration

      ILM使用migrate动作自动的在可见的数据层间进行索引的转变,默认情况下,每一层都会自动注入这个动作。你可以通过 "enabled":false显示指定关闭自动迁移。例如你正在使用allocate动作手动的指定分配规则。

    Monitor a cluster

    (8.2)link

      Elastic Stack monitoring功能提供了一种可以随时了解(keep a pulse)Elasticsearch集群健康跟性能的方法。

    Monitoring overview

    (8.2)link

      当你监控一个集群时,你会从集群中的Elasticsearch nodes,Logstash nodes,Kibana和Beats中收集数据。你也可以use Filebeat to collect Elasticsearch logs

      所有的检测指标(monitoring metrics)都存储在Elasticsearch中,使得你可以很容易的在Kibana中可视化这些数据。默认情况下,监控指标存储在本地索引中。

    TIP: 在生产中,我们强烈建议使用分开的监控集群(a separate monitoring cluster)。防止发生因生产集群(production cluster)中断而影响访问监控数据的问题。同样的也是防止因为监控活动对生产集群的性能产生影响。基于同样的原因,我们也建议使用一个分开的Kibana实例来观察监控数据(monitoring data)

      你可以使用Metricbeatt将收集到的Elasticsearch,Kibana,Logstash和Beats的数据直接发送给你的监控集群,而不是通过生产集群进行路由。下图中展示的是一个经典的生产集群和监控集群分离的监控架构:

      如果你有特定的许可证,你可以从多个生产集群中将数据路由到一个监控集群中。见https://www.elastic.co/subscriptions 了解了解更多关于订阅级别的差异。

    IMPORTANT: 通常来说,监控集群和被监控的集群应该使用相同的版本。监控集群不能监控高版本的生产集群。If necessary, the monitoring cluster can monitor production clusters running the latest release of the previous major version.。

    How monitoring works

    (8.2)link

      基于它们的持久的UUID(persistent UUID),每一个Elasticsearch node,Logstash node,Kibana实例和Beat实例都被认为是唯一的。在节点或者实例启动时,这个值会被写入到path.data中。

      Monitoring document只是普通的JSON格式的document,通过每一个ELastic Stack 组件在一个指定的收集间隔(collection interval)构建。如果你想要更改这些索引的模板,见Configuring indices for monitoring

      MetricBeat用于收集监控数据并且发送给监控集群。

      见下面的内容学习如何收集监控数据:

    Monitoring in a production environment

    (8.2)link

      在生产中,你应该将监控数据发送到到一个分开的监控集群(a separate monitoring cluster)中,使得即使有些你监控的节点不在了也能对历史的数据可见。例如,你可以使用Metricbeat将Kibana,Elasticsearch,Logstash,和Beats的监控数据发送到监控集群中。

    IMPORTANT:Metricbeat是一种收集和发送监控数据到监控集群的一种方法。 如果你之前配置了legacy collection method,你应该迁移到使用Metricbeat collection。要么使用Metricbeat collection,要么使用legacy collection method,不要同时使用。 Collecting monitoring data with Metricbeat了解更多信息

      如果你至少有一个Gold Subscription,可以使用一个专门的监控集群让你从一个central location中监控多个集群。

      在一个分开的集群中存储监控数据,你需要:

    1. 建立(set up)你想要用于作为监控集群的Elasticsearch集群。例如,你可以建立两个节点分别名为es-mon-1es-mon-2的集群。

    IMPORTANT:最理想的情况是监控集群跟生产集群的运行在相同版本的Elastic Stack上。然而8.x的最新版本的监控集群也能跟主版本号(major version)相同的生产集群工作正常。8.x版本的监控集群也能跟7.x的最新版本的生产集群工作正常。

      a. (Optional)核实好在监控集群上的监控数据的收集功能是关闭的。默认情况下,xpack.monitoring.collection.enabled的设置为false

      例如,你可以使用下面的API查看以及更改设置:

      b. 如果监控集群上开启了Elasticsearch Security功能,创建好有权限发送以及查询监控数据的用户。

    NOTE: 如果你计划使用Kibana查看监控数据。在Kibana服务和监控集群上的用户名密码都必须要合法。

      例如,下面的请求创建一个remote_monitor用户,它拥有remote_monitoring_agent的角色:

      或者,使用remote_monitoring_user built-in user

    1. 配置你的生产集群来收集数据并且发送到监控集群:

    2. (Optional)Configure Logstash to collect data and send it to the monitoring cluster

    3. (Optional)配置Beats来收集数据并发送到监控集群

    4. (Optional)配置Kivana来收集数据并发送到监控集群

    5. (Optional)创建一个专用的Kibana实例用于监控。而不是使用单个即要访问你的生产集群也要访问你的监控集群的Kibana。

    NOTE: 如果你使用SAML, Kerberos, PKI, OpenID Connect, or token authentication providers登陆Kibana,那么必须使用专用的Kibana。security token是cluster-specific的,因此你不能使用单个Kibana实例同时连接生产和监控集群。

    1. Configure Kibana to retrieve and display the monitoring data

    Collecting Elasticsearch monitoring data with Metricbeat

    link

    Collecting Elasticsearch log data with Filebeat

    link

    Configuring indices for monitoring

    (8.2)link

      Index templates用于对索引进行配置来存储从集群中收集的监控数据。

      你可以使用_templateAPI查询监控数据的模版:

      默认情况下,只会在模板中为监控索引(monitoring Index)配置一个分片以及一个副本。你可以添加自己的模版信息来覆盖默认配置:

    1. 设置template pattern来匹配现有的.monitoring-{product}-7-*索引

    2. 将template的order设置为1,使得默认模版先于你的模版,默认模版的order0

    3. settings区域中设置number_of_shards and/or number_of_replicas

      下面的例子中,配置了5个分片以及2个副本分片:

    IMPORTANT:只设置settings区域中的number_of_shards 以及number_of_replicas。覆盖其他的监控模版信息会导致你的监控仪表盘停止正常工作。

    Collecting monitoring data using legacy collectors

    link

    Troubleshooting monitoring

    link

    Roll up or transform your data

    (8.2)link

      Elasticsearch提供了下面的方法来处理(manipulate)你的数据:

    Rolling up historical data

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      保留历史数据用于分析是非常实用的,但由于归档大量的数据带来的财政开销(financial cost)而不会保留。因此保留时间由财政现实(financial realities)决定而不是根据历史数据的用处。

      Elastic Stack的rollup功能提供一个汇总(summarize )和存储历史数据的方法,使得历史数据仍然可以用于分析,但只有原始数据(raw data)所需的存储开销的一小部分(a fraction of the storage cost)。

    Rollup overview

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      基于时间(time-based)(主要由时间戳标识的文档)的数据经常有相关的保留策略(retention policy)来管理数据的成长。比如说,你的系统可能生成每秒生成500篇文档,那么一天会有4300万篇文章,一年有接近16亿篇文档。

       然而分析师和数据科学家可能希望你能存储无限量的数据。时间是无穷无尽的,所以你的存储需求将持续增长并且没有尽头。因此保留策略通常由随时间推移的存储成本的简单计算决定以及公司愿意为保留历史数据而花的钱。通常这些策略会在几个月或者几年后删除数据。

       存储成本是一个固定数量(Storage cost is a fixed quantity)。It takes X money to store Y data。但是一段数据的效用(utility)会随着时间发生变化。在当前时间内毫秒颗粒度的传感器的数据是非常有用,在几个星期前的数据相对有点用,但是几个月前就几乎没什么用了。

       虽然存储十年前的一毫秒传感器数据的成本是固定的,但传感器读数的价值会随着时间而减小。这些数据并不是没有用,它可以很容易地为实用的分析(useful analysis)做出贡献,但是价值的降低通常会导致被删除而不是使用固定的存储开销来保留它们。

    Rollup stores historical data at reduced granularity

      That’s where Rollup comes into play。Rollup 功能将旧的高粒度(high-granularity)汇总为降低粒度的格式,以便长期存储。通过将数据roll up到单个summary document中,相较于原始数据(raw data),历史数据可以更好的被压缩。

      比如说一个每天生成4300万文档的系统,每一秒的数据对实时分析是很实用的,但是查看超过 10 年数据的历史分析可能只在更大的时间间隔内起作用,例如每小时或每天的趋势。

      如果我们把4300篇文档按小时进行汇总,我们就可以节省大量的空间。Rollup功能会对历史数据进行自动的汇总。

      Create Job API详细了解Rollup的设置跟配置。

    Rollup uses standard Query DSL

      Rollup功能提供了新的search endpoint(_rollup_search vs 标准的/_search),这个endpoint知道如何查询rolled-up的数据。重要的是,这个endpoint接受100%普通的(normal)Elasticsearch Query DSL。你的应用不需要学习新的DSL来inspect历史数据,很容易重新使用现有的查询跟dashboard。

      这个功能也是有一些限制。不是所有的查询和聚合都支持的,一些查询功能(高亮)被禁用了并且可以使用的字段(available fields)取决于Rollup的配置。更多的限制见Rollup Search limitations

      But if your queries, aggregations and dashboards only use the available functionality, redirecting them to historical data is trivial。

    Rollup merges "live" and "rolled" data

      Rollup的另一个实用的功能是可以在同一个查询中同时查询"live"实时数据和历史的"rollup"数据。

      比如说你的系统保留了一个月的原始数据(raw data)。一个月后,这些数据被rollup到历史汇总(historical summarizes)数据中并且原始数据会被删除。

      如果你想查询原始数据,你只能查看最近一个月的数据,如果你想查看rollup数据,你只能查看一个月前的数据。RollupSearch endpoint支持在同一时间同时进行查询。这个查询会从两个数据源获取并且将结果合并到一起。如果"live"和"rollup"的数据发生重叠,那么选择"live"数据,因为它更准确。

    Rollup is multi-interval aware

      最后,Rollup能够智能地利用可用的最佳间隔。如果你使用过其他产品的汇总功能(summarizing Feature),你会发现其局限性。比如如果配置了按天为间隔的rollup,那么你只能基于按天来进行查询或者出图表。如果你需要每月间隔,则必须显示的(explicit)创建另一个存储每月平均值的汇总。

      Rollup功能可以通过按照最小的可用的间隔进行存储,并且依次来进行处理。如果你rollup了按天的数据,那么可以执行按天或者更长间隔的查询(按周、按月、按年等等)而不用显示的去配置一个新的rollup任务。这有助于缓解(alleviate)汇总系统的主要缺点之一:相对于原始数据的灵活性的降低。

    Rollup API quick reference

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      大多数rollup endpoint都有下面的前缀:

    /job/
    /data/
    /<index_name>/

    Getting started with rollups

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      你需要创建一个或多个"Rollup jobs"来使用rollup功能。这些job会在后台持续不断的运行,将你指定的index或者indices进行rollup操作。那些被rolled的文档会被放到二级索引(secondary index)中。

      比如你有一些按天记录传感器数据的索引(daily indices)(比如说sensor-2017-01-01, sensor-2017-01-02)。示例文档如下所示:

    Creating a rollup job

      我们想要将文档rollup到按小时汇总(hourly summarize)。这将允许我们生成间隔为1个小时或者更大间隔的报告和dashboard。rollup job如下所示:

      我们给这个job命名为"sensor"(在url中: PUT _rollup/job/sensor),并且告诉这个job我们要对 sensor-*进行rollup。这个job会找到匹配sensor-* pattern的所有索引。Rollup会进行汇总并存储到名为sensor_rollup的索引中。

      cron参数用来控制什么时候以及什么频率来激活这个job。当一个rollup job的cron计划激活后,这个job将对上一次job结束任务后产生的新的数据(new worth of data)执行rollup。所以你如果配置了一个每30秒就执行一次的cron,该作业将处理最近 30 秒的数据,这些数据被索引到 sensor-* 索引中。

      如果你配置了每天在午夜时执行rollup的任务,这个job将会处理过去24小时的数据。选择主要取决于偏好,具体取决于你希望汇总的“实时”程度,以及你是否希望连续处理或将其移至非高峰时间。

      接下来是groups的设置。Essentially, we are defining the dimensions that we wish to pivot on at a later date when querying the data。这个job中的grouping允许我们在timestamp字段上执行date_histogram操作,按照一小时的间隔进行rollup。同样允许我们在node字段上进行terms aggregation。

    Date histogram interval vs cron schedule 你可能注意到了job中的cron配置为每30秒执行一次,但是date_histogram配置为按照60分钟的间隔执行rollup,它们之间是什么关系呢? date_histogram控制保存的数据(saved data)的颗粒度。数据会按照小时的间隔(hourly interval)执行rollup,并且你无法执行更细的颗粒度(finer granularity)的查询。cron只是简单的查找是不是有新的数据可以用于rollup。每隔30秒,cron会看下有没有new hour’s worth of data可以用于rollup,如果没有,这个job则go back to sleep。 通常来说,在一个较大的间隔(1h)中定义一个这么小的cron(30s)是不合理的,因为大部分cron激活后会马上go back to sleep。但这也不会有什么问题,job会正确处理这种情况。

      在定义好了这些数据中会生成哪些groups后,你下一步的配置是应该收集哪些metric。默认情况下,只会收集每一个group的doc_counts。为了使rollup更加具有实用性,你一般经常会收集例如averages, mins, maxes等一些metric信息。在这个例子中需要收集的metric是相对简单的(fairly straightforward):我们想要保留temperature字段的min/max/sum,以及voltage字段的average。

    Averages aren’t composable?! 如果你之前使用过rollup,那么使用Average的时候要注意了。如果average用于计算10分钟的间隔,通常来说average就不能用于更大间隔的计算。你不能用简单的10分钟的average * 6 来计算以一个小时为间隔的average。the average of averages is not equal to the total average。 由于这个原因,其他的系统会试图omit计算average的能力或者存储多个不同的时间间隔来支持更多的灵活的查询。 然而在rollup功能中会根据定义的时间间隔来保存对应的countsum。使得当时间间隔大于或等于定义的时间间隔后我们可以重新来计算。这就给予了使用最小的存储开销来实现最大化的灵活性。所以你不用担心average的精确度(no average of averages here!)。

      Create rollup jobs了解更多关于job语法的信息。

      在你执行上文中的命令,并创建了job后,你会收到下面的响应:

    Starting the job

      job创建后,它会处于未激活状态(inactive state),在开始处理数据(这样使得随后你可以临时的暂停这个job而不需要删除它)前,job需要被启动。

      执行这个命令来启动job:

    Searching the rolled results

      在job运行并处理了一些数据后,我们就可以通过Rollup search endpoint来做一些查询了。Rollup功能被设计为你可以使用你习惯了的Query DSL进行查询,只不过是在rolled up的数据上进行查询。

      例如执行这个查询:

      这是一个计算temperature字段最大值的简单聚合查询。但需要你注意的是,这是在sensor_rollup索引上进行查询而不是原始的sensor-*索引。还有一个你要注意的是使用了_rollup_search这个endpoint。Otherwise the syntax is exactly as you’d expect。

      如果你执行了这个查询,那么会收到一个跟普通的聚合(normal aggregation)一样的响应:

      这里唯一需要注意的是Rollup的查询结果中是没有hits结果的,因为我们不再从原始的,live data中进行查询。其他部分都是相同的语法结构。

      There are a few interesting takeaways here。首先,尽管数据按小时的间隔(hourly interval)并按照node的名称进行分组,但是这个query我们只计算了所有文档中temperature的最大值。job中配置的groups在查询不是必要的元素(mandatory element),它们只是你可以用于分组的额外的维度。其次,这个查询和响应跟普通的DSL是一模一样的,使得更容易集成与dashboard和应用中。

      最后,我们可以使用分组的字段来构造一个更加复杂的查询:

      这个查询对应的响应是:

      除了使用更加复杂的查询((date histogram and a terms aggregation, plus an additional average metric),值得你注意的是这里的date_histogram使用了7d作为时间间隔而不是配置中的60m

    Conclusion

      这一章的内容提供了简明扼要的关于Rollup所能提供的核心功能。在剩余的章节中你可以学习到更多在设置Rollup时的tips和内容。你可以通过REST API概览下目前可用的功能。

    Understanding groups

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      为了能提供灵活性(flexibility),Rollup的定义会基于以后的数据查询对应的query。通常来说,系统会要求管理员在配置rollup时要决定好metric以及时间间隔。比如说按小时的间隔(hourly interval)并且是cpu_time的average。这种方式存在局限性。在以后的日子里,管理员可能想要查询按小时的间隔并且是cpu_time的average同时还要根据host_name分组,这时候就做不到了。

      当然管理员可以在按小时的间隔的基础上对[hour, host]这么一对来配置rollup,但是随着分组字段数量的增加,其需要更多的配置。另外[hour, host]的配置只能在按小时的间隔上才有用,按天、按周、按月的rollup都需要新的配置。

      相较于要求管理员提前为rollup做好决策,Elasticsearch中的Rollup job的配置则是基于哪些groups可能会在将来被用于查询。例如下面的这个配置:

      允许在timestamp字段上使用date_histogram。在hostnamedatacenter字段上使用terms aggregation,并且可以在loadnet_innet_out的任意一个字段上使用histograms

      更重要的是,这些 agg/fields可以任何的组合:

      跟下面的这个聚合都是合法的:

      需要你注意的是第二个aggregation is not only substantially larger, it also swapped the position of the terms aggregation on "hostname",说明了聚合的先后顺序对rollup没有影响。在对数据进行rollup时date_histogram是必须的,但是在查询阶段不是必须的(尽管经常会被使用)。例如下面是个可以用于Rollup Search的合法聚合查询:

      最后,在对一个job配置groups时,考虑好在以后的查询会用到哪些字段用于分组,那么将这些字段都添加到配置中就可以了。因为Rollup Search允许任意的先后顺序或者分组的字段的组合。你只需要决定好某个字段是否会在以后用于聚合,以及你可能希望使用某一种聚合方式(terms、histogram等等)。

    Calendar vs fixed time intervals

      每一个rollup-job必须有一个date histogram并且定义一个间隔。Elasticsearch可以解析(understand) calendar and fixed time intervals,fix time intervals解析(understand)起来相对简单;60s意味着60秒。但是1M是什么意思呢?一个月代表的时间取决于不同的月份,一些月份可能大于或者小于某些月份。这个calendar time的例子的持续的时间取决于上下文( This is an example of calendar time and the duration of that unit depends on context)。Calendar unitis同样受到润秒(leap-seconds)、闰年(leap-years)等等的影响。

      rollup生成的bucket可以使用calendar或者fixed intervals,所以上文中提到的影响是重要。并且这个问题会限制后续的查询。见Requests must be multiples of the config

      我们建议坚持(sticking with)使用fixed time intervals,因为它更容易解析(understand)并且在查询时更具弹性。它会在闰事件(leap-event)期间在你的数据中引入一些drift,你将不得不考虑固定数量(30 天)的月份,而不是实际的日历长度。However, it is often easier than dealing with calendar units at query time。

      units的倍数总是fixed(Multiples of units are always "fixed")。比如说2h也是一个固定数值(fixed quantity)7200秒。单个units是fixed还是calendar取决于unit:

    UnitCalendarFixed
    millisecondNA1ms, 10ms, etc
    secondNA1s, 10s, etc
    minute1m2m, 10m, etc
    hour1h2h, 10h, etc
    day1d2d, 10d, etc
    week1wNA
    month1MNA
    quarter1qNA
    year1yNA

      对于一些单位(units)可是同时是fixed和calendar,你最好使用更小的单位来描述数量(quantity)。比如说你想要一个fixed day(not a calendar day),你应该指定为24h而不是1d。同样的,如果你想要一个fixed hours,应该指定为60m而不是1h。因为单个数量(single quantity)意味着calendar time,并且会在以后限制通过calendar time进行查询。

    Grouping limitations with heterogeneous indices

      以前在 Rollup 如何处理具有heterogeneous mappings(multiple, unrelated/non-overlapping mappings)的索引时存在限制。 当时的建议是为每个数据“类型”配置一个单独的作业。 例如,你可以为已启用的每个 Beats module配置一个单独的作业(一个用于process,另一个用于filesystem等)

      由于在内部实现细节中。如果单个"merge" job被使用后会导致文档的统计可能会不正确,因此给出了上文中的建议。

      这个局限性已经被缓和(alleviate)了,从 6.4.0 开始,现在将所有rollup配置组合到一个job中被认为是最佳实践。

      例如,如果你的索引中有这两类的文档:

      以及:

      最佳实践是将它们组合成一个涵盖这两种文档类型的rollup job,如下所示:

    Doc counts and overlapping jobs

      以前在“overlapping”的job配置上存在文档计数问题,这同样是由于内部实现细节导致的。 如果有两个rollup job保存到同一个索引,其中一个job是另一个job的“subset”,则对于某些aggregation arrangements,文档计数可能不正确。

      此问题也已在 6.4.0 中消除。

    Rollup aggregation limitations

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      对字段进行rollup up/aggregated存在一些限制。这一章强调了你需要注意的主要的限制(major limitation)。

    Limited aggregation components

      Rollup功能允许使用对字段使用下面的aggregation进行分组:

      下列是numeric Field可以指定的metric:

    Rollup search limitations

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      当我们觉得Rollup功能非常的灵活(flexible)时,汇总数据(summarize data)的本质是有局限的。一旦live data(raw data)被丢弃后,你总是会丢失一些灵活性。

      在使用Rollup search时,index参数可以接受一个或者多个索引,可以是普通的(regular)、non-rollup、rollup的混合索引。然而只能指定一个rollup索引。使用index参数的规则如下所示:

      导致这些局限的原因是内部逻辑会根据给定的query决策出一个"best" job。如果在单个索引中存储了10个job。这个索引将覆盖不同的完整度(degree of completeness)和时间间隔的原数据(source data),这个query需要判断使用哪个job来进行查询。错误的决策可能会导致不准确的聚合(inaccurate aggregation)结果(比如over-counting doc counts, or bad metrics)。不管怎么样(needless to say),在技术上这是对编码的一种挑战。

      为了简化这个问题,我们限制为每次只能对一个rollup index进行查询(which may contain multiple jobs)。In the future we may be able to open this up to multiple rollup jobs。

    Can only aggregate what’s been stored

      一个也许是非常明显的限制就是只能对存储在rollup中的数据进行聚合操作。如果你没有在rollup job中配置price字段的metric,那么你不能在任何query或者aggregation中使用price字段。

      比如说在下面的query中,temperature字段已经存储在一个rollup job中,但是没有存储它的avg这个metric信息。意味着不能使用avg这个功能:

      在响应中会告诉你不能对这个字段做这次聚合操作,因为没有一个rollup job中包含这个字段的avg的metric信息:

    Interval granularity

      Rollup会以某个粒度进行存储,即date_histogram在配置中的定义。这意味着你在query/aggregation rollup data时,只能使用比rollup配置中相等或者更大的间隔(interval)。

      比如说如果数据按小时间隔(hourly interval)进行rollup。Rollup search可以在按任意小时的间隔或者更大的间隔进行聚合。小于一个小时间隔的查询都将抛出异常,因为不存在粒度更细(finer granularity)的数据。

    Requests must be multiples of the config Perhaps not immediately apparent,在aggregation请求中指定的间隔必须是配置中的间隔的倍数。如果一个job中rollup配置了3d时间间隔。那么你只能query/aggregation 3的倍数的时间间隔(3d6d9d等等)。 不是倍数的时间间隔无法正常工作。因为rollup data无法与aggregation生成的桶完全“overlap”,从而导致不正确的结果。 基于这个原因,如果没有找到配置中的时间间隔的倍数将会抛出异常。

      由于RollupSearch endpoint可以使用配置中的时间间隔的倍数( "upsample" intervals) ,所以不需要根据不同倍数的间隔(hourly、daily等等)来配置多个job。建议按需配置最小粒度的时间间隔,使得RollupSearch可以根据需要来向上调整时间间隔(upsample)。

      也就是说,如果在单个索引中配置了多个不同时间间隔的job,search endpoint会识别(identify)并且使用最大间隔的job来进行查询。

    Limited querying components

      Rollup功能允许在查询请求中带有query,但局限于只能使用一部分query,目前可用的query如下所示:

      这些query同样只能使用在rollup job的group中配置的字段。如果你想要过滤出keyword类型的hostname字段,那么这个字段必须在rollup job中配置term grouping。

      如果你尝试使用一个不支持的query,或者query引用了一个没有在rollup job中配置的字段,那么会抛出一个异常。我们预计随着时间推移会增加更多的query支持。

    Timezones

      Rollup documents存储在date_histogram中的时区里。如果没有指定时区,那么默认rollup的timestamp是UTC。

    Transforming data

    (8.2)link

      Transforms可以让你将现有的(existing)Elasticsearch索引转换(Convert)到汇总索引中(summarized indice),使得能提供一个新的insight和analytics。比如说你可以使用transforms将你的数据pivot到entity-centric indices中,它汇总了用户的行为(he behavior of users)或者是sessions,或者是其他实体(other entities)。或者你可以使用transforms在具有某个唯一键的所有文档中查找最新文档。

    Transform overview

    (8.2)link

      你可以使用下面两个方法中的一种来transform你的数据:pivot或者latest

    IMPORTANT:transforms不会破坏你的源索引(leave your source index intact)。transformed data会创建一个新的专用的索引。 相较于Kibana中的可用参数,Transforms可以通过APIs来提供更多的配置选项。参考API documentation了解transform所有的配置选项。

      Transforms是持久性(persistent)的任务,存储在cluster state使得节点发生故障也具有弹性(resilient)。参考How checkpoints workError handling了解更多关于transforms背后的机制(machinery)。

    Pivot transforms

      你可以使用transforms将你的数据pivot到entity-centric indices中。通过transforming和汇总(summarizing)你的数据,可以以另一种有趣的方式对其进行可视化和分析。

      许多的Elasticsearch索引的组织方式是事件流(stream of events),每一个事件是一个独立的文档,比如说单个商品的购买信息。Transforms能让你对这些数据进行汇总,汇总成一个组织化的(organized)、更友好的用于分析(analysis-friendly)格式。比如说你可以将某个用户购买的所有商品进行汇总。

      Transforms让你定义一个pivot,它是一个特征集合(a set of features)将索引transform到一个不同的,更加易于提取(digestible)的格式。Pivoting会将汇总后的数据输出到一个新的索引。

      要定义一个pivot,你首先要选择一个或者多个字段,你将使用这些字段对你的数据进行分组。你可以选择可以用于分类的字段(categorical field)以及numerical fields用于分组。如果你使用了numerical fields,则使用你指定的间隔对这些字段的字段值进行分桶。

      第二步就是决定好你想要如何对分组的数据进行聚合。When using aggregations, you practically ask questions about the index。聚合的类型很有多,每一种都有其作用和输出。见Create transform了解更多关于支持的聚合和分组依据字段的内容。

      作为一个可选的步骤,你也可以增加一个query来进一步限制聚合的范围。

      transform会分页处理source index query对应的数据并且对此执行一个composite aggregation。聚合的输出会存储到一个destination index中。transform每次查询source index时,都会创建一个checkpoint。你可以决定是否希望transform执行一次还是连续执行。一个batch transform属于单个操作并且只有一个checkpoint。连续的transforms会不断的增加以及处理(increment and process)新提取的(ingest)source data的checkpoint。

      比如你正在运行一个售卖衣服的网上商城(webshop)。每个订单会创建一个文档,文档中包含一个唯一的订单ID、订单名称和订单中产品的分类、价格、数量,订单的准确时间和一些客户的信息(名称,性别,地址等等)。你的数据集中包含了过去一年的交易。

      如果你想查看上一财年不同类别的销售额,那么定义一个transform,这个transform根据产品分类(女鞋、男鞋等等)和订单时间进行分组。使用过去一年的时间作为订单时间的时间间隔(interval),然后根据订单数量增加一个sum aggregation。输入结果是一个entity-centric index,这个index中显示了过去一年每一类产品卖出的商品的数量。

    Latest transforms

      你可以使用 latest transform将最近的文档拷贝到新的索引中(You can use the latest type of transform to copy the most recent documents into a new index)。你必须指定一个或者多个字段作为一个唯一键用于对数据进行分组,同时还要一个时间字段(date field)来进行时间排序(sort the data chronologicallly)。比如说你可以使用这种类型的transform来跟踪每一个用户最新付款的时间或者每一台服务器最新的事件(the latest event for each host)。

      跟pivot transforms一样,latest transform也可以允许一次或者持续运行。它会在source index的data上执行一个composite aggregation并将输出存储到destination index。如果transform持续运行,新的唯一键会自动的添加到destination index上,现有键(existed key)的最新的文档会在每一个checkpoint时自动的更新。

    Performance considerations

      Transforms在source index上执行聚合并将结果存储到destination index中。因此它所需要的时间跟资源不会比aggregation和index这两个操作花费的时间少。

      如果你一定要对大量的历史数据执行Transform,那么它最初会占用大量的资源—特别是在第一个检查点期间。

      为了有更好的性能,你需要保证对search aggregation和queries进行了优化并且只对必要的进行Transform处理。考虑好你是否能将一个source query对应的数据进行Transform操作,降低处理的数据范围。同样要考虑好集群是否有足够的资源同时处理composite aggregation的查询和索引Transform输出的结果。

      如果你想要分散集群的压力(spread out the impact on your cluster)(slower Transform带来的压力)。你可以调整执行查询跟索引请求的速率。在你create或者update 你的Transform时设置docs_per_second进行限制。如果想要计算当前的速率,根据get transform stats API中使用下面的信息:

      documents_processed / search_time_in_ms * 1000

    Set up transforms

    link

    Requirements overview

      若要使用Transform,你必须:

    Security_privileges

      用户的安全权限的分配对用户使用transform会有影响。考虑下面的两个类别:

    Elasticsearch API user

      为了能管理transform,你必须满足下面的所有要求:

      如果是仅仅要读取下transforms的配置跟状态,你必须要有:

      可以参考Built-in roles and Security privileges了解更多关于Elasticsearch roles and privileges的信息。

    Kibana user
    Kibana spaces

    When to use transforms

    (8.2)link

      Elasticsearch的aggregation是一个强有力并且非常灵活的功能,可以让你汇总(summarize)并且获取出你的数据中的complex insight。你可以在一个busy website上汇总每天请求网页的数量这类复杂的事情,并可以按地理位置和浏览器类型细分(break down)。 如果你使用相同的数据集来尝试计算一些东西比如说计算页面访问的会话(visitor web session)的平均时间,然而,这样很快会出现OOM。

      为什么会发生OOM呢?网页会话(web session)的持续时间是behavior attribute的一个例子,它不被记录于任何一条日志中。只有从weblogs中找到每一个session的第一条跟最后一条才能衍生出来。这种衍生(derivation)数据要求复杂的查询表达式以及很多的内存来连接(connect)所有指向的数据。如果你有一个持续处理的后台程序将相关的事件融合(fuse)到entity-centric并汇总到另一个索引,你就可以得到一个更实用、连贯的图(joined-up picture)。这个新索引有时被称为数据帧(data frame)。

      当出现下面的需求时,你应该要使用transforms而不是aggregation:

    Generating alerts for transforms

    (8.2)link

    WARNING:该功能处于beta测试阶段,可能会发生变化。设计跟代码相较于官方的GA(general availability)功能是不成熟的,原样的提供了这个功能但没有任何的保证(warranty)。Beta功能不受官方GA功能的支持SLA的限制。

      Kibana的告警功能(alerting feature)中支持transforms的规则,它会基于某些条件来检查连续的transforms的运行状况(the healthy of continuous transforms)。如果满足规则中的条件,会创建一条规则并且触发相关的action。您可以创建一个规则来检查连续的transforms是否已经启动,如果没有启动,则通过电子邮件通知你。参考Alerting了解更多关于Kibana alerting feature的内容。

      目前可用的transforms规则如下所示:

    Transform health

      监控transforms的运行状况并在发生操作问题(operational issue)时发出警报。

    Creating a rule

      你可以在Stack Management > Rules and Connectors下创建transforms的规则。

      Create rule的窗口中,给规则起一个名称并且提供一个可选的tag。指定检查transforms运行状态是否发生变化的时间间隔。你也通过选择Notify来指定一个通知选项。只要在检查间隔期间满足配置的条件,alert就会保持活动状态。当在下一个interval中没有满足条件,Recovered action group会被调用并且告警状态改为OK。参考general rule details了解更多的内容细节。

      在Stack Monitoring下选择Transform health rule type:

    Transform health

      选择一个或者多个transforms。你可以使用特殊的符号(*)将规则应用到所有的transforms。Transforms created after the rule are automatically included。

      下文中的transform运行状态检查是可用的并且是默认开启的:

      相关的transforms如果没有启动或者它没有索引任何的数据时会发出通知。建议在通知的消息中包含必要的action来解决这个错误。

      在创建规则的最后一步中,define the actions来执行满足条件后的后续动作。

    Defining actions

      通过选择一个connector type将你的规则和内建集成(built-in integrations)的action联系起来。

      比如说你可以选择Slack作为一个connector type,配置为将消息发送到一个你选择频道中。你可以选择一个index connector type,配置为往你指定的索引中写入JSON对象(JSON object)。当然也可以自定义通知消息。消息中可以有一系列的变量可选,例如 transform ID, description, transform state等等。

      在保存完配置后,你可以在Rules and Connectors列表中看到这条规则,你可以检查其状态并且概览其配置信息。

      告警的名称总是跟关联的触发的transforms的ID是一样的。你可以在列出各个警报的规则页面上关闭特定的transforms的通知。你可以在Rules and Connectors中根据规则的名称打开通知。

    Working with transforms at scale

    link

      Transforms将现有的Elasticsearch索引转化到汇总索引中(summarized indices),使得有机会用于new insight和数据分析。transforms中的查询和索引操作都使用了标准的Elasticsearch功能,所以在大规模(at scale)使用transforms时需要考虑的事项跟使用标准的Elasticsearch查询是相似的(similar)。如果你遇到了性能问题(performance issue),可以先从明确好瓶颈区域(bottleneck areas)(查询、索引、运行或者存储),然后再看下本章节中提高的需要考虑的相关事项来提高性能。本章节的内容还有助于理解transforms是如何工作的,因为根据transforms是在连续模式下运行还是在批处理模式下(in continuous mode or in batch)运行,应用了不同的考虑事项。

      在这一章节中,你可以学习到:

    Prerequisites:

      阅读这些指导内容的前提是你有一个想要进行调整(tune)的transforms,并且你对熟悉了下面的内容:

      下面的考虑事项(consideration)没有先后顺序(not sequential),每一条的编号只是作为navigation而已。你可以任意的采纳(take action)一个或者多个考虑事项。大多数的建议同时适用于continuous和batch transforms。如果只适用于一种transforms类型,会在描述中高亮说明。

      在每一条建议末尾的圆括号中的关键字说的是当遇到这类瓶颈区域(bottleneck area)可能可以通过这条建议来提高性能。

    Measure transforms performance

      为了可以优化transforms的性能,首先从明确主要工作的地方开始(start by identifying the areas where most work is being done)。在Kibana 页面中,Transforms中的Stats里包含了下面三个主要的信息:Indexing、searching、和processing time(或者你可以使用transforms stats API)。例如,如果结果中显示在查询时花费的时间比例最高(highest proportion of time),那么优先优化transforms中的查询。Transforms同样有Rally support,使得在必要时通过transforms进行配置来检查运行时的性能。如果你已经优化了关键的部分(crucial factor),但是仍然有性能问题,那么你可能需要考虑是否要提高硬件的性能。

    1. Optimize frequency (index)

      在一个continuous transform中,配置项frequency用来设置周期检查source index变更的时间间隔。如果检测到了变更,source index会被搜索,并将变更应用(apply)到destination index。基于于你的用例,你可能会降低应用变更的频率。通过将frequency设置为一个较高的值(最大值是一个小时),工作负载(workload)可以随着时间推移被分散,代价是数据更新频率降低了(less up-to-date)。

    2. Increase the number of shards of the destination index (index)

      基于destination index的大小,你可能需要提高分片的数量。transforms在创建destination index时默认只使用一个分片。可以在启动transforms前先创建好索引来覆盖索引设置。参考Scalability and resilience了解分片的数量会如何影响扩展性跟弹性(scalability 和 resilience)。

    TIP:使用Preview transform来查看transforms创建destination index时使用的设置(settings)。你可以拷贝并且调整索引配置并且在transforms启动前创建好索引。

      如果你定义了一个查询source index的query,确保这个query是高效的。使用Kibana中的Search ProfilerDev Tools来获取每一个独立的组件在查询请求中详细的时间开销信息(timing information)。或者你可以使用Profile。其结果可以给你一个insight,让你了解查询请求在low level是如何执行的,并理解为什么一些请求很慢。接着你就可以采取操作进行优化。

      Transforms执行的是标准的Elasticsearch查询请求。有很多的方法来编写Elasticsearch query,并且有些query比其他的query更加的高效。参考Tune for search speed了解更多关于调节(tune)Elasticsearch性能的内容。

    How transform checkpoints work

    (8.2)link

      transformas每次检查完(examine)source index会创建或者更新destination index,并生成一个checkpoint。

      如果transforms只运行一次,逻辑上只会生成一个checkpoint。如果transforms持续运行,它会在提取(ingest)和转化(transform)source data时创建checkpoint。ransform的sync属性通过指定一个时间类型的字段(time fields)来配置checkpoint。

      要创建一个checkpoint,continuous transform会:

    1. 检查source index的变更

      • transform使用一个周期性的定时器(periodic timer) 对source index进行检查。基于transforms中定义的frequency这个时间间隔属性来完成检查。

      • If the source indices remain unchanged or if a checkpoint is already in progress then it waits for the next timer

      • 如果发生了变更则创建一个checkpoint。

    2. 明确哪个entities and/or time buckets发生了变更

      • transforms在查询后会检查在上一次和最新的检查点之间哪些entities or time buckets发生了变更。transform会用变更的值,使用较少的操作来同步source和destination index,而不是full re-run。

    3. 将变更更新到destination index(the data frame)中

      • transform将变更应用到destination index中相关的新的或者发生变更的entities or time buckets中。The set of changes can be paginated。transform执行一个composite aggregation,类似batch transform operation。然而它会基于之前的步骤添加query filters来减少工作量(amount of work)。应用(apply)后所有的变更后,checkpoint就完成了。

      checkpoint的处理会涉及到集群上的Indexing和search动作(activity)。在开发transforms这个功能时,我们已经尝试控制其性能。我们决定让transform花更长的时间来完成,而不是快速完成并优先(take precedence in)消耗资源。也就是说,集群仍然需要足够的资源来支持composite aggregation搜索以及索引其结果。

    TIP:如果集群因为transform导致性能下降(unsuitable performance degradation),可以停止使用transform,并且参考Performance considerations

    Using the ingest timestamp for syncing the transform

      在大多数的情况下,强烈建议提取(ingest)source index中的时间戳用于同步transform。这是一种能让transform区分发生变更最好的方法(the optimal way)。如果你的数据源(data source)遵循ECS standard,那你已经有一个event.ingested字段,这时候就可以将event.ingested作为transform的sync.time.field属性。

      如果你没有event.ingested或者没有生成(populated)。你可以通过一个ingest pipeline进行设置。创建一个ingest pipeline可以使用ingest pipeline API或者通过Kibana中的Stack Management > Ingest Pipelines。使用set processor来设置这个字段并关联提取的timestamp的值。

      你在创建ingest pipeline之后,将其应用(apply)到transform的source index中。这个pipeline会将提取出的时间戳的添加到每篇文档的event.ingested字段中。在通过create transform API创建一个新的transform或者通过update transform API更新现有的transform时来配置transform的sync.time.field属性。

      参考Add a pipeline to an indexing requestIngest pipelines了解更多关于如何使用ingest pipeline的内容。

    Change detection heuristics

      当transform以continuous mode运行时,它不会的更新新的数据到destination index中。transform使用一组称为change detection的启发式方法以更少的操作更新destination index。

      在这个例子中,根据host name对数据进行了分组。Change detection会检测哪些host name发生了变更。host A、C和G,只更新与这些host有关的文档,而不更新存储关于hostB、D或任何其他未更改的主机的信息的文档。

      date_histogram这种通过时间分桶的场景也可以使用这种启发式方法。Change detection会检测哪些时间分桶发生了变更并且只更新发生变更的时间分桶。

    Error handling

      transform中发生故障往往是在Indexing或者searching时。To increase the resiliency of transforms, the cursor positions of the aggregated search and the changed entities search are tracked in memory and persisted periodically。

      Checkpoint的故障可以根据下面的方式分类:

      如果在一个节点上transform发生故障。transform会从最近的一次 persisted cursor position重启恢复。恢复的操作可能执行一些已经完成过的工作,但是能保证数据一致性。

    API quick reference

    (8.2)link

      所有transform的endpoint都有这个前缀:

      Transform APIs查看所有的接口。

    Tutorial: Transforming the eCommerce sample data

    (8.2)link

      Transforms能让你获取Elasticsearch的索引,然后进行转化(transform)并存放到另一个索引中。我们将使用Kibana sample data来演示如何使用transform来pivot以及summarize。

    1. 先验证下你的环境是否设置正确以便使用transform。如果开启了Elasticsearch Security Feature,你需要一个有预览和创建transform权限的用户来完成此次教程。你同样需要有source index和destination index这些指定的索引权限。见Setup

    2. 选择source index

      • 在这个例子中, 我们将使用电子商务订单的样例数据(eCommerce orders sample data)。如果你不熟悉kibana_sample_data_ecommerce这个索引,使用Kibana中的Revenue了解下。考虑下你能从这些电子商务数据中获得哪些insight

    3. 选出transform的pivot类型,并使用各种用于分组和聚合的选项

      • 目前有两种类型的transform,但首先我们先要Pivoting你的数据,也就是至少使用一个字段进行分组(apply)并应用一个聚合。你可以先预览转化后的数据(transformed data), so go ahead and play with it! 你也可以开启histogram chart来更好的了解你的数据分布。

      • 比如说你可能想要根据产品ID进行分组并且统计每一个产品的销售额和平均价格。或者你可能想要查看每一个客户的行为,计算每一个客户的总消费以及它们为多少种产品付费。或者你可能想要将货币和地区考虑进去。What are the most interesting ways you can transform and interpret this data?

      进入Kibana中的Management > Stack Management > Data > Transforms,使用向导(use the wizard)来创建一个transform:

      根据客户ID进行分组并添加一个或多个aggregation来了解每一个客户的订单。比如说让我们计算下购买的产品数量,购买花费总额、最贵以及最便宜的两个订单、订单的总数。通过在total_quantitytaxless_total_price上使用sum aggregation,在total_quantity上使用max aggregation,在order_id上使用cardinality aggregation

    TIP: 如果你只对数据的部分子集感兴趣,你可以使用query。在这个例子中,我们对数据进行了过滤,使得只关心货币类型为欧元的数据。或者你可以根据货币进行分组。如果你想要使用更加复杂的查询,你可以从saved search中创建你的数据帧(data frame)。

      你也可以使用preview transforms API

    1. 如果你满意这个预览数据,那么就可以创建这个transform了。 a. 提供一个transform ID,destination index的名称以及描述信息(可选)。如果destination index不存在,则会在transform启动的时候创建。 b. 先确定好transform要运行一次还是一直运行(once or continuous)。由于样例数据是不会发生变更,那就让transform运行一次。If you want to try it out, however, go ahead and click on Continuous mode。你必须选择一个字段,transform就可以根据这个字段检查是否发生了变更。一般情况下,使用ingest timestamp域是个不错的主意。在这个例子中,你可以使用order_filed字段。 c. 获取你可以配置一个retention policy来应用到你的transform中。选择一个date字段用于明确destination index中的旧文档并且提供一个最大的寿命(age)。destination index中超过这个寿命的文档会被移除。

      在Kibana中,在你完成创建transform前,你可以复制preview transform API request 到你的粘贴板。这些信息对你之后想要手动创建destination index会有一定的帮助。

      你也可以使用create transforms API.

    1. 可选:创建destination index

      • 如果destination index不存在,会在transform启动时候创建。pivot transform会根据source index和transform aggregation为destination index推测出mapping。如果destination index中的一些字段是从脚本中衍生出来的(比如说你使用了scripted_metrics或者bucket_scripts),它们是通过dynamic mappings创建的。你可以使用preview transform API预览下destination index中的mapping。在Kibana中,如果你拷贝了API请求,粘贴到控制台,然后参考下API响应中的generated_dest_index

    NOTE:相较于Kibana中可用的选项,通过APIs能够为transform提供更多的用于配置的选项。例如你可以通过调用Create transform来为dest设置一个ingest pipeline。参考documentation了解更多关于transform配置信息 。

      API example:

    1. 启动transform

    TIP:尽管资源的使用会基于集群负载进行调整,在transform启动后会增加集群中Indexing和search的负载。如果你遇到了过多的负载,那你可以停止transform。

      你可以在Kibana中启动、停止、重置以及管理transform:

      或者你也可以使用start transforms, stop transformsreset transforms这些APIs。

      如果你reset了transform,所有的checkpoint,states和destination index(如果是通过transform创建的)都会被删除。如果transform创建好了那么它就可以开始运行了。

      API example:

    TIP:如果你选择了Batch transform,这是一个single operation并且只有一个checkpoint。当这个transform完成后你不能重启它。 Continuous transforms的不同点在于,当提取了新的source 数据后,它持续的增加和处理checkpoint。

    1. 查看新的索引中的数据

      例如在Kibana中使用Discover这个应用:

    1. 可选:使用latest方法创建另一个transform

      这个方法在destination index中产生最新的文档的每一个唯一键的值。例如你可能想找到每一个客户或者每一个国家和地区的最新排序(根据order_date进行排序)。

    API example:

    TIP:如果destination index不存在,则会在第一次启动transform时创建。跟pivot transforms不同的是,latest transform不会在创建index的时推测mapping定义。它使用的是动态索引(dynamic index)。如果要使用显示的(explicit)mapping。在你启动transform前创建好索引。

    1. 如果你不想要保留某个transform,你可以在Kibana中删除它或者使用使用delete transform API进行删除。默认情况下,当你删除了一个transform,它的destination index和Kibana index pattern会保留。

      现在你对Kibana样例数据创建了简单的transform,并且考虑了你的数据中可能的用例。见When to use transformsExamples了解更多的想法。

    Transform examples

    (8.2)link

      这些例子展示的是如何使用transform从你的数据中衍生(derive)出有用的insight。所有的例子都使用了Kibana sample datasets。至于更详细的,分步骤的例子,见Tutorial: Transforming the eCommerce sample data

    Finding your best customers

      这个例子中使用了电子商务订单的样例数据集来找出在一个假想的网上商城中消费最多的客户。让我们使用pivot类型的transform,这样我们的destination index中会包含订单的数量,订单的总价,每一个商品的总数,每一个订单的平均价格以及每一个客户购买的产品数量。

      或者你可以使用preview transformcreate transform API

      API example

      第6行,transform中的destination index,在_preview中可以忽略   第10行,使用了两个group_by。这意味着transform包含了由usercustomer_id组成的列。在此数据集中,这两个字段都是唯一的。通过将两者都包含在transform中,它为最终结果提供了更多的context。

    NOTE: 在上面的例子中,简练的 (condense)JSON 格式对pivot对象有更好的可读性

      preview transform API能让你提前(in advance)的看到transform生成出的一些样例结果布局:

      这个transform使得更容易的回答下面的问题:

      当然也可以只使用聚合来回答上面的问题,但是transform可以让我们持久化这些数据作为一个customer centric index。这个索引使我们能够用于大规模(at scale)分析数据,并提供更大的灵活性,从以客户为中心的角度探索和navigate 数据。在某些情况下,它甚至可以使创建可视化变得非常简单。

    Finding air carriers with the most delays

      这个例子使用了航空样例数据来找出哪个航空公司延误次数最多。首先通过一个query filter从source data中筛选掉所有被取消的航班。然后将数据转化(transform)为包含了根据航空公司对航班编号分组去重,延误时间求和,飞行时间求和。最终使用了一个bucket_script确定实际延误的飞行时间百分比。

      第5行,从数据源中筛选出没有被取消的航班   第13行,transform中的destination index,在_preview中可以忽略   第17行,根据Carrier字段进行分组,这个字段的字段值是航空公司的名称   第24行,这个bucket_script会对聚合返回的结果进行计算。在这个特定的例子中,它会计算出延误占飞行时间的比例。

      预览可以让你看到在新的索引中将含有每家航空公司的这样的数据:

      这个transform使得更容易的回答下面的问题:

    NOTE: 此数据是虚构的(fictional),并不反映任何特色目的地或出发地机场的实际延误或航班统计数据

    Finding suspicious client IPs

      这个例子使用网页样例数据集来识别出有问题的(suspicious)client ip。转化(transform)后的数据所在的索引中包含了流量的总和(sum of bytes)以及每个客户机IP的不同url、代理、按位置和地理目的地传入的请求的数量。还使用了filter aggregation来统计每一个client IP收到的不同HTTP类型响应的数量。最终下面的例子将网页日志数据转化为一个entity centric index,这个entity就是cientip

      第6行,transform中的destination index   第9行,将transform配置为持续运行。它使用timestamp字段来同步source index和destination index。最晚60秒进行一次同步   第16行,根据clientip对数据进行分组   第26行,Filter aggregation统计了response字段中成功响应(200)的数量。接下来的两个aggregation根据错误码、某个范围内的响应码(response code)统计了错误的响应。   第40行,bucket_script基于聚合结果统计了clientip访问的持续时间

      在你创建transform之后,你必须启动它:

      此后不久(Shortly thereafter),第一个结果会出现在destination index中:

      下面展示的是你的数据中某一个client ip的结果:

    NOTE: 跟其他的Kibana数据集一样,网页日志样例数据集的时间戳跟你加载时的时间有关,包括有些数据的时间是未来时间。一旦这些时间超前的数据成为以前的时间,continuous transform在一定的时间点就会处理它们。如果你是在一段时间之前加载的网页日志样例数据集,你可以卸载并重新加载,时间戳就会发生变更。

      这个transform使得更容易的回答下面的问题:

    Finding the last log event for each IP address

      这个例子使用网页日志样例数据集来找出一个IP地址最后的那条日志。我们使用continuous模式下的latest类型的transform。它从最新的source data中拷贝出每一个唯一的key对应的最新文档信息到destination index中,并且在新的数据进入到source data后,将其更新到destination index中。

      选择clientip作为唯一的key。根据这个字段对数据进行分组。选择timestamp字段作为时间类型的字段用来对数据进行排序。对于continuous mode,指定一个时间类型的字段用于识别在source index中新的文档,以及用于周期性检查是否发生变更的间隔时间。

      让我们假设下,我们对只在最近的log中出现的IP地址对应的文档感兴趣。你可以定义一个保留策略(retention policy)并且指定一个date字段用于计算文档的寿命(age)。这个例子使用了相同的date字段用于排序。然后设置一个文档的最大寿命,超过你设定的值的文档会从destination index中移除。

      这个transform创建的destination index中包含了每一个client ip最新的登陆时间。因为transform是continuous模式,所以当新的数据进入到source index后会更新destination index的值。最终每一篇超过30天(基于保留策略)的文档都会从destination index中移除

      第9行,指定用于对数据分组的字段   第12行,指定用于对数据排序的date字段   第14行,设置时间间隔用于周期性检查source index中是否发生了变化   第18行,这里面的date字段和delay的设置用于同步source index跟destination index   第24行,为transform指定保留策略,超过配置的值的文档会从destination index中移除

      创建transform之后并启动:

      transform处理了数据后,可以从destination index中进行查询:

      下面展示的是你的数据中某一个client ip的结果:

      这个transform使得更容易的回答下面的问题:

    Finding client IPs that sent the most bytes to the server

      这个例子使用了网页日志样例数据集来找出每小时往服务器发送最多字节的client Ip。这个例子使用了带有top_metrics aggregationpivot类型的transform。

      在date字段上使用date histogram并指定一个小时作为时间间隔对数据进行分组。在bytes字段上使用max aggregation获取发送到服务的最大数值总和。如果不用max aggregation,可以返回发送字节最多的client ip,但是获取不到字节的数值总和。在top_metrics属性中,指定clientipgeo.src,然后根据byte字段进行降序排序。这个transform返回发送数据最多的client ip和用对应位置的2个字母的ISO代码(2-letter ISO code of the corresponding location)。

      第7行,使用时间间隔为1个小时的date histogram对数据进行分组   第16行,计算bytes字段的最大值   第22行,指定top document中的clientipgeo.src以及排序方法(bytes的值最大的文档)

      上面的例子返回的结果大致是:

    Getting customer name and email address by customer ID

      这个例子使用电子商务样例数据集,基于客户ID创建一个entity-centric index,并通过top_metrics aggregation获取客户名称、email地址。

      根据customer_id进行分组,在top_metrics aggregation中添加metirc,包括emailustomer_first_name.keyword,以及customer_last_name.keyword。用order_date字段对top_metrics进行降序排序。API大致如下:

      第7行,在customer_id字段上使用terms aggregation对数据进行分组   第16行,根据时间降序排序返回指定的字段(email和名称)

      API返回结果大致如下:

    Painless examples for transforms

    (8,2)link

      这些例子展示的是如何在transform中使用painless。你可以在Painless guide中了解更多关于Painless scripting language的内容。

    NOTE:

    尽管下面的例子中的上下文是transform的用例,但是它内部的painless脚本可以在Elasticsearch的其他查询聚合中使用。

    下面的所有的例子都使用了脚本,但是transform无法推测出脚本生成的用于mapping的字段。Transform不会在destination index中创建这些字段的mapping,意味着是动态映射的(dynamic mapped)。如果你要显示的mapping,你可以在启动Transform前创建好destination index。

    Getting top hits by using scripted metric aggregation

      下面的脚本片段(snippet)说的是如何找到最新的文档,换句话说就是找到timestamp是最新的文档。从技术视角看,在Transform中使用Scripted metric aggregation也能达到Top hits的功能。

      第4行,init_scriptstate对象中创建了一个long类型的timestamp_latest和string类型的last_doc   第5行,map_script中基于文档中的timestamp定义了current_date,并且跟state.timestamp_latest作比较。最终从shard中返回state.last_doc。通过使用new HashMap(...)复制了source document,这个操作对于将完整的source object从一个阶段传递给下一个阶段是非常重要的   第11行,combine_script从每一个shard中返回state   第12行,reduce_script遍历每一个shard返回的s.timestamp_latest的值并且返回带有最新timestamp(last_doc)的文档。在响应中,top hit(也就是latest_doc)嵌套在latest_doc

      scope of scripts了解更多的脚本信息

      你可以使用类似的方式来获取last value:

    Getting time features by using aggregations

      下面的这个片段(snippet)用来展示如何在transform中使用Painless提取time的功能。片段中使用的@timestamp字段被定义为了date类型。

      第2行,aggregation的名称   第4行,包含了一个painless脚本,该脚本将返回小时   第6行,基于文档中的timestamp字段设置一个date   第7行,从date中返回小时   第12行,aggregation的名称   第14行,包含了一个painless脚本,该脚本将返回月份   第16行,基于文档中的timestamp字段设置一个date   第17行,从date中返回月份

    Getting duration by using bucket script

      这个例子展示的是如何从一个数据日志中通过使用bucket script并根据client ip进行分组获取session的持续时间。这个例子使用了 Kibana中的样例网页日志集。

      第25行,为了定义session的时长,我们使用 bucket script   第27行, bucket script是脚本变量的一个映射(map)并且关联的路径是你在脚本中会使用的变量。在这个例子中,minmax这两个变量跟time_frame.gte.valuetime_frame.lte.value形成映射关系   第31行,最终脚本对session的开始跟结束时间执行减法操作并返回了session的持续时间

    Counting HTTP responses by using scripted metric aggregation

      你可以在transform中使用scripted metric aggregation来计算网页日志数据中不同的HTTP响应类型。你也可以使用 filter aggregations来达到类似的功能,见Finding suspicious client IPs了解更多详细的例子。

      下面的例子中假设HTTP响应码是文档中keyword类型的response字段的字段值。

      第1行,这个transform的aggregations对象包含了所有的aggregation   第2行,scripted_metric aggregation对象   第3行,scripted_metric在网页日志数据上执行了分布式操作来统计指定的HTTP响应码类型(error,success,其他)   第4行,init_scriptcstate对象中创建了带有三个long类型属性(error, success, other)的responses数组。   第5行,map_script基于文档中的response.keyword定义了code。然后基于response中的第一个数字来统计errors, successes, 和其他responses类型   第15行,combine_script从每一个shard中返回state.responses   第16行,reduce_script创建了一个counts数组,带有error,,successother三个属性。然后遍历从每一个shard返回的response,将不同的相应类型分配给counts的对应属性。error responses to the error counts, success responses to the success counts, and other responses to the other counts。最终返回counts数组。

    Comparing indices by using scripted metric aggregations

      这个例子展示的是如何在transform中使用一个scripted metric aggregation来比较两个索引的内容

      第4行,在source对象中引用的索引,它们将会进行相互比较   第13行,dest索引中包含了比较的结果   第20行,group_by字段必须是文档中的唯一键   第25行,scripted_metric aggregation对象   第27行,map_scriptstate对象中定义了一个doc,通过new HashMap(...)拷贝了原文档,这个操作对于将完整的source object从一个阶段传递给下一个阶段是非常重要的   第28行,combine_script从每一个分片中返回state   第29行,reduce_script检查索引的大小是否一样,如果不一样,那么返回count_mismatch。然后遍历两个索引的所有值,如果值相等,返回match,否则返回mismatch

    Getting web session details by using scripted metric aggregation

      这个例子展示的是如何从一个transform中衍生(derive)出多个功能。让我们先看下原数据:

      通过使用sessionid字段对数据进行分组,你可以通过session列举事件并且使用scripted metric aggregation获得session的更多详细内容。

      第8行,使用sessionid对数据进行分组   第14行,aggregation统计了每一个session中apache.access.path的种类以及apache.access.url的数量。   第27行,init_scriptstate对象中创建了数组类型的doc   第28行,map_script使用文档中的timestamp定义了一个span数组,以及根据文档中对应的字段定义了referrerurl。然后将span数组的值添加到doc对象中。   第36行,combine_script从每一个分片中返回state.docs   第37行,reduce_script定义的多个对象例如min_timemax_timeduration都是基于文档中的字段。然后声明一个ret 对象,使用new HashMap ()将source document拷贝到这个对象中。接着脚本在ret中定义了first_timelast_timeduration,这些字段的值基于脚本中的之前的一些值,最终返回ret

      最终返回的结果大致如下:

    Troubleshooting transforms

    (8.2)link

      使用这个章节中的信息来解决一些常用的问题。

      For issues that you cannot fix yourself … we’re here to help。如果你是有support contract的现有用户,可以在Elastic Support portal中创建一个ticket,或者在Elastic forum发帖。

      如果你遇到了transform的问题,你可以从下面的文件和API中获取更多的信息。

    Transform limitations

    (8.2)link

      下文中的局限性和已知问题适用于8.2.3版本的Elastic transform功能。局限性按下面几种进行分类:

    Configuration limitations
    Field names prefixed with underscores are omitted from latest transforms

      如果你使用了latest类型的transform并且source index中有已下划线开头的字段名,它们会被认为是内部字段(internal fileds)。在destination index中这些字段会被omit。

    Transforms support cross-cluster search if the remote cluster is configured properly

      如果你使用cross-cluster search,远程的集群(remote cluster)必须支持你transform中的查询和聚合。Transform会验证它们的配置。如果你使用了cross-cluster search并且验证失败,确保远程的集群支持你使用的查询和聚合。

    Using scripts in transforms

    只要是聚合中支持的脚本,那么在任意case下,在transform中使用也是支持的。然而在transform中使用脚本需要考虑下面的一些因素(factor):

    Deprecation warnings for Painless scripts in transforms

      如果transform使用了Painless脚本,并且使用弃用的语法(deprecated syntax),transform的预览或启动时不会显示warning。然而 由于运行中的查询可能是资源密集型过程,所以不可能在转换期间为了弃用警告进行检查。因此任何因为使用了弃用的语法而引起的弃用警告都不会在Upgrade Assistant中出现。

    Transforms perform better on indexed fields

      transform使用用户定义的时间字段(time filed)进行排序,这个字段会被经常访问。如果时间字段是一个runtime filed,在查询期间对于计算字段值的性能影响会显著的降低transform。在使用transform时使用一个indexed field作为时间字段。

    Continuous transform scheduling limitations

      continuous transform会周期的检查source data是否发生变化。这个定时功能目前局限于一个basic periodic timer,frequency可以是1s到1h范围的值。默认值是1m。它被设计为run litter and often。当基于你的提取率(ingest rate)为计时器选择了一个frequency时,同时也要考虑在集群中使用transform search/index操作对其他用户的影响。Also note that retries occur at frequency interval。

    Operational limitations
    Aggregation responses may be incompatible with destination index mappings

      当pivot transform首先启动后,它会为destination index推测出mapping。这种处理基于source index中的字段的类型以及使用的aggregation。如果字段是从scripted_metrics或者bucket_scripts中衍生(derive)出来的,会使用dynamic mappings。在有些情况下(in some instances),推测出来的mapping(deduced mapping)可能跟真正的数据不兼容。比如说可能会发生numeric overflow或者动态映射出的字段同时包含numbers和strings。如果你觉得发生了上述的问题,可以检查Elasticsearch的日志。

      你可以使用[preview transform API预览推测出的mapping。见API response中generated_dest_index对象。

      如果有必要的话,你可以在transform启动前,使用create index API先创建一个自定义的destination index使得可以自定义mapping。由于推测的mapping不能被index template overwrite,所以就使用create index API来自定义mapping。index template只能应用于(apply to)脚本中使用dynamic mapping衍生出的字段。

    Batch transforms may not account for changed documents

      Batch transform使用了composite aggregation使得所有的分桶可以有高效的分页(efficient pagination)。composite aggregation不支持search context,因此如果source data发生了变更(删除,更新,添加)并且同时Batch data frame正在处理中,那么结果中可能不会包括这些变更。

    Continuous transform consistency does not account for deleted or updated documents

      尽管在提取(ingest)到new data后,transform中的处理允许重新转化(transform)计算,但它同样有一些局限。

      发生变更的entities只有在它们的时间字段同时发生变化并且处于更改检查的操作范围内时才能被识别到(identified)。这是因为从设计原则上来讲,是根据new data提供的时间戳进行提取的。

      如果满足source index pattern的索引被删除了,例如当删除了历史的基于时间的索引(historical time-based),那么composite aggregation在持续的checkpoint处理中会搜索到不同的source data,entities只存在于被删除的索引中,并且不会从destination index中移除。

      取决于你的使用用例,你可能希望在有删除(deletion)后重新创建transform。或者你的使用用例能容忍historical archiving,你可能希望在你的聚合中包含一个max ingest timestamp。This will allow you to exclude results that have not been recently updated when viewing the destination index。

    Deleting a transform does not delete the destination index or Kibana index pattern

      当使用DELETE _transform/index删除一个transform时,destination index和Kibana index pattern都不会删除,这些都需要各自进行删除。

    Handling dynamic adjustment of aggregation page size

      在开发transform时,更倾向于control而不是性能。在设计方面的考虑中,更愿意让transform在后台花费更长的时间进行处理而不是快速完成并且优先资源消费(take precedence in resource consumption)。

      Composite aggregations are well suited for high cardinality data enabling pagination through results。当composite aggregation查询时发生了circuit breaker的内存异常时,我们会降低请求中分桶的数量并重试。这个circuit breaker是基于集群中的所有活动(activity)计算的,而不仅仅是来自transform的活动,因此它可能只是一个临时的资源可用性问题(resource availability issue)。

      For a batch transform, the number of buckets requested is only ever adjusted downwards. The lowering of value may result in a longer duration for the transform checkpoint to complete. For continuous transforms, the number of buckets requested is reset back to its default at the start of every checkpoint and it is possible for circuit breaker exceptions to occur repeatedly in the Elasticsearch logs.

      The transform retrieves data in batches which means it calculates several buckets at once. Per default this is 500 buckets per search/index operation. The default can be changed using max_page_search_size and the minimum value is 10. If failures still occur once the number of buckets requested has been reduced to its minimum, then the transform will be set to a failed state.

    Handling dynamic adjustments for many terms

      对于每个checkpoint,会检查entities自上一次检查后发生的变化。发生变更的entities作为一个terms query提供给transform的composite aggregation,one page at a time。然后更新被应用到destination index中。

      max_page_search_size定义了页的size,它同样用于定义composite aggregation查询返回的分桶数量。默认值是500,最小值是10.

      index setting中的index.max_terms_count定义了在一个terms query中term的最大数量。默认值是65536。如果max_page_search_size超过了index.max_terms_count,transform将失败。

      使用更小的max_page_search_size的值会导致transform的checkpoint完成的时间花费更长。

    Handling of failed transforms

      失败的transform仍然会作为一个persistent task并且应该要做适当的处理。要么删除它或者在解决导致失败的原因后重启。

      当使用API删除一个失败的transform时,先使用_stop?force=true停止transform,然后再删除它。

      一篇文档在被索引后,在它对搜索可见前有一段很小的延迟。

      一个continuous transform 会周期性的检查entities是否发生变化,其检查的时间范围是上一次检查的时间到 (now 减去 sync.time.delay)。时间窗口的移动不会有重叠的。如果一个最近索引的文档的时间戳在检查时间窗口内,但是这个文档对搜索不可见,那么这个entity不会被更新。

      如果使用了一个sync.time.field 字段来表示数据的提取时间(data ingest time)并且使用了一个 zero second或者一个非常小的sync.time.delay。那么更有可能会发生这个问题。

    Support for date nanoseconds data type

      如果你的数据使用了date nanosecond data type,aggregation仍然是millionsecond的粒度。这个局限同样会影响transform中的聚合。

    Data streams as destination indices are not supported

      transform会在destination index中更新数据,要求能够往destination index写入。Data Streams被设计为append-only,意味着你不能直接往data stream中发送更新或者删除请求。因为这个原因,data streams不支持作为transform的destination index。

    ILM as destination index may cause duplicated documents

      不建议ILM用于作为transform 的destination index。Transform在当前destination index中更新文档,不能删除ILM之前使用过的索引中的文档。在rollover中,使用transform结合ILM可能会导致重复的文档。

      如果你使用ILM来获得time-based索引,请考虑使用Date index name。如果你的transform包含基于date_hisotramgroup_by,这个处理工作不会有重复的文档。

    Limitations in Kibana
    Transforms are visible in all Kibana spaces

      Spaces允许你组织你的source、destination index 以及Kibana中其他保存的对象(saved object)并且只能看到属于你的空间的objects。然而transform是一个长期运行的任务并且是在集群层进行管理的,因此不会将其可见范围限制到某些空间(certain spaces)。Space awareness can be implemented for a data view under Stack Management > Kibana which allows privileges to the transform destination index。

    Up to 1,000 transforms are listed in Kibana

      transform的管理页面最多只能显示1000个transform。

    Kibana might not support every transform configuration option

      可能有些配置选项在transform API中可见但是在Kibana中不支持。参考documentation浏览所有的可配置的选项。

    Set up a cluster for high availability

    (8.2)link

      你的数据对你来说很重要。让数据保持安全以及可见性对Elasticsearch来说很重要。有时候你的集群可能会经历硬件错误或者断电。为了帮助你对付这类事件,Elasticsearch提供了一些功能实现高可用。

    Designing for resilience

    (8.2)link

      分布式系统比如Elasticsearch都会设计为即使它们中的一些组件失效了也能工作。只要有足够多连接正常的节点能担负起它们的任务职责,Elasticsearch集群仍能正常的操作,即使一些节点不可用或者丢失连接。

      再小的具有弹性的集群也要有以下的限制。所有的Elasticsearch集群要求:

      弹性集群需要为每个必需的集群组件提供冗余。这意味着弹性集群要求:

      一个有弹性的集群需要三个具有master节点的资格,这样如果其中一个节点失败,那么剩下的两个仍然形成多数(form a majority),并且可以成功举行选举。

      同样的,每一个节点角色的冗余意味着如果某个有特定角色的节点发生故障后,其他的节点能承担起对应的职责。

      最终,一个弹性的集群中至少包每一个分片有两个拷贝。如果一个拷贝发生故障,另一个拷贝能接管。在发生故障后,Elasticsearch会自动的在剩余的节点上重建分片拷贝来恢复集群的健康。

      故障会暂时减少集群的总容量。 此外,在发生故障后,集群必须执行额外的后台活动才能将自身恢复到健康状态。 即使某些节点发生故障,你也应该确保您的集群有能力处理您的工作负载。

      基于你的需求以及预算,一个Elasticsearch集群可以由一个或者上百个或者这个范围内的节点组成。当你设计一个较小的集群时,你通过应该集中考虑单节点故障的问题。对于较大集群的设计,需要考虑同一个时间多个节点发生故障的问题。下面的链接介绍了在不同规模的集群上构建弹性(build resilience)的一些建议:

    Resilience in small clusters

    (8.2)link

      在较小的集群上,最重要的是单节点故障对应的弹性。这个章节给出了一些指导:对于单节点故障如何尽可能保证集群的弹性。

    One-node clusters

      如果你的集群由一个节点组成,这个节点必须做所有的事情。对这种场景的推荐是,Elasticsearch默认将所有的角色给这个节点。

      单个节点的集群是不具备弹性的。如果这个节点发生了故障,集群将停止工作。因为在这个单节点的集群中没有replica,你无法存储冗余数据。然而默认情况下green cluster health状态至少需要一个replica。为了你的集群能显示一个green状态,可以对每一个索引通过index.number_of_replicas设置为0

      如果节点发生故障,你可能需要从snapshot中恢复会丢失索引数据的较老的拷贝。

      由于对于任何的故障不具备弹性,我们不建议在生产中使用单节点的集群。

    Two-node clusters

      如果你有两个节点,我们建议这两个节点都是数据节点。你应该保证在两个节点上都保留着冗余数据,通过在每一个索引上设置index.number_of_replicas1,这些索引不是一个 searchable snapshot index,以上都是默认的行为但是可以通过index template覆盖。Auto-expand relicas能达到同样的目的,但是不建议在这种规模的集群上使用这个功能。

      我们建议在这两个节点的其中一个节点上设置node.master: false使得这个节点不是master-eligible。这样你可以知道哪个节点会被选为集群的master节点。这个集群容忍不是master-eligible的节点的丢失。如果你不在其中一个节点上设置node.master:false,两个节点都是master-eligible。这意味着这两个节点要求master的选举。由于如果任一节点不可用,选举将失败,因此你的集群无法可靠地容忍任一节点的丢失。

      默认情况下,每一个节点会有一个角色。我们建议你除了master-eligible外给这两个节点赋予所有的角色。如果一个节点发生了故障,另一个节点可以接管任务。

      你应该避免把客户请求只发送给其中一个节点。如果你这么做了并且这个节点发生了故障,这个请求将不会收到响应即使剩余的节点本身是一个健康的集群。理想情况下你应该在这两个节点间做好请求的平衡。一个好方法是在客户端配置所有节点的地址,这样你可以弹性的负载均衡的请求集群中的节点。

      由于对于任何的故障不具备弹性,我们不建议在生产中使用只有两个节点的集群。

    Two-node clusters with a tiebreaker

      因为master节点的选举基于多数(majority-based)。上文中的两个节点的集群容忍某一个节点可以发生故障而不是另一个。你不可能配置一个两个节点的集群,并且可以容忍任意一个节点可以发生故障,因为理论上是不可能。你可能期望任意一个节点发生故障后,Elasticsearch可以选出剩余的节点作为master,因为没法区分出远程节点发生故障还是仅仅发生了连接问题。如果两个节点都可以进行各自的选举,连接的丢失会导致split-brain问题从而丢失数据。Elasticsearch会避免这种情况并且通过不让任何节点作为master节点来保护你的数据,直到节点保证拥有最新的集群状态并且集群中没有其他的master节点。这种方式会导致集群中没有master节点直到恢复连接。

      你可以通过添加第三个节点并且让这个三个节点都是master-eligible来解决这个问题。一次master election只要求三个master-eligible中的两个节点。这意味着集群可以容忍任意单个节点的丢失。原先的两个节点相互之间丢失连接后,这个第三个节点扮演了一个tiebreaker。你可以将这个额外的节点作为一个 dedicated voting-only master-eligible node来降低这个节点的资源配置,即dedicated tiebreaker。因为这个节点没有其他的角色,一个dedicated tiebreaker 节点不需要像其他两个节点一样的powerful。这个节点不会用于执行任何搜索或者客户端的请求,并且不能选举为集群的master节点。

      原先的两个节点不能是voting-only master-eligible nodes因为一个弹性的集群至少需要3个master-eligible 节点,至少有两个节点不能是 voting-only master-eligible nodes。如果三个节点中的两个是 voting-only master-eligible nodes那么选出的master节点必须是第三个节点,但这个节点会成为单点故障(single point of failure)。

      我们建议给两个non-tiebreaker的节点赋予所有的角色。通过创建冗余信息保证集群中的任何任务都有节点接管。

      你应该避免把客户请求发送到dedicated tiebreaker节点。你也应该避免把客户请求只发送给其他两个节点中的一个节点。如果你这么做了并且这个节点发生了故障,这个请求将不会收到响应,及时剩余的节点本身是一个健康的集群。理想情况下你应该在这两个节点间做好请求的平衡。一个好方法是在客户端配置所有节点的地址,这样你可以弹性的负载均衡的请求集群中的节点。Elastic Cloud 服务提供这种负载均衡。

      两个节点加上一个额外的tiebreaker节点的集群是可以在生产中使用的最小的集群。

    Three-node clusters

      如果你有三个节点,我们建议这三个节点都是data nodes,不是 searchable snapshot index的索引都应该至少有一个replica。默认情况下节点是data node。你可以让一些索引拥有两个replica,这样每一个节点都有一个分片的拷贝。你应该将每一个节点配置为master-eligible,这样任意两个节点都可以选择出一个master并且不需要第三个节点的参与。默认情况下所有的节点都是master-eligible。在丢失单个节点的情况这个集群仍然是弹性的。

      你应该避免把客户请求只发送给其中一个节点。如果你这么做了并且这个节点发生了故障,这个请求将不会收到响应即使剩余的节点本身是一个健康的集群。理想情况下你应该在这两个节点间做好请求的平衡。一个好方法是在客户端配置所有节点的地址,这样你可以弹性的负载均衡的请求集群中的节点。Elastic Cloud 服务提供这种负载均衡。

    Clusters with more than three nodes

      一旦你的集群增长超过3个节点,你可以指定节点给予特定的责任,根据需要独立的衡量节点需要的资源。你可以有许多例如 data nodes, ingest nodes, machine learning nodes等等的节点。根据你的需求来支持你的工作量。当你的集群增长到更大后,我们建议你为每一个角色指定专用的节点。这样可以为每一个任务来独立的衡量对应的资源。

      然而,一个好的实践就是限制master-eligible的节点数量到三个。Master节点不需要像其他类型的节点一样去衡量,因为总是从它们三个中选取一个作为master节点。如果有太多的master-eligible节点,那么完成master的选举需要较长的时间才能完成。在大型的集群中,我们建议你配置一些节点为dedicated master-eligible节点,并且避免往这些专用的节点中发送请求。如果master-eligible节点因为额外的工作可能会导致你的集群可能变得不稳定,这些额外的工作可以交给其他节点处理。

      你可以将master-eligible节点中的一个节点为voting-only node,这样它永远不会被选为master节点。比如说你有两个专用的master 节点以及一个第三个节点,这个节点同时是data note以及voting-only master-eligible节点。第三个节点将会用于在master选举中扮演tiebreaker并且自身不会成为master。

    Summary

      只要满足下面的条件,集群在丢失任何节点后依然是弹性的:

    Resilience in larger clusters

    (8.2)link

      节点间共享一些基础设施(infrastructure),比如网络互联(network interconnect)、电源供应(power supply)并不罕见。如果是这样的话,你应该计划好为这些基础设施发生故障做好准备并且保证发生故障后不会影响太多的节点。常见的实践是将共享一些基础设施的节点分组为不同的区域(zone)并且为整个zone发生故障做好计划。

      Elasticsearch期望节点之间的连接是可靠的、低延迟以及有足够的带宽。许多Elasticsearch任务要求在节点间多次往返(multiple round-trips)。缓慢或者不可靠的互联(interconnect)对集群的性能和稳定有着很明显的影响。

      比如说,每次往返增加几毫秒的延迟会迅速累积成明显的性能损失(performance penalty)。一个不可靠的网络可能会有频繁的网络分区(network partition)。Elasticsearch 将尽快从网络分区自动恢复,但你的集群可能在分区期间部分不可用,并且需要花费时间和资源来重新同步任何丢失的数据并在分区恢复后重新平衡自身。从故障中恢复可能会设计节点之间拷贝大量的数据,所以恢复的时间往往取决于可用的带宽。

      如果将你的集群按照区域(zone)进行划分,区域内(within)的节点网络通常比区域间(between)的更高。保证区域间的网络连接质量足够的高。将所有的区域放在一个数据中心(data center)并且每一个区域有自己独立的电源供应和其他基础设置是最好的方式。你也可以把集群扩张(stretch)到附近的数据中心,只要数据中心间的网络互联足够好。

      没法指定一个健康运行的Elasticsearch所需要的最低网络性能。理论上,即使节点间的往返延迟有上百毫秒的延迟,集群也能正常工作。在实践中,缓慢的网络会导致很差的集群性能。另外缓慢的网络通常是不可靠的并且会发生网络分区导致间断性的不可用。

      如果多个数据中心间相隔很远(further apart)或者连接不好并且还要希望数据可见,可以在每一个数据中心内部署一个额外的集群,使用 cross-cluster search或者 cross-cluster replication来连接集群。这些功能使得,相较于集群内,即使集群间有更低的可靠性以及性能也能较好的运行。

      在丢失了一个区域内所有的节点后,一个设计合理的集群可能会正常运行(functional),只是大大的降低了capacity(significantly reduced capacity)。当出现这个故障后你需要提供(provision)额外的节点恢复到可接受的性能。

      对于整个区域发生后故障的弹性问题,在一个或多个区域中有每一个分片的拷贝是很重要,可以通过将data node放置在多个区域中并且配置shard allocation awareness 实现弹性。你也应该保证客户端的请求会发送给一个或多个区域。

      你需要考虑到所有的节点角色并且保证每一个角色冗余的分配到两个或多个区域中。例如,如果你使用ingest pipelines或者machine learning,你应该在两个或者多个区域中有ingest node或者machine learning node。然而master-eligible node的位置更需要关注因为一个弹性的集群需要三个master-eligible node中的两个才能工作正常。下面的章节展开介绍了多个区域中如何放置master-eligible node。

    Two-zone clusters

      如果你有两个区域,在每一个区域中应该有不同数量的master-eligible node,这样拥有更多节点的区域中将包含大多数(majority)并且在丢失其他区域后也能够survive。比如说如果你有三个master-eligible node,那么可以将所有的master-eligible node 放在一个区域中或者你把其中两个master-eligible node放到一个区域,第三个放到另一个区域中。你不能在每一个区域中放置相同数量的master-eligible node。每一个区域没有拥有它自己区域内的大多数。因此,在丢失任意一方的区域后,另一方的区域可能没法survive。

    Two-zone clusters with a tiebreaker

      因为master节点的选举基于多数(majority-based)。上文中的two-zones可以容忍某个某一个节点可以发生故障而不是另一个。你不可能配置一个two-zone cluster,并且可以容忍任意一个区域可以发生故障,因为理论上是不可能。你可能期望任意一个区域发生故障后,Elasticsearch可以从剩余的区域中选出一个节点作为master,因为没法区分出远程区域(remote zone)发生故障还是仅仅发生了连接问题。如果两个区域都可以进行各自的选举,连接的丢失会导致split-brain问题从而丢失数据。Elasticsearch会避免这种情况并且通过不让任意区域中的节点作为master节点来保护你的数据,直到节点保证拥有最新的集群状态并且集群中没有其他的master节点。这种方式会导致集群中没有master节点直到恢复连接。

      你可以在每一个区域中添加一个master-eligible node并且在一个独立的第三个区域中额外单独添加一个master-eligible node。原先的两个区域相互之间丢失连接后,这个第三个节点扮演了一个tiebreaker。你可以将这个额外的节点作为一个 dedicated voting-only master-eligible node,即dedicated tiebreaker。因为这个节点没有其他的角色,一个dedicated tiebreaker 节点不需要像其他两个节点一样的powerful。这个节点不会用于执行任何搜索或者客户端的请求,并且不能选举为集群的master节点。

      你应该使用shard allocation awareness 来保证每个区域中的每一个分片都有一份拷贝。这意味着任意一个区域发生故障后所有的数据仍然是可见的。

      所有的master-eligible node,包括voting-only node,相较于集群中的其他节点,它们需要相当快速的持久存储以及一个可靠的低延迟的网络连接,因为它们处于publishing cluster state updates的关键路径(critical path)上。

    Clusters with three or more zones

      如果你有三个区域,那么你应该在每一个区域都放置一个 master-eligible node。如果你有超过三个区域,那么从中选出三个区域并且在这三个区域都分别放置一个 master-eligible node。这意味着其中一个区域发生故障后仍然可以选出一个master node。

      你的索引应该至少有一个副本来防止节点发生故障,除非这些索引是searchable snapshot indices。你也应该使用shard allocation awareness 来限制每一个区域中每一个分片的副本数量。比如说你配置了一个索引有一个或者两个副本,那么allocation awareness会保证主分片的副本在不同的区域中。这意味着即使一个区域发生了故障,分片的副本仍然是可见的,分片的可见性不会受到这种故障的影响。

    Summary

      只要满足下面的条件,集群在丢失任何区域后依然是弹性的:

    Cross-cluster replication

    (8.2)link

      通过cross-cluster replication,你可以跨集群复制索引使得:

      Cross-cluster replication使用主动-被动模式(active-passive mode),往leader index写入数据,然后数据被复制到只读的follower index中。在集群中创建一个follower index之前,需要先配置一个包含leader index的远程集群(remote cluster)。

      当leader index收到写入请求时,follower index会从远程的leader index中拉取(pull)变更。你可以手动创建follower index,也可以配置auto-follow 模式为时序索引(time series indices)自动创建follower index。

      你可以配置双向(bi-directional)或者单向的(uni-directional)cross-cluster replication集群:

      在uni-directional中,包含follower index的集群中的Elasticsearch版本必须跟远程集群的Elasticsearch版本相同或者更新。如果版本更新,那么参考下面表格中的兼容性。

      版本兼容性:

     Local cluster        
    Remote cluster5.0–5.55.66.0–6.66.76.87.07.1–7.167.178.0–8.2
    5.0–5.5×××××××
    5.6××××
    6.0–6.6×××××
    6.7××××
    6.8××
    7.0××××
    7.1–7.16×××××
    7.17××××
    8.0–8.2×××××××
    Multi-cluster architectures

      在Elastic Stack中使用cross-cluster replication来构造多个多集群架构:

      观看cross-cluster replication webinar来了解更多关于下文中用例的内容,然后在你的电脑上[set up cross-cluster replication]来允许webinar中的demo。

    Disaster recovery and high availability

      Disaster recovery为你的任务关键型(mission-critical )应用程序提供承受数据中心或区域中断的容错能力。这个用例是最常见的基于cross-cluster replication的部署方式。你可以通过不同的架构来提供集群的disaster recovery和高可用:

    1. Single disaster recovery datacenter

      在这个配置中,生产中心(production datacenter)中的数据拷贝到灾难恢复中心(disaster recovery datacenter)或者说灾备中心。由于follower index复制了leader index,所以如果生产中心不可用时候可以使用灾难恢复中心的数据。

    1. Multiple disaster recovery datacenters

      你可以将一个数据中心的数据复制到多个数据中心。在复制到两个数据中心后,当主数据中心(primary datacenter)发生故障后,这种配置可以提供disaster recovery和高可用。

      下图中,数据中心A的数据复制到了数据中心B和数据中心C,这两个数据中心拥有从数据中心A上的leader index复制的索引,并且是只读的。

    1. Chained replication

      你可以跨多个数据中心进行数据复制并形成一个复制链(replication chain)。下图中,数据中心A包含了leader index,数据中心B复制了数据中心A的数据,数据中心C复制了数据中心B上的follower index。这些数据中心间的连接形成了一个链式的复制模式(chained replication pattern)。

    1. Bi-directional replication

      bi-directional replication中,所有集群有权(access)访问所有的数据,所有集群拥有用于写入的索引并且不用手动实现故障转移(failover)。应用程序可以写入到每一个数据中心的本地索引中并且可以跨多个索引(across multiple indices)来读取全局的所有的信息(a global view of all information)。

      当一个集群或者数据中心不可用时,这种配置不需要手动的干预。在下面图中,当数据中心A发生不可用后,你可以继续使用数据中心B并且不需要手动的进行故障转移。当数据中心A重新上线后(come online),集群间就会恢复复制。

      这种配置对于index-only,不会对文档进行更新的场景十分有用。在这个配置中,通过Elasticsearch索引的数据是不会变更的(immutable)。客户端只跟所在数据中心的集群通信,不要跟其他数据中心的集群有联系(Clients are located in each datacenter alongside the Elasticsearch cluster, and do not communicate with clusters in different datacenters)。

    Data locality

      把数据放在靠近应用程序或者用户的地方能降低延迟以及响应时间。这种方法在Elasticsearch中进行数据复制时同样适用。比如你可以将产品目录(product catalog)和reference dataset复制到全世界20个或者更多的数据中心中,使得最小化数据和应用服务之间的距离。

      下图中,一个数据中心的数据复制到了三个额外的数据中心。每个数据中心位于各自的区域(region)。Central DC中包含了leader index,其他三个数据中心在各自的区域中包含follower index。这个配置将数据放在了靠近应用的地方。

    Centralized reporting

      当查询需要跨一个很大的网络的时候其效率很低下的,这时候使用一个中心化的报告集群(centralized reporting cluster)是非常有用的。在这个配置中,你将许多较小的集群中的数据拷贝到centralized reporting cluster。这个配置使你能够将数据从区域中心(regional hubs)复制到中央集群(central cluster),使得你可以在本地运行所有报告。

    Replication mechanics

      尽管你可以在索引层(index level)来设置cross-cluster replication,而Elasticsearch是在分片级别(shard level)实现复制。当创建了一个follower index,这个索引中的每一个分片会从对应的leader index中的分片拉取变更。这意味着follower index跟leader index有相同的分片数量。在leader index上的所有操作都会被follower index复制,比如创建、更新、删除一篇文档的操作。这些请求会通过leader shard(primary或者replica)发送。

      当一个follower shard发送一个读请求,leader shard会根据在创建follower index时候配置的read parameter来响应每一个新的操作。如果没有新的操作,leader shard会根据配置的超时时间等待新的操作的发生,等待超时后,leader shard会响应follower shard没有新的操作。follower shard在更新shard statistics后会马上再发一个读请求给leader shard。这种通信模型确保远程集群和本地集群之间的网络连接持续使用,避免被防火墙等外部源强行终止。

      如果读请求失败了,则会检查(inspect)失败的原因。如果失败的原因认为是可以恢复的(比如说网络问题),那么 follower shard会进行循环重试。否则follower shard会暂停until you resume it

    Processing updates

      你不能手动的更改follower index的mappings或者aliases。如果进行变更,需要去更改leader index。因为follower index是只读的,所有配置中对follower index的写操作都会被reject。

    NOTE:Although changes to aliases on the leader index are replicated to follower indices, write indices are ignored. Follower indices can’t accept direct writes, so if any leader aliases have is_write_index set to true, that value is forced to false.

      例如你在数据中心A中添加了一篇名为doc_1的文档并且复制到了数据中心B。如果客户连接到了数据中心B并且尝试更新doc_1,那这次请求会失败。要想更新doc_1,必须连接数据中心A并且在leader index上进行更新。

      当follower shard从leader shard收到操作请求时,follow shard会将这些操作放到一个writer buffer中,follower shard会基于这个writer buffer执行bulk write请求。当writer buffer超过配置的上限后,则不会发送读请求。这个配置提供back-pressure机制,使得writer buffer不再full以后就恢复读请求。

      你可以在creating the follower index时进行配置来管理如何复制leader index的操作。

      leader index上的index mapping的变更会马上复制到follower index上。这种行为同样发生在index settings上。除了一些leader index的本地设置,比如说修改leader index的分片数量是不会复制到follower index的,follower index不会收到(retrieve)这种设置。

      如果在leader index上应用了一个non-dynamic的设置(settings)并且follower index也需要这个设置,follower index会先关闭,然后应用这个设置,最后重新打开。在这个期间,follower index无法被读取并且不能复制写操作。

    Initializing followers using remote recovery

      当创建了一个follower index,你只有等这个follower index完全的初始化结束后才能使用它。remote recovery process会在follower node上创建一个新的分片并且将leader node上的主分片数据拷贝到这个新的分片中。

      Elasticsearch使用这个remote recovery process来引导(bootstrap)follower index使用来自leader index的数据。remote recovery process将leader index当前状态的副本提供给follower index,即使由于Lucene中合并中的段使得leader上完整的历史更改还不可用。

      remote recovery是网络密集型(network intensive)的处理过程:它将所有的Lucene的段文件从leader集群传到follower集群。follower在leader集群中的主分片上初始化一个recovery session,随后并发的向leader请求文件块(file chunks)。默认情况下,并发的请求five 1MB file chunks。默认的行为设计为:支持leader和follower集群之间具有高网络延迟(high network latency)。

    TIP:你可以修改dynamic remote recovery settings来限制数据传输速率,并通过remoterecovery管理资源消费。

      使用集群中的recovery API以及follower index来获取处理中的remote recovery信息。由于Elasticsearch使用snapshot and restore来实现remote recovery,运行中的remote recovery在recovery API被标记为snapshot类型。

    Replicating a leader requires soft deletes

      Cross-cluster replication的工作方式是通过replay leader index的主分片上执行的各个写操作的历史记录。Elasticsearch需要保留history of these operations,这样就可以让follower shard任务去拉取这些操作。保留这些操作的底层机制是soft deletes

      当删除/更新现有的文档时会发生soft delete。保留的soft delete有一定的限制,这个限制是可配置的。操作历史保留在leader shard上并且对follower shard task可见,用于replay历史操作。

      index.soft_deletes.retention_lease.period这个设置定义了分片历史的驻留最大时间,这个设置决定了你的follower index可以离线的最长时间,默认12个小时。如果分片拷贝在其保留租约(retention lease)到期后恢复,但是缺失的操作仍然在leader index上可用,那Elasticsearch会建立一个新的租约并拷贝缺失的操作。然而Elasticsearch不能保证retain unleased operations,所以有可能一些缺失的操作被leader丢弃了并且现在完全不可用了。如果发生了这种情况,follower就不能自动恢复,那你必须recreate it

      如果要作为leader index,它必须开启soft delete。在Elasticsearch 7.0.0之后,新创建的索引默认开启soft delete。

    IMPORTANT: Cross-cluster replication不能用于Elasticsearch 7.0.0或者更早版本中现有的索引,因为soft delete是关闭的。你必须reindex你的数据并且开启soft delete。

    Use cross-cluster replication

      下面的内容提供了关于如何配置以及使用cross-cluster replication的更多信息:

    Tutorial Set up cross-cluster replication

    (8.2)link

      使用本章节的指南来设置两个数据中心集群的cross-cluster replication(CCR)。跨数据中心复制(replicate)你的数据能提供以下的好处:

      在这一章节,你将会学习到:

      你可以手动创建follower index来复制(replicate)remote cluster上的指定的索引,或者配置auto-follow patterns来复制 rolling time series indices。

    TIP:如果你要在cloud上跨集群复制数据,你可以configure remote clusters on Elasticsearch Service,然后你就可以search across clusters以及设置CCR。

    Prerequisites

      若要完成这个教程,你需要:

    Connect to a remote cluster

      若要将remote cluster(Cluster A)上的索引复制到本地集群(Cluster B),你需要将Cluster A配置为Cluster B的remote 。

      若要在Kibana中的Stack Management中配置一个remote cluster:

    1. 从侧边导航栏选择Remote Clusters

    2. 指定remote cluster(Cluster A)的Elasticsearch endpoint URL,或者IP地址,hostname以及transport端口(默认值9300)。例如cluster.es.eastus2.staging.azure.foundit.no:9400或者192.168.1.1:9300

      你也可以使用cluster update settings API 来添加一个remote cluster:

      第8行,指定remote cluster的hostname以及transport 端口。

      你可以通过下面的方式验证本地集群是否成功连接了remote cluster。

      API响应显示本地集群连接了一个名为leader的remote cluster。

      第7行,本地集群连接的remote cluster中节点的数量

    Enable soft deletes on leader indices

      index若要能被follow,在创建时必须开启soft deletes。如果索引没有开启soft deletes,你必须reindex并且使用新的索引作为leader index。Elasticsearch 7.0.0及以后的版本默认在新的索引上开启soft deletes。

    Configure privileges for cross-cluster replication

      CCR在remote cluster和本地集群(local cluster)上要求有不同的cluster和index privilege。使用下面的请求创建remote cluster和本地集群(local cluster)上不同的角色,然后创建一个拥有这些角色的用户。

    Remote cluster

      拥有leader index的remote cluster上,CCR role要求read_ccr cluster privilege,以及leader index上的monitorread privilege。

    NOTE:如果请求出现了on behalf of other users的问题,用户需要有remote cluster上的run_as privilege。

      下面的请求在remote cluster上创建一个remote-replication 角色:

    Local cluster

      拥有follower index的本地集群,remote-replication 角色要求manage_ccr cluster privilege,以及follower index上的monitorreadwrite,以及manage_follow_index privilege。

      下面的请求在本地集群上创建了一个remote-replication角色:

      在一个集群上创建remote-replication角色后,在本地集群上使用create or update users API上创建一个用户并且赋予remote-replication角色。例如,下面的请求赋予名为cross-cluster-user的用户一个remote-replication角色:

    NOTE:你只需要在本地集群上创建这个用户

    Create a follower index to replicate a specific index

      当你创建了一个follower index,要将remote cluster和leader index引用到你的remote cluster中。

      若要从Kibana中的Stack Management中创建一个follower index:

    1. 侧边导航栏选择Cross-Cluster Replication,然后选择Follower Indices

    2. 选择你想要复制(replicate)的包含leader index的cluster(Cluster A)

    3. 输入leader index的名称,如果你按照的是以下的教程,那么就填入kibana_sample_data_ecommerce

    4. 为你的follower index输入一个名称,比如follower-kibana-sample-data

      Elasticsearch使用remote recovery process来初始化follower,即将leader index中的Lucene段文件传输到follower index中。索引状态被更改为Paused。在remote recovery process结束,follower index开始使用并且状态更改为Active

      当你在leader index中索引文档时,Elasticsearch会将这些文档复制到follower index中。

      你也可以使用create follower API来创建follower index。在你创建一个follower index后,你必须引用remote cluster以及leader index。

      在初始化follower请求时,请求响应在remote recovery process完成前就会返回,若要等待完成后再返回,那么在你的请求中添加参数wait_for_active_shards

      使用get follower stats API来观察复制状态(status of replication)。

    Create an auto-follow pattern to replicate time series indices

      你可以使用auto-follow patterns自动的为rolling time series indices创建新的follower。只要remote cluster上的新的索引名称匹配到了auto-follow pattern,对应的follower index就会添加到local cluster中。

      auto-follow pattern用于指定你想要从remote cluster中复制的索引,可以指定一个或者多个。

      若要在Kibana的Stack Management中创建一个auto-follow pattern:

    1. 侧边导航栏选择Cross Cluster Replication ,然后选择Auto-follow patterns

    2. 为auto-follow pattern输入一个名称,比如beats

    3. 选择你想要复制(replicate)的包含leader index的remote cluster,例子中的场景是Cluster A

    4. 输入一个或者多个index pattern来确认你想要从remote cluster中复制的索引。例如输入metricbeat-* packetbeat-*会为Metricbeat和Packetbeat自动创建follower

    5. 输入以Follower作为follower index名称的前缀,这样能让你更容易区分出复制的索引

      匹配pattern的新索引在remote cluster中创建,Elasticsearch会自动的将它们复制到本地follower index中。

      你可以使用create auto-follow pattern API来配置auto-follow patterns。

      第6行,自动follow新的Metricbeat索引   第7行,自动follow新的Packetbeat索引   第9行,follower index的名称继承于leader index 并且添加了copy后缀

    Manage cross-cluster replication

    (8.2)link

      使用下面的内容来管理cross-cluster replication任务,例如inspecting replication progress、pausing and resuming replication, recreating a follower index, and terminating replication。

      若要开始使用CCR,访问Kibana然后进入Management > Stack Management。在侧边导航栏选择Cross-Cluster Replication

    Inspect replication statistics

      若要查看某个follower index的复制过程以及详细的分片统计数据(shard statistics)。根据上文中的内容进入Cross-Cluster Replication然后选择Follower indices

      选择你想要查看的follower index详情的名称,滑出(slide out)的面板会先显示follower index的设置和replication statistics,包括follower shard的读写操作。

      若要显示更多的详细的统计数据,点击View in Index Management,在index management中选择follower index的名称,查看follower index的详细统计数据。

      API example:

    Pause and resume replication(manage)

      若要停止或者恢复leader index的复制(replication),根据上文中的内容进入Cross-Cluster Replication然后选择Follower indices

      选择你想要停止的follower index然后选择Manage > Pause Replication,follower index的状态变更为Paused。

      若要恢复复制,选择follower index然后选择Resume replication

      API example:

      你可以使用pause follower API停止复制并随后使用resume follower API恢复复制。一前一后(in tandem)使用这两个API可以让你调整follower shard task的读写参数,如果你最开始的配置不太适用于你的用例。

    Recreate a follower index

      当更新/删除一篇文档时,底层操作会在Lucene的索引中保留一段时间,这个时间通过参数index.soft_deletes.retention_lease.period定义。你可以在leader index上配置这个设置。

      当follower index开始后,它会向leader index需求一个retention lease,这个lease要求leader不允许prune一个soft delete,直到follower告知它已经收到了该操作或者lease到期。

      如果follower index远远落后于(fall sufficiently)leader并且不能复制操作,Elasticsearch会报出indices[].fatal_exception的错误,若要解决这个问题,需要重新创建一个follower index。当新的follower index创建后,remote recovery process开始从leader中复制Lucene的段文件。

    IMPORTANT:重新创建follower index属于破坏性的行为(destructive action),集群中包含follower index的所有Lucene段文件都会被删除

      若要重新创建follower index,根据上文中的内容进入Cross-Cluster Replication然后选择Follower indices

      选择follower index和pause replication。当follower index的状态更改为Paused,重新选择follower index,然后unfollower leader index。

      follower index会被转化为standard index,并且不再Cross-Cluster Replication 页面上显示。

      在侧边导航栏,选择Index Management,选择上一步的follower index然后关闭它们。

      随后你就可以recreate the follower index,重新进行复制。

      API example:

      使用pause follow API来停止复制,然后关闭follower index并重新创建:

    Terminate replication

      你可以unfollower leader index,然后将follower index转化为一个standard index。根据上文中的内容进入Cross-Cluster Replication然后选择Follower indices

      选择follower index和pause replication。当follower index的状态更改为Paused,重新选择follower index,然后unfollower leader index。

      follower index会被转化为standard index,并且不再Cross-Cluster Replication 页面上显示。

      选择Index Management,选择上一步的follower index然后关闭它们。

      API example:

      你可以使用unfollow API来停止复制,这个API会将follower index转化为standard index(non-follower)。

    Manage auto-follow patterns

    (8.2)link

      若要复制(replication)时序索引,你可以配置一个auto-follow pattern,使得新创建的索引被自动复制。只要remote cluster上新的索引名称匹配到auto-follow pattern,对应的follower index就会添加到本地集群(local cluster)中。

    NOTE:Auto-follow patterns只会匹配remote cluster上打开的索引(open index),并且索引的所有的主分片都已经启动(start)。Auto-follow patterns不会匹配closed indicessearchable snapshots来用于CCR。避免使用auto-follow pattern匹配带有read or write block的索引,这些block会阻止follower index执行复制操作。

      你也可以为data streams创建auto-follow pattern。当remote cluster上创建了一个新的backing index并且auto-follow pattern匹配到了data stream的名称,那index和data stream会被自动的follow。如果你在创建auto-follow pattern之后再创建data stream,那么所有的backing index都会被follow。

      通过CCR从remote cluster复制过来的data streams受到local rollovers的保护,可以使用promote data stream API来将这些data streams变成regular data streams。

      Auto-follow patterns在Index lifecycle management中特别有用,因为它在包含leader index的集群上会不断的创建新的索引。

      若要在Kibana的Stack Management中使用cross-cluster replication auto-follow patterns,从侧边导航栏选择Cross-Cluster Replication然后选择Auto-follow patterns

    Create auto-follow patterns

      当你create an auto-follow pattern时,你可以对单个集群配置一个pattern集合。当在remote cluster上创建一个索引时,索引名会匹配pattern集合中的一个,随后就会在local cluster中配置一个follower index。follower index使用最新的索引作为leader index。

      使用create auto-follow pattern API来添加一个新的auto-follow pattern配置。

    Retrieve auto-follow patterns

      若要查看现有的auto-follow patterns并修改backing patterns,那就访问你的remote cluster上的Kibana。

      选择你想要查看的auto-follow pattern,然后就可以对其做变更,你可以查看auto-follow pattern下的follower index。

      你可以通过get auto-follow pattern API查看所有配置的auto-follow pattern集合。

    Pause and resume auto-follow patterns

      若要停止或者恢复auto-follow pattern 集合,访问Kibana,然后选择auto-follow并且停止复制(replication)。

      若要恢复复制,选择pattern并选择Manage pattern > Resume replication

      可以使用pause auto-follow pattern API来停止auto-follow pattern,并使用pause auto-follow pattern API来恢复auto-follow pattern。

    Delete auto-follow patterns

      若要删除auto-follow pattern集合,访问Kibana,选择auto-follow pattern,然后停止复制。

      当pattern状态变成Paused,选择Manage pattern > Delete pattern

      也可以使用delete auto-follow pattern API来删除一个auto-follow pattern集合。

    Upgrading clusters using cross-cluster replication

    (8.2)link

      对正在使用CCR的集群升级要谨慎对待,下面的情况可能会导致在rolling upgrades时发生索引follow出现失败:

      基于uni-directional和bi-directional index following,在开启CCR的集群上运行rolling upgrade有所不同。

    Uni-directional index following

      在uni-directional配置中,只有一个集群包含leader index,并且其他集群只包含复制leader index的follower index。

      这种策略中,follower index所在的集群应该先升级并且leader index所在的集群最后升级。按这种顺序处理能保证在升级过程中能继续index following并且不需要下线。

      你也可以使用这个策略升级一个replication chain,先升级链中最后的集群再升级包含leader index的集群。

      例如,ClusterA包含了所有的索引,ClusterB follow ClusterA中的索引,ClusterC follow ClusterB中的索引。

      在这种配置中,按照下面的顺序升级:

    1. Cluster C

    2. Cluster B

    3. Cluster A

    Bi-directional index following

      在bi-directional的配置中,每一个集群包含leader和follower index。

      在这种配置中升级时,在升级集群前先pause all index followingpause auto-follow patterns

      在升级结束后,恢复index following以及恢复auto-follow pattern的复制。

    Recreate a follower index
    Pause and resume replication

    Snapshot and restore

    (8.2)link

      快照(snapshot)是运行中的Elasticsearch集群的备份。你可以使用快照用于:

    The snapshot workflow

      Elasticsearch将快照存储在集群外的称为snapshot repository的存储位置中。在创建或恢复快照之前,你必须在集群中register a snapshot repository。Elasticsearch支持一些带有云仓库选项的仓库类型,包括:

      注册一个快照仓库(snapshot repository)后,你可以使用snapshot lifecycle management (SLM)自动的创建和管理快照。你可以restore a snapshot来恢复或传输数据。

    Snapshot contents

      默认情况下,集群的快照包含了集群状态(cluster state),所有的常规的(regular)data streams,所有常规的索引。集群状态包括:

      你也可以在创建快照时只指定集群中的data stream或者索引。包含data stream或者索引的快照自动会包含它们的alias。当你恢复一个快照,你可以选择是否恢复这些alias。

      快照中不包括或者说不备份:

    Feature states

      Feature states包含索引和data streams,用于为一个Elastic feature存储配置、历史和其他数据,例如Elasticsearch security或者Kibana。

      一个feature state通常包括一个或者多个system indices or system data streams。它也可能包括feature使用的常规索引和data stream。例如,某个feature state可能包括了一个常规索引,这个索引包含了feature的执行历史。在一个常规索引中存储这个历史让你更容易查询到。

      在Elasticsearch 8.0及以后的版本中,feature states备份和恢复系统索引和系统data stream的唯一方法。

    How snapshots work

      快照会自动的删除重复数据(deduplicate)来节省存储空间并且能减少网络传输开销。快照通过拷贝索引的segment来备份一个索引并且将其存储在快照仓库中。由于segment是不可变的,快照只需要拷贝仓库中上一个快照后新的段。

      每一个快照在逻辑上是独立的。当你删除一个快照,Elasticsearch仅仅(exclusively)删除那个快照使用的段。如果段被仓库中的其他快照使用,则不会删除。

    Snapshots and shard allocation

      快照对索引的主分片进行拷贝。当你开始一个快照,Elasticsearch会马上开始拷贝任意可见的(available)主分片的段。如果某个分片正在启动或者relocating,Elasticsearch会在拷贝分片的段(shard's segment)之前等待它们完成。如果一个或者多个分片不可见,the snapshot attempt fails。

      一旦快照开始拷贝分片的段,Elasticsearch不会将这个分片移动到其他节点,即使rebalancing或者shard allocation settings会触发reallocation。Elasticsearch只会在快照完成复制分片数据后才移动分片。

    Snapshot start and stop times

      快照不代表某个精确时间点(a precise point in time)的集群。而是每个快照包含一个开始跟结束时间。快照代表的是两个时间之间每一个分片数据的视图。

    Snapshot compatibility

      若要往某个集群中恢复一个快照,快照、集群以及每一个恢复的索引版本必须兼容。

    Snapshot version compatibility
    Snapshot version6.87.0–7.17.2–7.178.0–8.2
    5.0–5.6×××
    6.0–6.7×
    6.8××
    7.0–7.1×
    7.2–7.17××
    8.0–8.2×××

      你不能将快照恢复到旧版本中。例如,你不能把在7.6.0中创建的快照恢复到运行7.5.0的集群中。

    Index compatibility

      恢复的每一个索引必须和当前集群的版本兼容。如果你尝试在一个不兼容的集群中恢复一个索引,尝试恢复会失败。

    Index creation version6.87.0–7.17.2–7.178.0–8.2
    5.0–5.6×××
    6.0–6.7×
    6.8××
    7.0–7.1×
    7.2–7.17××
    8.0–8.2×××

      你不可以在旧版本中恢复索引。例如,你不能把在7.6.0中创建的索引恢复到运行7.5.0的集群中。

      一个兼容的快照中可能会包含在不兼容的版本中创建的索引。例如,7.17集群的快照可以包含6.8中创建的索引。但你如果要在8.2的集群中恢复6.8的索引,尝试会失败。如果在升级之前创建快照请注意这个情况。

      存在这么一种替代方法(workaround),你可以先将索引恢复到同时兼容你当前集群和索引的最新版本的集群上。你随后可以使用reindex-from-remote在你当前集群上重新构建索引。只有索引开启_source才可以从remote上reindex。

    Warnings

    Other backup methods

      Taking a snapshot is the only reliable and supported way to back up a cluster 。你不能通过拷贝data目录中的节点数据进行备份。没有一种支持方式(supported way)从文件系统层面的备份来恢复数据。如果你想尝试从这种备份中恢复集群,可能会失败并且Report出corruption或者文件丢失或者其他数据一致性的问题,或者出现成功的悄无声息的丢失一些你的数据。

      拷贝data目录中的节点数据不能用于备份是因为它不是在单个时间点上对其内容的一致表示(consistent representation)。你不能通过将节点下线,然后执行那些拷贝或者是采用文件系统层面的快照来修复刚才的问题。因为Elasticsearch有跨整个集群的一致性要求。你必须使用内置的快照功能来备份集群。

    Repository contents

      Don’t modify anything within the repository or run processes that might interfere with its contents。如果某个除了Elasticsearch以外的东西修改了仓库的内容,那以后快照或者恢复操作可能会失败,可能会出现轻微的数据丢失。

      你可以安全的 restore a repository from a backup ,只要你:

      另外,快照可能包含security-sensitive的信息,那你可能需要store in a dedicated repository

    Register a snapshot repository

    link

    Azure repository

    link

    Google Cloud Storage repository

    link

    S3 repository

    link

    Shared file system repository

    link

    Read-only URL repository

    link

    Source-only repository

    link

    Create a snapshot

    (8.2)link

      这一章节介绍了如何对运行中的集群创建快照。随后你可以通过restore a snapshot来恢复或者传输数据。

      你将学习到:

      这一章同样介绍了创建专用的集群状态快照的技巧以及在不同的时间间隔创建快照。

    Prerequisites

    Considerations

    Automate snapshots with SLM

      Snapshot lifecycle management(SLM)是定期备份集群的最简单的方法。SLM策略根据设定好的定时计划自动的创建快照。该策略同样可以根据你定义的保留规则删除快照。

    TIP:Elasticsearch Service deployments automatically include the cloud-snapshot-policy SLM policy. Elasticsearch Service uses this policy to take periodic snapshots of your cluster. For more information, see the Elasticsearch Service snapshot documentation.

    SLM security

      在开启Elasticsearch security feature后,下面的cluster privilege控制SLM动作的访问:

    manage_slm

      允许用户执行所有的SLM动作。包括创建/更新策略以及开始/停止SLM。

    read_slm

      允许用户执行所有的只读的SLM动作,例如获取策略以及检查SLM状态。

    cluster:admin/snapshot/*

      允许用户创建/删除任意的索引,无论是否有访问那个索引的权限

      你可以通过Kibana创建/管理角色来分配这些privilege。

      为了能保证必要的privilege来创建/管理SLM策略和快照,你可以设置一个拥有manage_slmcluster:admin/snapshot/*privilege的角色以及访问SLM history index的全部访问权限。

      下面的例子中,下面的请求创建了名为slm-admin的角色:

      为了保证有SLM 策略和快照历史的只读访问权限,你可以设置一个拥有read_slm的集群privilege的角色以及SLM history index的读取访问权限。

      下面的请求中创建了一个名为slm-read-only的角色:

    Create an SLM policy

      若要在Kibana中管理SLM,进入主菜单并且点击tack Management > Snapshot and Restore > Policies,若要创建一个策略,则点击Create Policy

      你也可以使用SLM APIs管理SLM。使用create SLM policy API创建一个策略。

      下面的请求创建了一个策略,该策略在1:30 a.m.UTC备份了集群状态、所有的data streams、以及所有的索引。

      第3行,使用Cron syntax定义创建快照的时间   第4行,快照的名称,支持date math。为了防止命名冲突,这个策略在每个名称后面追加了一个UUID   第5行,Registered snapshot repository用于存储这个策略的快照   第7行,这个策略的快照中包含了data stream和 index   第8行,如果为true,该策略的快照中包含集群状态(cluster state)。同时也默认包含所有的 feature state。若要只包含指定的feature states,见Back up a specific feature state   第10行,保留规则(可选)。该配置将为快照保留30天,无论快照的寿命(age)是多少,至少保留5个以及最多50个快照。见SLM retentionSnapshot retention limits

    Manually run an SLM policy

      你可以手动运行一个SLM策略来立即创建一个快照。在升级前测试一个策略或者快照时很有用。手动运行一个策略不会影响它的快照定时计划(snapshot schedule)。

      若要在Kibana中运行一个策略,计入Policies页面,在Action列下并且点击运行图标。你也可以使用execute SLM policy API

      快照程序在后台运行。若要监控其运行过程,见Monitor snapshot

    SLM retention

      SLM snapshot retention属于cluster-level的任务,独立于策略中的快照定时计划。若要控制SLM retention任务的运行时间,配置集群设置slm.retention_schedule

      若要马上运行retention任务,使用execute SLM retention policy API

      SLM策略中的保留规则(retention rule)只会应用到使用这个策略创建的快照。其他快照不会受到(not count toward)这个策略的保留限制。

    Snapshot retention limits

      我们建议你在SLM策略中包含保留规则来删除你不再需要的快照。

      快照仓库可以安全的扩展到上千个快照。然而,若要管理它的metadata,规模大的(large)仓库要求在master node上有更多的内存。保留策略能保证仓库的metadata一直增长而造成master node的不稳定。

    Manually create a snapshot

      若不使用SLM策略创建一个快照,则使用create snapshot API,快照的名称支持date math

      快照需要花点时间时间完成,取决于它的大小。默认情况下,快照创建API用于初始化快照,快照的处理在后台运行。若要阻塞客户端直到快照完成,则将请求参数wait_for_completion设置为true

      你可以使用clone snapshot API克隆一个现有的快照。

    Monitor a snapshot

      若要监控当前正在运行的快照,使用参数_currentget snapshot API

      To get a complete breakdown of each shard participating in any currently running snapshots, use the get snapshot status API.

    Check SLM history

      若要获取某个集群SLM的执行历史(execution history),包括每一个SLM策略的统计,则使用get SLM stats API。这个API同样返回集群快照保留任务历史(retention task history)

      若要获取指定的SLM策略的执行历史,则使用get SLM policy API。响应包括:

    Delete or cancel a snapshot

      若要在Kibana中删除一个快照,进入Snapshots页面并点击Action列下面的trash icon。你也可以使用delete snapshot API

      如果你删除一个正在处理中的快照,Elasticsearch会取消这个快照。快照的处理会被停止并删除为这个快照生成的文件。如果某些文件被其他快照使用,那么不会删除这些文件。

    Back up configuration files

      如果在你自己的硬件上运行Elasticsearch,我们建议作额外的备份,选择一个文件备份软件对每一个节点上的$ES_PATH_CONF directory 进行常规备份(regular backup)。快照不会备份这些文件。注意的是每一个节点上的这些文件可能会不同,所以节点上的文件需要各自备份。

    IMPORTANT:The elasticsearch.keystore, TLS keys, and SAML, OIDC, and Kerberos realms private key files contain sensitive information. Consider encrypting your backups of these files.

    Back up a specific feature state

      默认情况下,包含集群状态的快照也包含所有的feature states。不包含集群状态的快照默认不包含所有的feature states。

      你可以配置一个快照只包含指定的feature states,不用关心集群状态。

      若要获取可用的feature信息,使用get features API

      这个API的响应:

      若要在快照中包含指定的feature state,则在feature_states数组中指定feature的name

      例如,下面的SLM策略中包含Kibana和Elasticsearch security features的feature states。

      feature state对应的索引或者data stream都会在快照内容中展示出来。例如,如果你备份了security feature state,security-*这些系统索引会在get snapshot APIindicesfeature_states下展示。

    Dedicated cluster state snapshots

      一些feature states包含敏感数据。例如security feature state包含的系统索引包含了用户名称和加密后的密码。因为密码使用cryptographic hashes存储,快照的泄露(disclosure)不会让第三方授权作为其中的一个用户或者使用API keys。然而,如果第三方可以更改快照,它们可以安装一个后门,则会丢失机密信息。

      若要更好的保护数据,考虑为集群状态的快照创建一个专用的仓库SLM策略。这能让你严格限制以及审计仓库的访问。

      例如,下面的SLM策略只备份集群状态。策略中使用了专用的仓库存储这些快照。

      第7行,备份集群状态,同时包含所有的feature states   第8行,不包括常规的data stream和index

    Create snapshots at different time intervals

      如果你使用单个SLM策略,那就很难同时做到频繁创建快照并且长时间保留快照。

      比如说,某个策略每30分钟创建一个快照同时快照数量最大值为100个,那么每个快照最多只能保留2天((100 * 30) / 60 / 24 = 2.08天 )的时间。这种设置对备份最新的改动是不错的,但是没法让你恢复一星期或者一个月之前的数据。

      为了解决这个问题,你可以使用相同的仓库创建多个SLM策略,这些策略的执行计划间隔不一样。由于策略的保留规则只应用到这个策略生成的快照,某个策略不会删除其他策略创建的快照。

      例如,下面的SLM策略每小时创建一次快照并最多保留24个快照。每个快照在这个策略中只保留一天。

      下面的SLM策略每天创建一次快照并最多保留31个快照。每个快照在这个策略中只保留30天。

      每天下午11点45 UTC运行。

      下面的SLM策略每月创建一次快照并最多保留12个快照。每个快照在这个策略中只保留366天。

      每个月第一天的下午11点56分 UTC运行。

    Restore a snapshot

    link

    Searchable snapshots

    (8.2)link

      Searchable snapshots能让你使用snapshots以一种cost-effective的方式查询很少被访问并且是只读的数据。coldfrozen data tiers使用Searchable snapshots来降低你的存储和操作开销。

      Searchable snapshots消除了replica shards的需要,可能将搜索数据需要的本地空间减半(halve)。searchable snapshots依赖相同的快照机制,这个机制也用于备份并且对你的快照仓库存储开销有极小的影响。

    Using searchable snapshots

      查询一个searchable snapshot index跟查询其他索引是一样的。

      默认情况下,searchable snapshot index没有副本分片(replica)。底层的快照提供弹性,由于对查询体量(query volume)的期望是很低的,所以单个分片就足够了。然而,如果你需要支持一个高查询体量,你可以通过调整索引设置index.number_of_replicas添加副本分片。

      如果节点发生故障,searchable snapshot shards需要在其他地方恢复,这时候就会出一个短暂的(brief)的时间窗口,在这个时间窗口内,Elasticsearch将分片分配到其他节点,集群的颜色不再是green。在那个时间内查询这些分片可能会失败或者返回部分结果,直到将分片分配到健康的节点。

      你通常会通过ILM来管理searchable snapshots。当常规(regular)索引到达cold或者frozen阶段, searchable snapshots动作自动将常规索引转化为searchable snapshot index。你也可以手动的通过使用mount snapshot API让现有的快照中的索引变成可以被搜索。

      若要从快照中mount一个索引,但是快照中拥有很多的索引,我们建议你创建一个快照的clone,克隆后的快照中只包含你想要搜索的那个索引,并mount那个克隆。你不应该删除一个被mount的快照,所以创建一个克隆能你管理这个快照备份的生命周期,独立于其他任何的searchable snapshots。如果你使用ILM来管理你的searchable snapshots,ILM会在快照需要时自动的进行克隆。

      你可以使用跟常规索引相同的机制来控制searchable snapshot index的分片的分配。例如,你可以使用Index-level shard allocation filtering来限制searchable snapshot shard分配到某些节点子集上。

      searchable snapshot index的恢复速度受制于仓库设置max_restore_bytes_per_sec以及跟普通的恢复操作一样的节点设置indices.recovery.max_bytes_per_sec。默认情况下,indices.recovery.max_bytes_per_sec的是无限制的,但是indices.recovery.max_bytes_per_sec的默认值取决于节点的配置。见Recovery settings

      我们建议在创建一个快照前,索引的每个分片都force-merge到单个段中,这样快照将会被mount成一个searchable snapshot index。从快照仓库中的每一次读取都耗时耗钱,段的数量越少,恢复快照或者查询的响应时的读取次数越少。

    TIP:Searchable snapshot用来管理大型归档历史数据室是最理想的的办法。历史信息相较于最新的数据通常很少被查询,因此不需要副本分片来提高性能。 对于更多复杂或者耗时的查询,你可以在Searchable snapshots中使用Async Searchable

      使用下面任意一个仓库类型来进行searchable snapshots:

      You can also use alternative implementations of these repository types, for instance MinIO, as long as they are fully compatible. Use the Repository analysis API to analyze your repository’s suitability for use with searchable snapshots。

    How searchable snapshots work

      当从某个快照中mount了一个索引,Elasticsearch将它的分片分配到集群中的data node上。data node随后基于指定的mount options,自动的从仓库中将相关的分片数据找回(retrieve)到本地储存。如果数据在本地不可见(available),Elasticsearch从快照仓库中下载需要的数据。

      如果包含了分片的节点发生故障,Elasticsearch自动的将受到影响的分片分配到其他的节点,并且节点是通过仓库来恢复相关的分片数据。不需要副本分片(replica),不需要负载的监控或者orchestration用于恢复丢失的分片。尽管searchable snapshot index默认不需要副本分片,你也可以通过调整index.number_of_replicas来添加副本分片。searchable snapshot shard的副本分片是通过拷贝快照仓库中的数据获得,像是searchable snapshot primary shard。与此相反,常规索引的副本分片则是从主分片中拷贝而来。

    Mount options

      若要搜索一个快照,你必须首先mount快照到本地成为一个索引。通常ILM会自动完成。但你也可以自己调用mount snapshot。有两个选项从快照中mount出一个索引,它们都不同的性能特色(performance characteristic)和本地储存占用(local storage footprints):

    Fully mounted index

      加载完整的被快照的索引分片(snapshotted index's shards)的拷贝到集群的本地节点存储上。ILM在hotcold阶段使用这个选项。

      fully mounted index的查询性能跟常规索引(regular index)相当,因为极小需要访问快照仓库。随着恢复的进行(while recover is ongoing),查询性能可能比常规索引要慢,因为某个查询所需要的数据还没有找回(retrieve)到本地。如果发生这种情况,Elasticsearch会急切的找回需要的数据来完成这次查询,并且是跟恢复过程并行处理。磁盘上的数据在重启后也会被保留,所以节点不需要在重启后重新下载已经存储在节点上的数据。

      fully mount后,ILM管理的索引名都有restored-的前缀。

    Partially mounted index

      使用本地缓存,只包含最新查询的索引数据。该缓存有一个固定大小,其大小由frozen tier的所有节点共享。ILM在frozen阶段使用这个选项。

      如果查询需要的数据不在缓存中,Elasticsearch会从快照仓库中获取丢失的数据。需要获取数据的查询会很慢,但是获取到的数据会存储在缓存中,以后类似的查询可以非常快。Elasticsearch会evict缓存中不常被使用的数据来释放空间。节点重启后,缓存会被清空。

      尽管比fully mounted或者常规索引慢,partially mounted index仍然能很快的返回查询结果,即使是很大的数据集,因为仓库的数据层为查询进行了heavily optimization。许多的查询在返回结果前只需要检索分片数据总量的一个小的子集。

      partiallly mounted后,ILM管理的索引名都有partial-的前缀。

      若要partially mount an index,你必须要有一个或者多个节点上分片缓存可用 。默认情况下,专用的frozen data tier中的所有节点共享一个配置,使用磁盘总空间的90%和磁盘总空间与headroom(100GB)的差值。

      强力推荐在生产使用中使用一个专用的frozen tier。如果没有,你必须配置xpack.searchable.snapshot.shared_cache.size为一个或者多个节点的缓存保留空间。Partially mounted indice只会分配到有分片缓存的节点。

      Static)为partially mounted index的分片缓存保留的磁盘空间大小。接收一个磁盘空间的百分比或者一个absolute byte value。对于专用的frozen data tires中的节点,默认值是90%。其他默认是0b

      Static byte value)对于专用frozen tier中的节点,headroom的最大值。如果xpack.searchable.snapshot.shared_cache.size没有显示设置, 则headroom设置为100GB。否则默认是-1(not set)。只有xpack.searchable.snapshot.shared_cache.size用百分比设置才能配置xpack.searchable.snapshot.shared_cache.size.max_headroom

      为了说明这些设置如何协同工作(work in concert)。下面两个例子是在一个专用的frozen node上使用了默认值:

      你可以在elasticsearch.yml中配置:

    IMPORTANT:你只能在data_frozen角色的节点上配置这些设置。另外,有分片缓存的节点只能有单个data path

      Elasticsearch同样使用了一个名为.snapshot-blob-cache的专用系统索引来加速searchable snapshot的恢复。这个索引是位于partially or fully mounted data之上的缓存层,它包含了启动searchable snapshot shard的最少需要的数据。Elasticsearch自动删除索引中不再使用的文档。可以通过以下的设置来调节这个周期性的清除:

      Dynamic.snapshot-blob-cache索引周期性清除计划的间隔时间。默认值是每1小时 。

      Dynamic)在.snapshot-blob-cache索引中保留过时文档的保留期。默认值是100

      Dynamic.snapshot-blob-cach周期性清除时,每次为bulk-delete查询的文档数量。默认值是10m

      Dynamic)The value used for the <point-in-time-keep-alive,point-in-time keep alive>> requests executed during the periodic cleanup of the .snapshot-blob-cache index. Defaults to 10m.

    Reduce costs with searchable snapshots

      在大多数的情况下,searchable snapshot降低开销的方式是通过消除副本分片以及节点之间分片数据的拷贝。然而,如果从快照仓库中取回数据的开销是特别大的,那么searchable snapshot可能比常规索引有更多的开销。在使用之前,确保操作系统的cost structure和searchable snapshot是兼容的。

    Replica costs

      为了弹性(resiliency),常规索引要求在多个节点上有冗余的分片拷贝(shard copy)。如果节点发生故障,Elasticsearch使用冗余分片来重构丢失的分片拷贝。searchable snapshot不要求副本分片。如果包含searchable snapshot index的节点发生故障,Elasticsearch会从快照仓库中重建丢失的分片拷贝 。

      没有副本分片后,很少被访问的searchable snapshot index要求非常少(far fewer)的资源。包含replica-free fully-mounted的searchable snapshot index要求的节点和磁盘空间只有常规索引的一半。只包含partially-mounted searchable snapshot index的frozen tier甚至只要更少的资源。

    Data transfer costs

      当常规索引的分片在节点间移动时,分片的内容从集群中的另一个节点拷贝。在许多环境中,在节点间移动数据的开销是很大的。特别是在节点位于不同区字段的云环境中运行时。相反的是,当mount一个searchable snapshot index或者移动其中一个分片时,总是从快照仓库中拷贝。通常来说成本是很低的。

    WARNING:Most cloud providers charge significant fees for data transferred between regions and for data transferred out of their platforms. You should only mount snapshots into a cluster that is in the same region as the snapshot repository. If you wish to search data across multiple regions, configure multiple clusters and use cross-cluster search or cross-cluster replication instead of searchable snapshots.

    Back up and restore searchable snapshots

      你可以使用regular snapshots备份一个包含searchable snapshot index的集群。当你恢复一个包含searchable snapshots index的快照后,这些索引又再次恢复成searchable snapshot index。

      在你恢复一个包含searchable snapshot index的快照之前,你必须首先register ,它包含最初的索引快照(original index snapshot)。在恢复时,searchable snapshot index从最初的索引快照中挂载索引快照。你可以使用不同的仓库分别用于常规快照(regular snapshot)和searchable snapshot。

      searchable snapshot index的快照中只包含了少量的metadata用来识别它的original index snapshot,它不包含原始索引中的任何数据。如果original index snapshot不可见,那么在恢复searchable snapshot indices时会失败。

      由于searchable snapshot index不是常规索引,所以她不能使用source-only repository对searchable snapshot indices生成快照。

    Reliability of searchable snapshots

      searchable snapshot index的数据拷贝依赖的是仓库中的快照。如果仓库出现故障或者快照损坏会导致数据丢失。尽管Elasticsearch在本地储存中有这些数据的副本(copy),这些副本可能是不兼容的并且在仓库发生故障时不能用于恢复数据。你必须保证你的仓库是可靠的并且保护仓库里面的数据不受到破坏。

      主流公共云提供商的blob storage都能很好的提供对数据丢失或者破坏的保护,如果你自己管理仓库,那你需要负责其可靠性。

    Secure the Elastic Stack

    link

    Manually configure security

    link

    Set up basic security for the Elastic Stack

    link

    Encrypt internode communications with TLS

    Security files

    link

    Enable audit logging

    link

    Audit events

    link

    Logfile audit events ignore policies

    link

    Auditing search queries

    link

    User authentication

    link

    Built-in roles

    link

    remote_monitoring_agent

    Native user authentication

    link

    Built-in users

    link

    User authorization

    link

    Defining roles

    link

    Security privileges

    link

    Cluster privileges
    Indices privileges

    Submitting requests on behalf of other users

    link

    Watcher

    link

    Watcher triggers

    link

    Watcher schedule trigger

    link

    Command line tools

    link

    elasticsearch-node

    link

    Changing the role of a node

    elasticsearch-reset-password

    link

    How to

    (8.2)link

      Elasticsearch附带了默认的配置目的是想让用户有一个很好的开箱体验,用户应该在不需要做任何更改的情况下就可以使用全文搜索(full text search),高亮、聚合和索引这些功能。

      一旦你更好的理解掌握了Elasticsearch后,你可以使用一些优化根据你自己的用例做性能的提升。

      这一章节会指导你哪些变更是应该做以及不应该做。

    General recommendations

    (8.2)link

    Don’t return large result sets

      Elasticsearch 被设计为一个搜索引擎,这使得它非常擅长取回与查询匹配的top documents。然而将Elasticsearch作为数据库领字段的那种工作负载是不太好的,比如返回满足某个查询的所有文档。如果你真的需要这么做,确保使用Scroll API来实现。

    Avoid large documents

      默认的http.max_content_length的值为100M。Elasticsearch会拒绝索引大于该值的文档。你可能想要增加这个特定的设置,但 Lucene 仍然有大约 2GB 的限制。

      即使抛开这些硬性的限制,索引一个large document不是一个很好的实践。large document会对网络、内存使用量和硬盘造成更多的压力。即使查询请求中不要求查询_source,Elasticsearch在所有情况下都需要获取文档的_id,而获取large document的这个字段的开销由于文件系统缓存的原因会更大。索引这个文档可能使用的内存量是文档原始大小的倍数。Proximity search(phrase queries for instance)和highlighting同样会变得开销昂贵,因为它们的开销直接取决于原始文档的大小。

      It is sometimes useful to reconsider what the unit of information should be。例如,如果你想要让一本书可以被搜索到,并不是意味着文档中包含这一整本书的内容。一种可能比较好的方式是使用章节(chapter)或者甚至是段落(paragraph)作为一篇文档,并且在这个文档中有其他的属性(property)来标识属于哪一本书。这种方式不仅仅会避免索引large document,同时也使得查询体验会更好。比如说用户想要查询两个单词foobar。跨章节的匹配结果可能较差,而段落中同时出现这两个单词的匹配结果则看起来是好的。的

    Recipes

    (8.2)link

      这一章节包含了一些用于解决常见问题的方法:

    Mixing exact search with stemming

    (8.2)link

      在构建一个查询应用时,stemming通常是必要的,因为在查询skiing时会渴望匹配到包含ski或者skis的文档。但如果用户就想专门查询skiing呢?通常的做法就是使用multi-field使得对相同的内容用两种不同的方式进行索引:

      根据这个设置,在body上查询ski会同时返回这两篇文档。

      另外,在body.exact上查询ski将只返回文档1,因为body.exact的analysis chain不会执行stemming。

      This is not something that is easy to expose to end users,我们需要找出一个方法来知道用户是想要查找一个精确匹配(exact match),如果不是的话我们就重定向到一个合适的字段。还需要考虑的是如果查询中的一部分需要精确匹配而其他部分仍然要stemming?

      幸运的是,query_stringsimple_query_string有一个功能来解决这个exact problem: quote_field_suffix。这个参数会告诉Elasticsearch被双引号包起来的词需要重定向到另一个不同的字段,如下所示:

      在上面的例子中,ski使用了双引号(in-between quotes),根据quote_field_suffix参数将在body.exact字段上查询。所以只有文档1返回。这允许用户基于自己喜好混合查询exact search和 stemming search。

    NOTE:如果quote_field_suffix中的字段不存在,那么查询就会回滚(fall back)到使用默认的字段进行查询。

    Getting consistent scoring

    (8.2)link

      Elasticsearch在执行跨分片和副本的文档打分操作时会增加一定的挑战。

    Scores are not reproducible

      比如说同一个用户执行两次相同的列和文档的查询(the same request twice in a row and documents),但是返回的结果是不一样的,这是一种很差的体验对吗?事实上如果你有多个副本时(index.number_of_replicas大于0)是有可能发生这种情况的。原因是Elasticsearch在选择分片时采用了一种循环(round-robin)的方式,所以两次相同的列和文档的查询会在同一个分片的不同的两个副本上执行。

      那为什么这会产生问题呢?Index statistics是打分的重要的组成部分。由于被删除的文档(deleted documents)的存在使得同一个分片的不同副本上的index statistics可能是不相同的。也许你知道当文档被删除或者更新后,旧的的文档不会从索引中移除,这些旧的文档只是被标记为被删除的(deleted)并且只有在所属的段下次被合并后才会被移除。然而由于生产实践的原因(However for practical reasons),index statistics会包含这些被删除的文档。所以考虑这种情况,当主分片刚刚完成了一次合并并且移除了很多被删除的文档,使得它的index statistic跟分片有很大的不同(分片中依旧有很多被删除的文档)导致打分也是不同的。

      一种推荐的方式是使用一个字符串(用户的id或者session)来确认登陆的用户的身份作为一个preference,使得给定的用户总是去命中相同的分片,最终多个查询的打分始终是一致的。

      这种work around还有别的好处:当两篇文档的打分相同时,它们会默认的根据lucene内部id(跟_id没有关系)进行排序。然而这些lucene内部id在同一个分片的不同副本中可能是不同的。所以通过总是命中相同的分片,使得相同打分值的文档总是有一致的排序结果。

    Relevancy looks wrong

      如果你注意到两篇内容一样的文档会得到不同的分数或者一次exact match不会让文档的排序靠前,这个问题可能跟sharding相关。默认情况下,Elasticsearch会让每一个分片负责生成自己的分数。然而由于index statistic对打分有重要的贡献,所以只有分片间有相同的index statistics才能工作正常。这个假设说的是文档会默认被均匀的(evenly)的路由到不同的分片,这些分片的index statistic应该是非常相似的那么就会得到期望的分数。然而如果有下面的假设:

      不然很大的可能会让参与查询请求的所有分片有不相同的index statistics使得相关性会很差。

      如果是一个较小的数据集,那么你可以把所有的东西都索引到只有一个副本的分片(index.number_of_shards: 1)中来work around这个问题,这是默认的配置。所有的文档有相同的index statistics并且分数是将保持一致。

      其他推荐的方式就是使用dfs_query_then_fetch的查询类型来work around这个问题。这使得Elasticsearch会遍历所有涉及的分片,向这些分片索要跟这次请求相关的index statistics,然后coordinating node会合并这些index statistics,伴随着查询将合并后的index statistics发给查询的分片,这样分片就可以使用全局的index statistics而不是自身的index statistics进行打分。

      大多数情况下,这个额外的round trip开销非常小。然而有些查询如果包含了数量很多的字段或者term,由于所有的term都需要从terms dictionary中查找并收集统计值使得开销不会很小。

    Incorporating static relevance signals into the score

    (8.2)link

      有些领域具有static single并且它跟相关性有关。比如说PageRank跟url长度都是用于web查询的两个通用的功能来调整对网页的打分,并且独立于查询条件。

      目前有两种查询允许对静态分数跟文本相关性进行组合。比如跟BM25一起打分:

      比如说你有一个pagerank字段,你希望跟BM25进行组合,并且最终的打分公式为:score = bm25_score + pagerank / (10 + pagerank)

      使用script_score query 的话如下所示:

      第9行,pagerank必须使用Numeric类型。

      使用rank_feature query 的话如下所示:

      第10行,pagerank必须是rank_feature字段。

      两种方式都可以获得相同的分数,但是各有取舍(trade-off):script_score query 提供了更多的灵活性,使得可以让你用文本相关性分数跟你想要的static singles进行组合。另外rank_feature query只暴露(expose)了一些方法将static singles纳入到分数中。然而它基于rank_featurerank_features字段,这两个字段的字段值通过了特殊的方式进行索引,使得rank_feature query可以跳过不具竞争力(non-competitive)的文档并快速的返回top match。

    Tune for indexing speed

    (8.2)link

    Use bulk requests

      Bulk request能获得比每次只索引一篇文档更高的性能。为了能找出bulk request中包含最合适的文档数量,你应该在一个单节点的单个分片上做基准测试(benchmark)。首先一次性索引100篇文档,然后200、400篇。每次的基准测试都将索引的文档数量翻倍。当索引的速度趋于平缓(start to plateau)那么说明针对你的数据类型已经达到了bulk request包含的最合适的文档数量。In case of tie, it is better to err in the direction of too few rather than too many documents。需要注意的是当并发发送large bulk request时,可能会对集群造成内存的压力,所以建议避免每次请求发送几十兆(a couple tens of megabytes)的数据,即使这些请求看起来性能没有问题。

    Use multiple workers/threads to send data to Elasticsearch

      单线程发送bulk request不大可能最大化Elasticsearch集群的索引能力。为了能使用集群所有的资源,你应该使用多线程或者多进程来发送数据。另外,除了可以更好的利用集群的资源,也应该会有助于降低每个 fsync 的成本。

      确保观察TOO_MANY_REQUESTS (429)的响应码(EsRejectedExecutionException with the Java client)。Elasticsearch通过这个响应码告诉你它处理的速度赶不上当前的索引速率。当这个情况发生后,你应该暂停下索引再进行重试,ideally with randomized exponential backoff。

      跟量化bulk request中的文档数量一样,只有通过测试才能知道优化后的worker的数量。可以通过持续的增加worker的数量直到集群中I/O or CPU达到饱和(saturate)。

    Unset or increase the refresh interval

      让变更的内容对搜索可见的操作称为refresh,这是一项开销很大的操作。频繁的refresh会对同时进行中的索引速率造成影响。

      默认情况下,Elasticsearch周期性的每一秒执行refresh。但只有最近30秒收到一个或者请求的索引才会按这种方式进行refresh。

      这是一个优化配置,如果没有或者有很少的搜索流量(search traffic,5分钟中有一次或者没有查询请求)就可以优化索引的速度。这个做法目的是在没有查询请求时能优化bulk Indexing。可以通过显示的设置refresh的间隔来opt out这种方式。

      另外,如果你的索引用于常规的查询请求(if your index experiences regular search requests),默认的行为意味着Elasticsearch每隔一秒种就会执行一次refresh。如果你能够承受(afford to)文档被索引后和对搜索可见之间的时间间隔,提高index.refresh_interval的值,比如说30s,以此来提高索引速度。

    Disable replicas for initial loads

      如果你想要马上将大量的数据写入到Elasticsearch中,可以将index.number_of_replicas设置为0来提高索引速度。没有副本(replica)意味着丢失单个节点后会遇到数据丢失,所以很重要的一点是数据在其他地方是live使得在最初的导入(initial load)在遇到这种情况时可以通过重试来解决这个问题。最初的导入完成后,你再把index.number_of_replicas的值设置为原来的值。

      如果在index settings中设置了index.refresh_interval,可以更助于在最初导入时先unset然后在完成后重新设置为原来的值。

    Disable swapping(how to)

      You should make sure that the operating system is not swapping out the java process by disabling swapping.

    Give memory to the filesystem cache

      文件系统缓存(filesystem cache)用于缓存I/O操作,你应该确保将运行 Elasticsearch 的机器的至少一半内存分配给文件系统缓存(You should make sure to give at least half the memory of the machine running Elasticsearch to the filesystem cache)。

    Use auto-generated ids

      当索引一个带有显示id(explicit id)的文档时,Elasticsearch会检查分片中是否有跟这个id一样的文档,这是一种开销大的操作并且随着索引量的增加开销会增加。通过自动生成的id,Elasticsearch会跳过检查来提高索引速度。

    Use faster hardware

      如果索引受 I/O 限制(I/O-bound),考虑增加文件系统缓存的大小(见上文)或使用更快的存储。Elasticsearch通常创建独立的文件并顺序写入(sequential write),然而索引过程中会并发写入多个文件,所以是随机和顺序写入的混合模式。因此SSD驱动器的性能往往比旋转磁盘(spinning disk)好。

    Indexing buffer size

      如果你的节点执行繁重的索引(heavy Indexing),确保indices.memory.index_buffer_size设置的足够大,让每一个正在执行繁重索引的分片最多拥有512M Indexing buffer(超过这个值通常不会再有提升)。Elasticsearch会让一个节点上所有活动的分片(active shard)都分享这个设置(a percentage of the java heap or an absolute byte-size)。非常活跃的分片自然的会比执行轻量级索引(lightweight indexing)的分片更多地使用这个缓冲区。

      默认值是10%,这个值通常是够用的:如果你分配给JVM 10G内存,那么1G的内存将会用于index buffer。这个值足够一个节点上的两个分片来执行繁重的索引。

    Use cross-cluster replication to prevent searching from stealing resources from indexing

      单个集群中,查询和搜索会为了资源进行竞争(compete for resources),通过设置两个集群并配置cross-cluster replication,将副本数据从一个集群复制到另一个集群中。并将所有的查询请求路由到follower index所在的集群,查询行为(search activity)将不再跟leader index所在的集群的索引(Indexing)抢夺资源。

    Additional optimizations

      另外在Tune for disk usage中提供了许多的策略也能提高索引的速度。

    Tune for search speed

    (8.2)link

    Give memory to the filesystem cache

      Elasticsearch非常依赖(heavily depend on)文件系统缓存来实现快速的查询。一般情况下你要让一半的内存用于文件系统缓存使得Elasticsearch让hot regions of the index保持在物理内存中。

    Avoid page cache thrashing by using modest readahead values on Linux

      查询会带来很多随机I/O访问。当底层的块设备(underlying block device)有大量的预读值(readhead value)时,会有很多不必要的I/O,特别是文件通过mmap(memory mapping )方式访问时。

      大多数的linux发行版会中的单个plain device会使用一个合理的128KiB的预读值。然而使用了software raidLVM或者dm-crypt后可能会导致块设备(用于支持Elasticsearch的path.data)使用一个很大的预读值(在几个 MiB 的范围内)。这通常会导致严重的页面(文件系统)缓存抖动(page cache thrashing adversely),从而对搜索(或update)性能产生不利影响。

      你可以使用lsblk -o NAME,RA,MOUNTPOINT,TYPE,SIZE检查当前以字节为单位的预读值。参考Linux发行版的文档来了解如何更改预读值(比如使用udev命令设置为一个常量,需要重启,或者通过blockdev --setra设置为一个临时的值),我们建议你将该值设置为128KiB

    NOTE:blockdev期望的是512个字节为一个扇区(section)的值然而lsblk的值是以KiB为单位的。如果要为/dev/nvme0n1的预读值临时设置为128KiB,可以这么指定:blockdev --setra 256 /dev/nvme0n1

    Use faster hardware

      如果查询受 I/O 限制(I/O-bound),考虑增加文件系统缓存的大小(见上文)或使用更快的存储。每一个查询涉及到在多个文件上进行随机和顺序的读取,并且可能在每一个分片上并发的进行查询。因此SSD驱动器的性能往往比旋转磁盘(spinning disk)好。

      Directly-attached类型的存储(local storage)通常比远程储存(remote storage)有更好的性能因为它配置更方便并且避免了communications overheads。通过精心的调整,远程储存也可以达到可接受的性能要求。使用实际的工作负载进行基准测试来检测你用于调整的参数。如果达不到你期望的性能要求,跟存储的供应商一起找出问题所在。

      如果查询受CPU限制,考虑使用更多更快的cpu。

    Document modeling

      可以对文档进行建模(Documents should be modeled),使得search-time的操作的开销尽可能的少。

      特别是尽量避免join,nested会以好几倍(several times)的代价降低查询速度并且parent-child relations会降低几百倍(hundreds of times)的查询速度。所以如果能通过重新标准化文档(denormalizing document)而不是用join解决同样的问题,那么可以获得非常好的查询速度。

    Search as few fields as possible

      query_string或者multi_match查询的字段越多,查询越慢。一个常用的用于提高查询速度的技术就是在索引阶段将多个字段的值索引到单个字段,然后只查询这个字段。可以通过copy_to实现自动的映射并且不需要更改源文档。下面的例子是一个包含电影的索引,该例子通过将电影的名称跟情节索引到name_and_plot字段来优化查询。

    Pre-index data

      你应该利用查询中的模式(pattern)来优化索引的方式。如果你的文档中有price字段并且大部分的查询是指定了多个范围的range聚合,你可以将范围信息写入到索引中,然后使用term聚合来提高聚合的速度。

      比如说文档长这个样子:

      并且查询请求长这个样子:

      然后这篇文档可以在索引期间丰富一个price_range字段,并且应该设为keyword类型。

      然后查询请求可以在新的字段上进行聚合查询而不是在price上执行range聚合。

    Consider mapping identifiers as keyword

      不是所有的数值类型的数据都必须用numeric类型的。Elasticsearch为integerlong这些数值类型的字段优化了range查询。然而keyword字段更适合用于term或者term-level的查询。

      类似ISBN或者产品ID的唯一标示(identifier),它们很少用于范围查询,然而它们经常使用term-level的查询。

      可以在下列的场景中考虑对数值类型的唯一标示使用keyword:

      如果你不确定怎么使用,可以通过multi-field 将数据同时索引为keyword或者数值类型的字段。

    Avoid scripts

      如果可以的话,避免在聚合中使用脚本、基于脚本的排序以及script_score查询。见Scripts, caching, and search speed

    Search rounded dates

      在时间类型的字段上使用now的查询通常是无法缓存的,因为匹配的时间范围一直在发生变更。然而在一些用户体验中对时间进行四舍五入(rounded)是可接受的,使得可以利用查询缓存的功能带来的好处。

      比如说下面这个查询:

      上面这个查询可以替换为下面这个:

      在上面的例子中, 我们对分钟进行了四舍五入,如果当前时间是16:31:29,这个范围查询将会匹配my_date字段上所有在15:31:0016:31:59之间的文档。如果一些用户执行了在同一分钟内的查询,查询缓存(query cache)会帮助提升一点查询速度。The longer the interval that is used for rounding, the more the query cache can help,但是注意的是过于激进的(too aggressive)四舍五入会降低用户的体验。

    NOTE:也可以尝试将查询范围切分为一个范围大可以缓存的部分和范围小但是不可以缓存的部分,这样就可以利用好查询缓存:

      然而这种方式在实践中可能会因为引入bool带来开销导致查询速度变慢,破坏了更好地利用查询缓存所节省的成本。

    Force-merge read-only indices

      那些只读的索引可以从merged down to a single segment中受益,这类索引通常是基于时间的索引(time-base indices):只有当前时间范围的索引会获取新文档,而旧索引是只读的。那些被force-merged到单个段的分片可以使用简单并且高效的数据结构来执行查询操作。

    IMPORTANT:不要force-merge索引到你正在写入的索引中,或者以后你会再次写入的索引中。而是依赖后台合并进程按需合并来保持索引平滑运行。如果你继续往一个合并后的索引中写数据会另性能变差。

    Warm up global ordinals

      Global ordinals是一个用来优化聚合的数据结构。它会被延迟计算并且保存在JVM堆中作为field data cache的一部分。用于频繁桶聚合(heavily used for bucket aggregation)的字段,可以在查询这些字段之前,让Elasticsearch对这些字段构造并且缓存global ordinals。注意的是这种操作会增加堆内存的使用并且增加refreshes 的时间。可以通过mapping参数eager global ordinals对现有的mapping进行动态的更新。

    Warm up the filesystem cache

      如果运行Elasticsearch的服务器重启了,那文件系统缓存会被清空。 所以需要一定的时间让操作系统将hot regions of the index 载入到内存中,使得可以查询操作可以变快。你可以使用 index.store.preload 设置明确地告诉操作系统哪些文件应该根据文件扩展名尽快的(eagerly)加载到内存中。

    WARNING:如果把太多的索引跟文件载入到内存中,并且文件系统缓存没有那么大来容下所有的数据,则会导致查询速度变慢。

    Use index sorting to speed up conjunctions(how to)

      Index sorting可以提高交集(conjunctions)查询的性能,代价是降低索引(Indexing)的速度。查看index sorting documentation了解更多内容。

    Use preference to optimize cache utilization

      有多种类型的缓存可以用来提高查询性能,比如filesystem cacherequest cache、以及 query cache。目前所有的缓存在节点层进行维护。如果你连续(in a row)执行两次相同的查询并且存在一个副本分片以及使用默认路由算法的round-robin,那这两次的查询会请求不同的两个分片,就没法使用节点层的缓存优化了。

      由于使用查询应用的用户先后执行相同的查询是很常见的。比如说为了分析索引的较窄子集(a narrower subset of the index),使用preference来标识当前用户或会话可以帮助优化缓存的使用。

    Replicas might help with throughput, but not always

      除了提高弹性(resiliency),副本分片可以用来提高吞吐量。比如说你有个单分片索引和三个节点,你可以将分片的数量设置为2来拥有一共三份分片的拷贝,这样所有的节点都可以用来查询。

      现在你想象你有一个索引,它有两个分片。在第一个场景中,副本分片的数量为0,那么每个节点都有单个分片。在第二个场景中,副本分片的数量为1,那么每个节点都有两个分片。哪一种方式可以有更好的查询性能呢?通常有较少分片的节点有更好的性能。原因是每一个分片可以有更大的文件系统缓存,这个文件系统缓存的大小是所有分片共享的,并且文件系统缓存可能是Elasticsearch性能指标中最重要的影响因子(the filesystem cache is probably Elasticsearch’s number 1 performance factor)。同时注意的是没有副本的那个场景在单个节点发生故障后就不可用了。所以要考虑好吞吐量跟高可用之间的trade-off。

      所以正确的分片数量是多少呢?如果集群中一共有num_nodes个节点,num_primaries个主分片。如果你想要最多能够承受max_failures个节点同时发生故障,那么正确的分片数量是:max(max_failures, ceil(num_nodes / num_primaries) - 1)

    Tune your queries with the Search Profiler

    (8.2)link

      Profile API提供了这次查询处理的详细信息,包括每一个子查询和聚合花费的时间。

      Kibana中的Search Profiler能更方便的定位和分析profile results,并让你深入了解如何调整查询以提高性能并减少负载。

      由于Profile API自身就会带来额外的开销,所以主要用来观察各个子查询之间相对的开销,不会真正的给出实际的处理花费的时间。

    Faster phrase queries with index_phrases

    (8.2)link

      text类型的字段有一个index_phrases选项会索引2-shingles,可以自动的被query parser用来查询查询没有间隔(slop)的短语查询(phrase query)。如果你的用例中有很多短语查询,那么这个选项可以很好的提高查询速度。

    Faster prefix queries with index_prefixes

    (8.2)link

      text类型的字段有一个index_prefixes选项会将所有term的前缀索引,可以自动的被query parser用来前缀查询(prefix query)。如果你的用例中有很多的前缀查询,那么这个选项可以很好的提高查询速度。

    Use constant_keyword to speed up filtering

    (8.2)link

      通常来说,filter的开销取决于匹配到的文档数量。比如你有一个包含车子(cycles)的索引,并且有大量的bicycles,然后很多的查询都是过滤出cycle_type: bicycle。这是一个很普通的过滤操作但是开销很大,因为匹配到了大量的文档。有一个简单的办法来避免执行这个过滤操作:将包含bicycles的文档索引到自己的索引中,并且通过查询这个索引来过滤bicycles,而不是作为一个filter query

      但是这样做会使得客户端的逻辑变得复杂(logic tricky),不过可以通过constant_keyword来帮忙。通过在包含bicycles的索引上将cycle_type的类型映射为constant_keyword并且赋值为bicycles,客户端可以使用相同的query查询整体的索引(monolithic index),Elasticsearch会在bicycles的索引上做出正确的方式,即忽略cycle_typebicycles的过滤,否则不返回任何命中。

      mapping看起来是这样的:

      我们把索引切分成了两个:一个索引只包含bicycle,另一个索引包含其他类型的车子:独轮车(unicycle)、三轮车(tricycle)。然后在查询期间,我们需要对两个索引进行查询,并且不需要更改query。

      bicycles索引上,Elasticsearch会简单的忽略cycle_type的过滤并且将query重写为下面的样子:

      other_cycles索引上,Elasticsearch会快速的判断出在cycle_type字段中不存在bicycles然后不返回任何的命中。

      将常用的值放在专用的索引上是一种非常有力的使得查询开销很小的一种方式。这个想法可以跨多个字段进行组合:比如说,如果你要跟踪每一种车子的颜色,并且bicycles索引中有大量的黑色的bicycles,那么你可以继续将索引划分成bicycles-blackbicycles-other-colors的两个索引。

      这种优化不是一定严格需要constant_keyword的:也可以在客户端的逻辑中基于不同的filter将查询路由到对应的索引上。然而constant_keyword能够让这个过程透明,并允许将搜索请求与索引拓扑分离,以换取非常少的开销。

    Tune for disk usage

    (8.2)link

    Disable the features you do not need

      默认情况下,Elasticsearch对大部分的字段同时进行索引(倒排、bkd)和添加doc value(正排),使得这些字段默认(out of box)可以用于查询和聚合。比如说你有一个名为foo的数值类型的字段,并且你需要在这个字段上进行histogram并且从来不会应用于filter,那你可以在mappings中安全的关闭索引(只使用bkd存储,不用倒排):

      text类型的字段会存储标准化因子(normalization factor)用于(facilitate)文档打分。如果你只关心是否匹配text字段而不用生成分数,那么你可以使用match_only_text。这种类型的字段会扔掉分数和位置信息来节省很大的空间。

    Don’t use default dynamic string mappings

      dynamic string mappings会默认将字符串的值用textkeyword进行索引,如果你只需要其中一种,那么显然这种默认的方式会有一些浪费。比如说id类型的值只需要用keyword字段类型进行索引而body类型的值只要用text字段类型进行索引。

      可以通过显示的(explicit)在字符串字段上或者在dynamic templates上进行配置,使得将字符串字段使用keyword或者text索引。

      比如,下面的模板将字符串字段使用keyword索引:

    Watch your shard size

      更大的分片(larger shard)更能有效的存储数据。你可以在creating indices时设置较少的分片,生成较少的索引(比如说利用Rollover API)或者使用Shrink API更改现有的索引来降低主分片的数量。

      注意的(keep in mind)是大分片(large shard)也会带来缺点,比如说分片恢复的时间会很长。

    Disable _source

      _source会存储文档对应的原始的json内容。如果你不需要的话可以关闭这个配置,然而访问_source的API比如说更新或者reindex将无法正常工作。

    Use best_compression

      _source和stored filed很容易占用大量的磁盘空间(can easily take a non negligible amount of disk space)。可以使用best_compression codec对这些数据进行更加激进的压缩。

    Force merge

      Elasticsearch中的索引会被存储在一个或者多个分片上。每一个分片是一个Lucene索引,这个索引由一个或者多个组成。每一个段中的文件都是磁盘上对应的文件。更大的段(larger segment)更能有效的存储数据。

      force merge API可以用来降低每一个分片中段的数量。大部分情况下,可以通过设置max_num_segments=1将每一个分片中段的数量降至一个。

    WARNING:Force merge should only be called against an index after you have finished writing to it。Force merge会产生非常大(> 5G)的段,并且如果你持续往这个索引里面写数据,自动执行的合并策略以后也不会将新的段进行合并直到这些段中的文档都是标记为被删除的。这会导致索引中有很多的大段并且降低查询性能

    Shrink index

      Shrink API可以让你降低索引的分片数量。结合上文中Force merge可以很好的降低分片数量以及分片中段的数量。

    Use the smallest numeric type that is sufficient

      numeric data选择不同的字段会对磁盘使用有着很大的影响。特别是integer应该使用integer类型(比如说byteshortintegerlong)存储并且浮点型数据应该要么使用scaled_float(如果合适的话),要么使用最小的类型(比特位):使用float而不是用double,使用half_float而不是用float也能帮助节省磁盘空间。

    Use index sorting to colocate similar documents

      当Elasticsearch存储_source时,会一次性的处理多个文档来提高压缩率。比如文档间包含相同的字段是很常见的,并且这些字段包含相同的值也是很常见的。especially on fields that have a low cardinality or a zipfian distribution。

      默认情况下会按照添加到索引的顺序对文档进行压缩。如果你开启了index sorting后则会根据排序后的文档进行压缩。排序后的文档有着类似的结构、字段、字段值,使得可以提高压缩率。

    Put fields in the same order in documents

      由于是多篇文档被压缩到block中,所以如果每篇文档中_source中的字段是有序的,那么更容易找到更长的相同的值(duplicate strings)。

    Roll up historical data

      保留旧的数据对以后进行数据分析是有帮助的。但由于磁盘开销经常就不会保留。你可以使用data rollups以原始数据存储成本的一小部分来汇总和存储历史数据。见Rolling up historical data了解更多内容。

    Fix common cluster issues

    (8.2)link

      这一章节介绍如何处理Elasticsearch集群的一些常见错误和问题。

    Error: disk usage exceeded flood-stage watermark, index has read-only-allow-delete block

      这个错误指出数据节点的磁盘空间大小已经严重不足(critical low)了并且达到了flood-stage disk usage watermark。为了防止出现full disk,当一个节点达到watermark,Elasticsearch会block在这个节点上写入索引。如果这个block影响到了系统的索引,Kibana和其他Elastic Stack feature可能会不可用。

      当受到影响的节点的磁盘使用量降到high disk watermark以下,Elasticsearch会自动移除write block。Elasticsearch会自动的将受到影响的节点的分配移动到有相同data tier的其他节点上。

      若要验证分片已从受到影响的节点上移走,使用cat shards API

      如果分片仍然在节点上,使用cluster allocation explanation API 获取分配状态的介绍。

      如果要马上恢复写操作,你可以临时的提高disk watermark然后移除write block。

      作为长期解决方案(long-term solution)。你应该在受到影响的data tier中添加节点或者更新现有的节点的磁盘空间。若要释放额外的磁盘空间,你可以使用delete index API来删除不需要的索引。

      当一个长期解决方案落实后,重置或者重新配置disk watermark。

    Circuit breaker errors

      Elasticsearch使用circuit breakers防止节点发生OOM。如果Elasticsearch估算出一个操作会超出circuit breakers,它将停止这个操作并返回一个错误。

      默认情况下,parent circuit breaker在达到95%的JVM内存量时触发。为了防止错误的发生,我们建议使用量一旦超过85%时就采取行动来降低内存压力。

    Diagnose circuit breaker errors
    Error messages

      如果一个请求触发了circuit breaker,Elasticsearch会返回一个429的错误码。

      Elasticsearch同样会将circuit breaker的错误写入到elasticsearch.log中,这有助于记录一些自动处理,例如分配这种操作触发circuit breaker对应的错误。

    Check JVM memory usage

      如果你开启了Stack Monitoring,你可以在Kibana中查看JVM的内存使用。在主菜单中,点击Stack Monitoring。在Stack Monitoring的Overview页面,点击NodesJVM Heap会列出每一个节点的当前内存使用情况。

      你同样可以使用cat nodes API 来获取每一个节点当前的heap.percent

      若要获取每一个circuit breaker的JVM 内存使用量。使用node stats API

    Prevent circuit breaker errors
    Reduce JVM memory pressure

      高的JVM内存压力通常会导致circuit breaker error,见 High JVM memory pressure

    High CPU usage

      Elasticsearch使用thread pools来管理并发操作所需的CPU资源,High CPU usage通常说的是一个或者多个线程池运行不足(running low)。

      如果一个线程池耗尽(depleted)了,Elasticsearch会reject跟线程池相关的request。例如如果search 线程池耗尽了,Elasticsearch会reject查询请求直到有可用线程。

    Diagnose high CPU usage
    Check CPU usage

      响应中cpu这一列包含了当前CPU使用量的百分比,node这一列包含了节点的名称。

      响应中cpu这一列包含了当前CPU使用量的百分比,node这一列包含了节点的名称。

    Check hot threads

      如果一个节点有很高的CPU使用量,使用nodes hot threads API 检查正在节点上运行的资源密集(resource-intensive)的线程。

      这个API会返回hot thread的plain text形式的breakdown。

    Reduce CPU usage

      下面的内容介绍常见的导致high cup usage以及解决方案。

    Scale your cluster

      繁重的Index和search负载会耗尽(deplete)smaller thread pool。若要能更好的处理繁重的负载,在你的集群中添更多的节点或者更新现有的节点来提高承载能力(capacity)。

    Spread out bulk requests(1)

      尽管bulk indexing multi-search的请求比单独的请求有更高的效率,但是它们要求更高的CPU usage。如果可以的话,提交数量较小的请求然后运行提交多次。

    Cancel long-running searches

      运行时间长的查询会阻塞住search 线程池中的线程。使用task management API来检查这些运行时间长的查询。

      response中的description描述了请求索引以及query信息。running_time_in_nanos描述了这个查询已经运行了的时间。

      若要取消一个查询并且释放资源,使用endpoint _cancel

      Avoid expensive searches了解更多关于跟踪以及避免资源密集型的查询的内容。

    High JVM memory pressure

      High JVM memory usage会降低集群的性能以及触发circuit breaker errors。为了防止发生这个情况,我们建议当节点的JVM内存使用量一旦超过85%时就要采取行动来降低内存压力。

    Diagnose high JVM memory pressure
    Check JVM memory pressure

      你也可以使用nodes stats API来计算每一个节点上的内存压力。

      使用response中的内容按照下面的方式计算内存压力:

      JVM Memory Pressure = used_in_bytes / max_in_bytes

      你也可以使用nodes stats API来计算每一个节点上的内存压力。

      使用response中的内容按照下面的方式计算内存压力:

      JVM Memory Pressure = used_in_bytes / max_in_bytes

    Check garbage collection logs

      随着内存使用量的增加,垃圾回收器会变的更加频繁并消耗更长的时间。你可以在elasticsearch.log中垃圾回收器事件的频率跟长度(the frequency and length of garbage collection events)。例如下面的例子中,Elasticsearch花费了超过一般的时间来执行垃圾回收。

    Reduce JVM memory pressure
    Reduce your shard count

      每一个分片都会占用内存,大多数情况下,体积很大但是数量较小的分片比体积很小但是数量较大占用更少的资源。见Size your shards来降低分片的数量。

    Avoid expensive searches

      Expensive searches会使用大量的内存。可以开启show logs来更好的追踪集群上的expensive searches。

      Expensive searches可能是因为使用了非常大的size argument,使用了大量分桶的聚合,或者包含了expensive queries。若要防止expensive searches,考虑进行更改下面的设置:

    Prevent mapping explosions

      定义太多的字段,或者嵌套的字段太深会导致mapping explosions,使得占用大量的内存。若要防止mapping explosions,使用mapping limit settings 来限制字段的数量。

    Spread out bulk requests

      尽管bulk indexing multi-search的请求比单独的请求有更高的效率,但是它们造成更高的JVM memory pressure。如果可以的话,提交数量较小的请求然后运行提交多次。

    Upgrade node memory

      繁重的索引跟查询会带来较高的JVM memory pressure。为了能更好的处理高负载,升级你的节点,提高内存容量。

    Red or yellow cluster status

      red或者yellow的集群状态说明一个或者多个分片missing或者未分配(unallocated)。这些为unassign的分片会带来丢失数据的风险以及降低集群性能。

    Diagnose your cluster status
    Check your cluster status

      使用cluster health API

      一个健康的集群的颜色是green,并且没有unassigned_shardsyellow意味着只有副本分片没有被assign。red意味着一个或者多个主分片没有被assign。

    View unassigned shards

      若要查看unassigned分片,使用cat shards API

      unassigned的分片有UNASSIGNED的状态。prirep的值为p时指的是主分片,值为r时指的是副本分片。

      若要明白为什么unassigned 分片没有被assign以及你应该采取行动运行Elasticsearch去assign这个分片,使用cluster allocation explanation API

    Fix a red or yellow cluster status

      一个分片不能被assign有很多的原因。下面列出了最常见的原因以及解决方案。

    Re-enable shard allocation

      你通常会在restart节点或者维护节点时关闭分配(disable allocation)。如果你忘记了重新开启它,Elasticsearch将无法assign分片。若要开启,reset集群设置cluster.routing.allocation.enable

    Recover lost nodes

      当data node离开集群后分片会无法被assign。导致这个的原因很多,从连接问题到硬件问题。当你处理完这些问题并恢复节点后,它会重新加入到集群中。Elasticsearch将随后自动的分配(allocate)那些未assign的分片。

      为了避免资源浪费以及temporary issue,Elasticsearch会默认delays allocation一分钟。如果你想要恢复一个节点并且不想等待延迟周期(delay period)。你可以调用不携带参数cluster reroute API来启动分配处理(allocation progress)。这个处理在后台异步处理。

    Fix allocation settings

      错误的配置可能会导致一个unassgin的主分片。这些设置包括:

      若要查看分配设置,可以使用get index settingscluster get settings

      你可以使用update index settingscluster update settings来更改这些设置。

    Allocate or reduce replicas

      为了应对硬件故障,Elasticsearch不会将副本分片和主分片分配到相同的节点上。如果没有其他data node可以存放这个副本分片,它仍然是unassign的。若要修复这个问题,你可以:

    Free up or increase disk space

      Elasticsearch会使用low disk watermark来保证data node 有足够的磁盘空间来处理即将生成的分片。默认情况下,Elasticsearch不会将分片分配到磁盘使用超过85%的节点上。

      若要检查当前节点的磁盘使用情况,使用cat allocation API

      如果节点的磁盘空间不足,你有下面的Optional:

    Reduce JVM memory pressure

      分片的分配需要JVM heap memory。高的内存压力会导致circuit breakers,它会停止分配使得分片无法被assign。见High JVM memory pressure

    Recover data for a lost primary shard

      如果某个节点上的主分片丢失了,Elasticsearch通常会使用另一个节点的副本分片来替代它。如果你不能恢复节点并且不存在副本分片或者它无法用于恢复。那你需要从snapshot中或者源数据(original data source)重新添加。

    WARNING:只有再也无法恢复节点的情况下才考虑这个选项。这个操作会分配一个空的主分片。如果节点随后重新加入到集群。Elasticsearch会用新的空的分片中的数据进行覆盖,导致数据丢失。

      使用cluster reroute API手动的分配一个unassign的主分片到另一个相同node tier的data node中。设置accept_data_losstrue

      如果你使用snapshot备份了丢失的索引数据,使用 restore snapshot API来恢复。或者你可以从源数据中重新索引一遍。

    Rejected requests

      当Elasticsearch reject一个请求,它会停止这个请求的操作并且返回429的响应码。请求被reject通常由下面的情况导致:

    Check rejected tasks

      可以使用cat thread pool API检查每一个thread pool中reject的任务数量。特别是在searchwrite thread pool中rejected to completed的任务的比例很高,意味着Elasticsearch经常(regular)reject请求。

    Prevent rejected requests
    Fix high CPU and memory usage

      如果Elasticsearch经常reject请求或者其他任务,说明你的集群可能有很高的CPU或者JVM内存的使用压力。见High CPU usageHigh JVM memory pressure

    Prevent circuit breaker errors

      如果你经常触发circuit breaker errors,见Circuit breaker errors进行诊断并防止再次出现。

    Task queue backlog

      用于积压任务的队列会导致任务无法完成并让集群陷入不健康的状态。资源受限(resource constraint),触发大量的任务以及长时间运行的任务都会导致任务积压。

    Diagnose a task queue backlog
    Check the thread pool status

      depleted thread pool会导致rejected requests

      你可以使用cat thread pool API查看每一个线程池中活跃的线程数量以及有多少个任务在排队,有多少被reject,以及有多少已经完成。

    Inspect the hot threads on each node

      如果某个线程发生了积压,你可以周期性的调用Nodes hot threads来查看是否线程有足够的资源处理以及观察它处理的速度。

    Look for long running tasks

      长时间运行的任务也会导致积压,你可以使用task management API 获取运行中的任务的信息。检查running_time_in_nanos来确认任务是否花费了特别长的时间。

    Resolve a task queue backlog
    Increase available resources

      如果任务允许缓慢并且队列发生堆积,你可能需要采取行动来Reduce CPU usage

      在一些用例中,提高thread pool size可能会有帮助。例如force_merge thread pool默认只有一个线程,提高两个线程有助于降低合并线程的堆积。

    Cancel stuck tasks

      如果你发现活跃的线程没有在处理并且发生了堆积,可以考虑取消这个任务。

    Size your shards

    (8.2)link

      Elasticsearch中的每一个索引会被划分成一个或多个分片,每一个分片有对应的副本分片(replica),这些副本分布在多个节点上,用于应对硬件故障。如果你正在使用Data streams,每一个data stream会通过a sequence of indices实现备份。单个节点上能存储的数据量是有限制的,所以你可以通过添加节点和提高索引以及分片的数量 的方式来提高集群的承载能力。然而每一个索引和分片都是有开销的,如果你将数据划分出太多的分片,那么其开销会很大(overwhelming)。有太多索引或者分片的集群会有oversharding的问题。一个oversharding 的集群在响应查询方面会变得低效,极端情况下(in extreme case)会导致集群不稳定。

    Create a sharding strategy

      防止oversharding以及其他分片相关(shard-related)问题最好的办法 就是创建一个分片策略( sharding strategy)。sharding strategy通过限制分片的数量来帮助你明确以及维护集群中进行优化后的分片数量。

      不幸的是,不存在 one-size-fits-all的sharding strategy。在某个环境中工作不错的策略可能不适用于其他环境。一个好的sharding strategy必须考虑 你的基础设施,用例以及性能预期(performance expectation)。

      创建sharding strategy最好的方式就是使用与生产环境相同的硬件,对生产数据使用跟生产中相同的查询和索引负载进行基准测试。可以查看quantitative cluster sizing video了解我们的推荐方式。若要测试不同的分片配置,使用Kibana的Elasticsearch monitoring tools来跟踪集群的稳定性和性能。

      下面的内容提供了一些提醒(reminder)以及指导你在创建你自己的sharding strategy时需要考虑的点。如果你的集群已经有oversharding的问题,见Reduce a cluster’s shard count

    Sizing considerations

      在构建你自己的sharding strategy时,要牢记下面的内容:

    Searches run on a single thread per shard

      大多数的查询会命中多个分片。每一个分片上运行查询时需要一个CPU线程。一个分片上运行多个并发的查询,在大量的分片上查询会消耗(deplete) search thread pool。这会导致吞吐量和查询速度的下降。

    Each index, shard, segment and field has overhead

      每一个索引和每一个分片需要内存和CPU资源。大多数情况下,数量少但是体积大的分片比数量多体积小的分片使用更少的资源。

      段(segment)在分片的资源使用中起着重要的作用。大多数的分片包含多个段,段中存放了索引数据。Elasticsearch会在内存中保留一些segment metadata用于快速的查询。随着分片的增长,分片中的段会merged成数量更少,体积更大的段。合并可以降低段的数量,意味着在堆内存中保留更少的metadata。

      mapping中的每一个字段都会带有一些内存使用和磁盘空间的开销。默认情况下,Elasticsearch会自动创建被索引的文档中每一个字段的mapping,但是你可以通过take control of your mappings来关闭这个行为。

      并且segment会为每一个mapped field分配少量的堆内存。这个 per-segment-per-field的内存开销包括copy of the field name,使用 ISO-8859-1或者UTF-16编码。尽管它们占用的内存量不是很显著(not noticeable),但如果你的分片有很多的段,相关的mapping中包含了很多的字段或者非常长的字段名,这时候你是需要考虑它们的开销的。

    Elasticsearch automatically balances shards within a data tier

      集群中的所有节点会被分组到data tiers,在每一层,Elasticsearch会尝试将索引的分片尽可能的分布到许多节点上。当你添加了 一个新节点或者一个节点发生了故障,Elasticsearch会自动的在同一层中剩余节点上进行rebalance。

    Best practices

      如果适用的话,使用下面的最佳实践开始创建你的sharding strategy。

    Delete indices, not documents

      被删除的文档不会马上从Elasticsearch的文件系统中移除。而是在每一个相关的分片上将这些文档标记为被删除的。这些被标记的文档仍然会占用资源,直到在周期性的segment merge中移除。

      如果可以的话,删除整个索引。Elasticsearch会马上从文件系统中移除被删除的索引并释放资源。

    Use data streams and ILM for time series data

      Data streams可以让你在多个基于时间的backing索引中存储时序数据。你可以使用index lifecycle management来自动的管理这些backing 索引。

      这个设置的其中一个好处就是automatic rollover,它会在满足定义的max_primary_shard_sizemax_agemax_docsmax_size阈值后创建一个新的write index。当不再需要某个索引时,你可以使用ILM自动的删除它并释放资源。

      ILM可以让你随时轻松更改你的sharding strategy:

      每一个新backing index都是进一步调整策略的机会。

    Aim for shard sizes between 10GB and 50GB

      体积很大的分片会在发生故障后进行恢复时花费更多的时间。当一个节点发生故障,Elasticsearch会在同一层中剩余节点上进行rebalance。恢复的过程通常包括通过网络拷贝分片的内容,所以一个100G的分片会比50GB的分片花费两倍的时间。相比之下,体积小的分片会有更多的开销并且更低的查询效率。查询50个1GB的分片会比查询单个50GB包含相同内容的分片花费更多的资源。

      尽管在分片大小上没有严格的限制,但是从经验上来说,大小在10GB和50GB之间能很好的在日志以及时序数据上工作。你可能会基于你的网络以及用例使用体积更大的分片。较小的分片可能适用于Enterprise Search和类似用例。

      如果你使用ILM,设置rollover actionmax_primary_shard_size阈值到50gb来避免分片的大小超过50GB。

      使用cat shards API来查看分片当前的大小。

      pri.store.size的值显示了这个索引的所有主分片的大小总和。

    Master-eligible nodes should have at least 1GB of heap per 3000 indices

      master node能管理的索引数量跟它的堆大小成比例(proportional )。每一个索引对应的准确的堆内存大小取决于多个因素,例如mapping的大小和每一个索引的分片数量。

      作为一般的经验法则(As a general rule of thumb),master node上有1GB的内存就应该拥有不大于3000个索引。例如,如果你的集群中有一个拥有4GB的dedicated master node,那你应该拥有不大于12000个索引。如果你的master node不是dedicated master node:你应该让集群中每一个master-eligible node有1GB的内存就应该拥有不大于3000个索引。

      注意的是这个规则定义的是一个master node能管理的绝对最大数量的索引,但是不能保证在这么多数量的索引下的查询或者索引的性能。你必须保证你的data node有足够的资源满足你的工作负载,并且你整体的sharding strategy能满足你所有的性能要求。见Searches run on a single thread per shardEach index, shard, segment and field has overhead

      使用cat nodes API检查每一个节点的内存配置。

      你可以使用cat shards API检查每一个节点的分片数量。

    Data nodes should have at least 1kB of heap per field per index, plus overheads

      每一个mapped field需要的准确的资源使用量取决于字段的类型,但是一般的经验法则是允许每一个索引的每一个字段要有接近1KB的内存。你必须还要允许有足够的堆内存用于Elasticsearch最基本的用于索引,查询或者聚合所需要的内存。0.5GB的内存对于大多数的合理的工作负载都是够用的。如果你的工作负载是轻量级的那么可以需要更少的内存,反之需要更多的内存。

      例如,如果节点中有1000个索引,每一个索引包含了4000个mapped field,那么你应该允许为这些字段分配接近1000 * 4000 * 1KB = 4GB的内存,以及额外的0.5GB用于工作负载和其他开销。因此这个节点需要至少4.5GB。

      注意的是这个规则定义的是一个data node能管理的索引的绝对最大数量,但是不能保证在这么多数量的索引下的查询或者索引的性能。你必须保证你的data node有足够的资源满足你的工作负载,并且你整体的sharding strategy能满足你所有的性能要求。见Searches run on a single thread per shardEach index, shard, segment and field has overhead

    Avoid node hotspots

      如果太多的分片分配到了一个指定的节点,这个节点会成为一个热点(Hotspot)节点。例如,如果单个节点包含一个索引并带有大规模的索引操作,这个索引会有太多的分片,这个节点则很有可能出现问题。

      为了防止出现Hotspot。使用索引设置index.routing.allocation.total_shards_per_node来显示的(explicit)限制单个节点上分片的数量。你可以使用update index settings API配置index.routing.allocation.total_shards_per_node

    Avoid unnecessary mapped fields

      默认情况下,Elasticsearch会为文档中的每一个字段automatically creates a mapping。每一个mapped field对应磁盘上的一些数据结构,使得用于高效的查询,检索以及聚合。Details about each mapped field are also held in memory。在很多用例中这种开销是不需要的因为有些字段没有用于查询或者聚合。使用Explicit mapping替换dynamic mapping来防止创建从不会被使用的字段。如果有些字段通常一起使用,考虑在索引阶段使用copy_to。如果一个字段很少被使用,使用Runtime field可能更合适。

      你可以通过Field usage stats API获取哪些字段正在被使用的信息,并且你可以通过Analyze index disk usage API分析mapped field的磁盘使用。注意的是,不必要的mapped field也会带来一些内存开销以及它们的磁盘使用。

    Reduce a cluster’s shard count

      如果集群中已经oversharded了,你可以使用下面的一个或者多个方法来减少分片数量。

    Create indices that cover longer time periods

      如果你使用了ILM并且retention policy允许的话,不使用max_age阈值用于rollover action,而是使用max_primary_shard_size来避免创建空索引或者许多小的分片。

      如果你的retention policy要求max_age阈值,提高阈值来处理longer time interval。例如你可以按周或者按月创建索引而不是按天创建。

    Delete empty or unneeded indices

      如果你正在使用ILM并且基于max_age阈值对索引roll over,你可能会在不经意间(inadvertently)创建没有文档的索引。这些空的索引没有什么用但仍然会消耗资源。

      你可以使用 cat count API找出空的索引。

      一旦有了空的索引列表,你可以使用delete index API删除它们。你也可以删除不再与需要的索引。

    Force merge during off-peak hours

      如果你不再往一个索引中写入数据,你可以使用force merge API将小段merge到大段中。 这样能降低分片开销并能提高查询速度。然而force merge是一种资源密集型(resource-intensive)的操作,如果可以的话,尽量在非高峰期(off-peak)运行。

    Shrink an existing index to fewer shards

      如果你不再往一个索引中写入数据,你可以使用shrink index API 来降低分片数量。

      ILM同样在warm阶段有shrink action

    Combine smaller indices

      你也可以使用reindex API 将mapping类似的索引合并到一个更大的索引中。对于时序数据,你可以将短时间周期(short time period)的索引重新索引到长时间周期的索引中。类,例如你可以基于索引名模板重新索引按天索引的数据,例如my-index-2099.10.11重新索引到按月索引的my-index-2099.10中。reindex之后,删除按月索引的索引。

      下面介绍的是常见的分片相关的错误的解决办法。

    this action would add [x] total shards, but this cluster currently has [y]/[z] maximum shards open;

       集群的设置cluster.max_shards_per_node限制了集群中可以打开的分片的最大数量。这个错误说的是某个行为会超过这个限制。

      如果你有信心保证你的更改不会降低集群的稳定性,你可以通过cluster update settings API临时的提高限制然后重新这个行为。.

      这种解决方式只能是临时解决方案。作为一个长期解决方案,我们建议在发生oversharded的数据层添加节点或者reduce your cluster’s shard count。在做出变更后可以通过 cluster stats API查看当前的分片数量。

      当部署了一个长期解决方案后,我们建议你reset cluster.max_shards_per_nod

    Use Elasticsearch for time series data

    (8.2)link

      Elasticsearch提供的功能能帮助你存储,管理,以及搜索时序数据,例如日志和指标。使用了Elasticsearch后,你可以使用Kibana和其他Elastic Stack来分析以及可视化你的数据。

    Set up data tiers

      Elasticsearch的ILM使用data tiers根据索引的寿命(age)自动的将旧的数据移动到成本较低的硬件中。这有助于提高性能以及降低存储开销。

      hot和content层是必须要有的,而warm,cold以及frozen 层是可选的。

      在hot和warm层使用高性能的节点用于快速的索引和查询最近的数据。在cold和frozen层使用较慢,成本较低的节点来降低开销。

      设置datatiers的步骤基于你的部署类型:

      我们建议你在frozen tier使用专门的节点。如果有需要的话,你可以给一个节点赋予多个data tier。

      为你集群中的节点分配其他的角色。例如,一个小规模的集群中一个节点可以有多个角色。

    Register a snapshot repository ()

      cold和frozen层可以使用searchable snapshots来降低本地储存开销。

      若要使用searchable snapshots,你必须要注册一个支持的snapshots repository。注册的步骤取决于你的部署和提供的存储而有所不同:

    Elasticsearch Service
    Self-managed

    Create or edit an index lifecycle policy

      data stream在多个backing索引中存储你的数据。ILM使用一个index lifecycle policy自动的将这些索引移动到你的data tier。

      如果你使用Fleet或者Elastic Agent,可以编辑Elasticsearch内置的lifecycle policy。如果你使用自定义的应用,则需要创建你自己的策略:

    Fleet or Elastic Agent

      Fleet和Elastic Agent使用下列内置的生命周期策略“

      你可以基于你自己的性能,弹性(resilience)以及保留需求(retention requirement)自定义策略。

      若要在Kibana中编辑一个策略,打开主菜单然后跳转到Stack Management > Index Lifecycle Policies,点击你想要编辑的策略。

      你可以使用update lifecycle policy API

    Custom application

      若要在Kibana中创建一个策略,打开主菜单然后跳转到StackManagement > Index Lifecycle policies。点击 Create policy

      你可以使用update lifecycle policy API

    Create component templates

    TIP:如果你使用Fleet或者Elastic Agent,跳过Search and visualize your data。Fleet和Elastic Agent使用内置的模板为你创建data streams

      如果你使用自定义的应用,你需要设置你自己的data stream。data stream要求用于匹配的index template。大多数情况下,你会使用一个或多个component template组合成index template。你通常为mapping和index setting使用不同的component template。这可以让你在多个index template中复用component template。

      当你创建component template,包括:

    TIP:当对字段进行映射时,使用Elastic Common Schema (ECS)。ECS fields integrate with several Elastic Stack features by default。

    如果你不确定如何映射字段,使用runtime fields在查询期间从unstructured content 中提取字段。例如你可以索引一条日志消息为wildcard,随后在查询中从这个字段中提取出IP address和其他数据。

      若要在Kibana中创建一个component template,那么打开主菜单然后跳转到Stack Management > Index Management。在Index Templates视图中,点击Create component template

      你也可以使用create component template API

    Create an index template

      使用你的component templates来创建一个index template:

      若要在Kibana中创建一个index template,那么打开主菜单然后跳转到Stack Management > Index Management。在Index Templates视图中,点击Create template

      你也可以使用create index template API。包含data_stream object可以模版用于data streams。

    Add data to a data stream

      Indexing requests将添加文档到data stream中。这些请求必须是使用createop_type。文档中必须包含一个@timestamp字段。

      若要自动的创建你的data stream,指定stream的名称并提交一个索引请求。这个名称必须匹配你的index template的index patterns中的一个。

    Search and visualize your data

      若要在Kibana中展示并且查询你的数据。打开主菜单然后选择Discover。见Kibana的Discover documentation

      使用Kibana的Dashboard功能,在图表、表格、地图中可视化你的数据。见Kibana的Discover documentation

      你也可以使用search API查询或者聚合你的数据。使用runtime fields grok patterns 自动的在查询阶段从日志消息和其他非结构化数据中提取数据。

      Elasticsearch的查询默认是同步操作。跨frozen data,long time ranges,large datasets这些查询可能需要较长时间。可以使用async search API 在后台允许这些查询。更多的查询选项见Search your data

    REST APIs

    link

    API conventions

    link

    Date math support in index and index alias names

    Multi-target syntax

    ignore_unavailable
    Hidden data streams and indices
    System indices
    allow_no_indices

    Byte size units

    Time units

    Common options

    link

    Date Math

    Response Filtering

    Fuzziness(Common options)

    Compact and aligned text (CAT) APIs

    link

    cat fielddata API

    link

    cat indices API

    link

    cat nodes API

    (8.2)link

    IMPORTANT:cat APIs只能在命令行或者Kibana控制台中人为使用。不应该在应用中使用。若要在应用中使用,则使用nodes info API

      返回集群中节点的信息。

    Request

    GET /_cat/nodes

    Prerequisites
    Query parameter
    Examples
    Example with default columns

      API返回下面的响应:

      ipheap.percentram.percentcpuload_*这个几列提供了每一个节点的IP地址跟性能信息。

      node.rolemastername这几列提供了整个集群的有用信息,特别是在规模较大的集群中。

    Example with explicit columns

      下面的API请求会返回idipportv(version)以及m(master)这几列。

      API返回下面的响应:

    cat recovery API

    link

    cat shards API

    (8.2)link

    IMPORTANT:cat APIs只能在命令行或者Kibana控制台中人为使用。不应该在应用中使用。

      shard命令详细的展示了哪些节点包含了哪些分片,它能告诉你是主分片还是副本分片,文档的数量,磁盘占用的字节数以及分片在哪个节点上。

      对于data stream,API会返回stream中backing Index的信息。

    Request

    GET /_cat/shards/<target> GET /_cat/shards

    Prerequisites
    Path parameters
    Query parameter
    Examples
    Example with a single data stream or index

      API返回下面的响应:

    Example with a wildcard pattern

      如果你的集群中有很多的分片,你可以在<target>中使用wildcard pattern来限制API的请求。

      下面的请求返回索引名以my-index-开头的所有的data stream或者index。

      API返回下面的响应:

    Example with a relocating shard

      API返回下面的响应:

      state列中的值RELOCATING说明索引分片正在重新分配中。

    Example with a shard states

      某个分片在可以使用之前,它会经历INITIALIZING状态。你可以使用cat shards API来查看哪些分片正在初始化。

      API返回下面的响应:

    Example with reasons for unassigned shards

      下面的请求会返回unassigned.reason这一列,来查看某个分片为什么未分配。

      API返回下面的响应:

    cat thread pool API

    link

    Cluster APIs

    (8.2)link

    Node specification

      可以通过指定node filters,让一些cluster-level API只在一个节点子集合上操作。例如Task ManagementNodes StatsNodes Info这些API只报告(report)筛选出的一个节点集合,而不是所有节点的结果。

      node filters是一组独立的过滤项(individual filter)并且用逗号隔开。每一个过滤项会从已选择的节点结合中增加或者移除节点。每一个过滤项可以是下列之一:

    NOTE:node filter按照给定的顺序有序执行,这个规则对于从节点集合中移除节点是很重要的。比如说过滤项为_all, master:false时的意思是 除了master-eligible之外的所有节点,而master:false, _all则是跟_all是同一个意思,因为_allmaster:false之后运行,也就是_all会把所有的节点都添加到集合中。

    NOTE:如果没有给定过滤项,默认就是选择所有的节点。然而如果给定了任意的过滤项,那么则是从一个空的节点子集开始处理。意味着比如master:false这种过滤项,只有放在其他过滤项之后使用才能发挥作用。如果只指定了master:false,那么不会添加任何的节点到子集中。

      下列是一些使用node filterNodes Info API的例子:

    Cluster allocation explain API

    (8.2)link

      提供某个分片当前的分配信息

    Request

    GET _cluster/allocation/explain POST _cluster/allocation/explain

    Prerequisites
    Description

      该API 的目的是提供集群中分片分配的信息。对于未分配的分片,这个API会提供未分配的原因。对于已分配的分片,这个API会提供为什么这个分片仍然在当前节点并且还未移动或者Rebalance到其他的节点的原因。当尝试诊断某个分片为什么还未分配或者分片不像你期望那样仍然在当前节点时使用这个API就非常的有用。

    Query parameters
    Request body
    Example
    Unassigned primary shard

      下面的请求为一个未分配的主分片返回分配信息。

      API响应中指出这个分片只能被分配到一个不存在的(nonexistent)节点上。

      第5行,当前分片的状态   第7行,分片最开始未分配的原因   第11行,能否能分配这个分片   第19行,是否能将这个分片分配到指定的节点   第23行,desider为这个节点指向了no decision   第25行,解释了为什么desider返回了一个no decision,并且给出了有用的信息:配置导致指向这个no decision

      下面的响应中为一个未分配的主分片提供了一个分配信息,这个分片之前已经被分配了。

    Unassigned replica shard

      下面的响应中为副本分片提供了一个分配信息,是因为delayed allocation导致的。

      第14行,由于刚刚离开集群的节点拥有这个分片,并且配置了1m的延迟(如果在超时前那个节点重新回到集群,就不用生成新的副本分片)   第16行,即将分配副本分片的剩余时间   第30行,节点上分片数据的信息

    Assigned shard

      下面的响应中为一个已分配的分片提供了分配信息。这个响应指出该分片不允许继续呆在当前节点上,必须重新分配。

      第11行,分片是否允许一直待在当前节点上   第12行,decider指出为什么分片不允许待在当前节点上   第19行,分片是否允许移动到其他节点上

      下面的响应中为一个必须仍然待在当前节点的分片提供了分配信息。移动到其他节点不会提高集群的平衡。

      第13行,集群是否允许Rebalance   第14行,分片是否能Rebalance到其他节点   第21行,分片不能Rebalance到其他节点的原因,指出相较于待在当前节点并不能通过移动到其他节点来获得更好的平衡

    No arguments

      如果你不带参数调用这个API,Elasticsearch会随意的找出一个未分配的主分片或者副本分片并提供分配信息。

      如果集群中没有未分配的分片,API则返回400的错误。

    Cluster get settings API

    (8.2)link

      返回集群层面的设置:

    Prerequisites
    Request
    Description

      默认情况下,这个API只返回显示定义的设置,但也可以通过使用include_defaults参数返回一些默认设置。

    Query parameters

    Cluster health API

    (8.2)link

      返回集群的健康状态。

    Request

      GET /_cluster/health/<target>

    Prerequisites
    Description

      cluster health API返回一个集群较简明的状态。你可以通过这个api只获取指定的data stream和index。对于data stream,该API会检索(retrieve)流中backing index的健康状态。

      集群健康状态是greenyellow,或者red。在分片层,red说明分片没有被分配到集群中,yellow说明主分片已经被分配了,但是副本分片(replica)没有分配。green说明所有的分片(主分片和副本分片)都已经被分配。index level的状态由最差的分片状态决定。cluster level的状态由最差的index level的状态决定。

      这个API最重要的好处能够等待集群达到某个特定的(a certain high water-mark)健康状态。例如,下面的请求会等等待集群变成yellow状态,最多等待50秒(如果在50秒之前就达到了green或者yellow,那么就马上返回)。

    Path parameters
    Query parameters
    Response body
    Example

      API的响应中是一个单机群的、单索引、单个主分片/副本的例子:

      下面是获取分片层(shard-level)集群状态的请求:

    Cluster reroute API

    (8.2)link

      更改集群中分片的分配。

    Request

      POST /_cluster/reroute

    Prerequisites
    Description

      reroute命令允许你手动改变集群中的单个分片的分配。例如你可以显示的将一个分片从一个节点移动到另一个节点,可以取消分片的分配并且没有被分配的分片可以显示的分配到指定的节点上。

      很重要的一个注意点是在reroute命令执行后,Elasticsearch会执行rebalancing(遵循cluster.routing.rebalance.enable这个配置)来维持集群平衡的状态。例如,如果将一个分片从node1移动到node2,那随后可能会导致一个分片从node2移动到node1来平衡进出(even things out)。

      可以设置cluster.routing.allocation.enable关闭集群中的allocation。一旦关闭后,那么分配动作只会在使用reroute命令或者realancing时发生。

      通过在URL的请求参数中添加?dry_run或者在请求体中传递dry_run:true可以让reroute命令在"dry run"模式中运行。它会计算对当前集群状态应用这次reroute命令后会产生的结果,并返回这个结果,但不会真正的执行这些请求变更。

      如果在URI请求参数中添加?explain,那么在响应中会有一个详细的介绍来说明为什么可以或者不可以执行这个命令。

      集群会最多index.allocation.max_retries次来尝试(默认值为5)分配一个节点,否则就不再分配并且这个分片成为未分配的分片。这种情况可能由一些结构性的问题(structural problem)导致,比如分词器需要引用停用词文件,但不是所有的节点上都有这个文件。

      一旦问题解决了,就可以手动的通过rerouteAPI并且使用请求参数?retry_failed进行重试。这将对这些分片尝试一轮单独的重试。

    Query parameters
    Request body

    另外两个命令可以允许将一个主分片分配给节点。然而,这些命令应该非常小心地使用,因为主分片的分配通常完全由Elasticsearch自动处理。主分片不能自动分配的原因包括以下几点:

    下面两个命令是危险的,可能导致数据丢失。原始数据无法恢复并且集群管理员允许数据丢失的前提下可以使用。如果你遇到了一个可以修复的临时问题,见上文中的retry_failed。这里需要强调的是:如果执行了这些命令,然后一个持有受影响分片副本的节点加入集群,那么新加入节点上的副本将会被删除或覆盖。

    Examples

      以下是一个简短的reroute API调用的例子:

    Cluster state API

    (8.2)link

      返回集群状态(cluster state)的内部表示(internal representation)用于调试或者诊断目的。

    Request

    GET /_cluster/state/<metrics>/<target>

    Prerequisites
    Description

      cluster state是内部的数据结构,它记录了每个节点所需的各种信息,包括:

      被选为master的节点能保证集群中每个节点有相同的集群状态的副本。cluster state API能让你检索集群状态的内部表示用于调试或者诊断目的。你可能需要查看Elasticsearch的源码来明确响应中确切含义(precise meaning)。

      默认情况下,cluster state API将请求路由到被选为master的节点,因为它是集群状态的权威源头。你也可以在API请求添加请求参数?local=true获取本地节点上的集群状态。

      在较大的集群中,Elasticsearch可能需要花费大量的努力来计算对这个API的响应,而且响应可能包含非常大量的数据。如果你重复使用这个API,集群可能会变得不稳定。

    WARNING:响应是对内部数据结构的表示。它的格式不受与其他更稳定API相同的兼容性保证,可能会随版本而变化。不要使用外部监控工具查询此API。相反,请使用其他更稳定的cluster APIs来获取您需要的信息。

    Path parameters

      集群状态有时候会很大,Elasticsearch计算这个API响应时可能会花费大量资源。若要降低响应的大小,你可以只请求你感兴趣的部分集群状态:

    Query parameters
    Examples

      下面的例子中只返回metadata以及名为foobar的索引或者Data streams的routing_talbe

      下一个例子返回foobar所有可用的元数据:

      下面的例子只返回blocks

    Cluster stats API

    link

      

    Cluster update settings API

    (8.2)link

      用来配置dynamic cluster settings

    Request

    PUT /_cluster/settings

    Prerequisites
    Description

      你可以使用cluster update settings API对允许中的集群配置以及更新动态设置(dynamic settings)。你对未启动的或者关闭的节点上使用elasticsearch.yml配置本地的动态设置。

      使用cluster update settings API的更新方法是可持久的(对于persistent settings),即使集群重启也继续生效;也可以是临时的(transient settings),即有些配置在集群重启后重置。你也可以使用这个API通过赋予null值重置持久/临时的设置。

      如果你用多种方式配置了一样的设置,那么Elasticsearch会根据下面的优先顺序(order of precedence)来应用设置(apply settings)。

    1. Transient Setting

    2. Persistent Setting

    3. elasticsearch.yml setting

    4. Default setting value

      例如,你可以使用一个transient setting覆盖persistent setting或者elasticsearch.yml。然而,在elasticsearch.yml上的变更不会覆盖定义好的(defined)transient 或者 persistent setting。

    TIP:如果你使用Elasticsearch Service,使用user settings功能来配置所有的设置。这个方法能让Elasticsearch自动的拒绝(reject)掉任何会破坏你集群的设置。 如果你在自己的设备(hardware)上运行Elasticsearch,可以使用cluster update settings API来配置集群动态设置。对于集群或者节点的静态设置只使用elasticsearch.yml来配置。使用API不会要求重启并且保证所有节点都被配置成相同的值。

    WARNING: 我们不再推荐使用临时集群设置。请改用持久集群设置。如果集群变得不稳定,临时设置可能会意外清除,导致可能不希望的集群配置。请参阅 Transient settings migration guide

    Query parameters
    Examples

      以下是更新持久类型(persistent)设置的例子:

      以下是更新临时类型(transient)设置的例子:

    WARNING: 我们不再推荐使用临时集群设置。请改用持久集群设置。如果集群变得不稳定,临时设置可能会意外清除,导致可能不希望的集群配置。请参阅 Transient settings migration guide

      响应中返回更改后的设置,对于临时类型设置的更新也是如此:

      下面的例子重置了一个设置:

      响应中不包含被重置的设置:

      你也可以使用通配符重置设置。例如,重置所有indices.recovery设置:

    Nodes feature usage API

    (8.2)link

      返回功能的使用情况(usage of feature)的信息。

    Request

    GET /_nodes/usage GET /_nodes/<node_id>/usage GET /_nodes/usage/<metric> GET /_nodes/<node_id>/usage/<metric>

    Prerequisites
    Description

      这个API允许你查看每个节点上的功能使用情况的信息。所有节点上的Optional见Node specification

    Path parameters
    Query parameters
    Examples

      Rest action example:

      返回的响应:

      第10行,这个节点执行nodes usage请求的时间   第11行,开始记录节点使用信息的时间,这个值跟节点启动时间是一致的   第16行,这个节点执行了19次的查询操作

    Nodes hot threads API

    (8.2)link

      返回集群中选定节点上的hot thread。

    Request

    GET /_nodes/hot_threads GET /_nodes/<node_id>/hot_threads

    Prerequisites
    Description

      这个 API 提供了集群中每个选定节点的hot thread的详细分解(breakdown)。输出是纯文本格式,包含了每个节点顶级hot thread的详细分解。

    Path parameters
    Query parameters
    Examples

    Nodes info API

    (8.2)link

      返回集群节点信息。

    Request

    GET /_nodes GET /_nodes/<node_id> GET /_nodes/<metric> GET /_nodes/<node_id>/<metric>

    Prerequisites
    Description

      该接口能让你获取集群中一个或者多个(全部)的节点信息。所有节点Optional见这里

      默认情况下对于每一个节点,会返回其所有的属性和核心设置。

    Path Parameters

      如果你使用GET /_nodes/<node_id>/<metric>并且指定了所有的指标,那么你也可以使用指标名_all来获取所有的指标,或者你可以使用指标名_none来抑制(suppress)所有的指标并且只获取节点的身份信息。

    Response body

      os系列的配置用来获取操作系统的信息:

      process系列的配置用来获取当前运行中的进程信息:

    Query Parameters
    Examples

      设置_all用来返回所有的信息。

    Example for plugins metric

      如果指定了plugins,接口返回已安装的插件跟模块的详细信息:

      返回以下的内容:

    Example for ingest metric

      如果指定了ingest,接口返回每一个节点的processors信息。

      API返回以下的内容:

    Nodes reload secure settings API

    (8.2)link

      重新加载集群中节点上的keystore。

    Request

    POST /_nodes/reload_secure_settings POST /_nodes/<node_id>/reload_secure_settings

    Prerequisites
    Description

      Secure settings存储在on-disk keystore中。这些设置都是reloadable。也就是说你可以在磁盘上对齐更改并且不需要重启集群中的任何节点就可以重新加载。当你更新了keystore中reloadable的安全设置后,你就可以使用这个API在每一个节点上重新加载这些设置。

      如果Elasticsearch keystore使用密码保护而不仅仅是被混淆时(simply obfuscated) ,那当你重载安全设置时需要提供密码。为整个集群重载安全设置的前提是所有节点的keystores使用相同的密码保护,这个方法仅在inter-node communications are encrypted时可用。或者你可以通过本地访问每一个节点,使用节点对应的Elasticsearch keystore密码来重载安全设置。

    Path Parameters

    NOTE:Elasticsearch要求集群节点的安全设置一致性,但是这个一致性不是强制的。因此,重新加载指定节点不是标准做法。通常用于重载操作失败后使用这种方法比较合理

    Request body
    Examples

      下面的例子假设集群的每一个节点有相同的Elasticsearch keystore的密码:

      响应中包含了nodes对象,key就是node id。每一个value中有name以及一个可选的reload_exception字段。在重新加载的过程中抛出异常时就会序列化这个reload_exception字段:

    Nodes stats API

    link

      返回集群结点的统计信息。

    Request

    GET /_nodes/stats GET /_nodes/<node_id>/stats GET /_nodes/stats/<metric> GET /_nodes/<node_id>/stats/<metric> GET /_nodes/stats/<metric>/<index_metric> GET /_nodes/<node_id>/stats/<metric>/<index_metric>

    Prerequisites
    Description

      你可以使用这个API获取集群中节点的统计信息。

      节点的Optional见Node specification

      默认返回所有的统计信息。你可以通过使用指标<metric>限制返回的内容。

    Path Parameters
    Query parameters
    Response body
    Examples

      可以通过/_nodes/stats/_all或者/_nodes/stats?metric=_all请求所有的统计信息。

      你可以在nodeindices、或者shards层获取索引的统计信息。

      你可以获取节点上执行查询的search group的统计信息。

    Retrieve ingest statistics only

      若只要返回ingest相关的节点统计,将<metric>设置为ingest并且使用filter_path查询参数。

      你可以使用metric以及filter_path查询参数获取相同响应。

      若要进一步精确响应,修改filter_path的值。例如的下面的请求只返回ingest pipeline的统计信息。

    Pending cluster tasks API

    (8.2)link

      返回集群层(cluster-level)还未执行结束的变更。

    Request

    GET /_cluster/pending_tasks

    Prerequisites
    Description

      该接口返回所有的集群层未完成的变更(比如创建索引,更新mapping,分片分配或者分配失败)。

    NOTE:这个API返回一个集群状态待处理更新的列表。这些更新与Task Management API报告的任务不同,后者包括周期性任务和用户发起的任务,如节点统计、搜索查询或创建索引请求。然而,如果用户发起的任务(例如创建索引命令)导致了集群状态的更新,这个任务的活动可能会同时被Task Management API和Pending cluster tasks报告。

    Path Parameters
    Response body
    Example

      由于cluster level的变更都非常快,因此通常这个请求会返回一个空的list。然而,如果任务队列开始堆积,响应中就有类似下面的内容:

    Remote cluster info API

    (8.2)link

      返回远程集群(remote cluster)的配置信息

    Request

    GET /_remote/info

    Prerequisites
    Description

      该接口能让你获取远程集群的配置信息。返回的信息中用远端集群的别名作为key,包含连接和endpoint信息。

    Response body

    Task management API

    (8.2)link

    WARNING:task management API是一个新功能,但你应该将其认为是一个测试版功能。这个API可能会发生调整使得不能向后兼容。对于这个功能的更多信息见#51628

      返回集群中正在执行的任务信息。

    Request

    GET /_tasks/<task_id> GET /_tasks

    Prerequisites
    Description

      该接口返回集群中一个或多个节点上正在运行的任务信息。

    Path parameters
    Query parameters
    Response codes
    Examples

      第1行,获取集群中所有节点上的所有任务的信息   第2行,获取nodeId1nodeId2上的所有任务的信息。关于如何选择单个节点的更多信息见Node specification   第3行,获取节点nodeId1nodeId2上跟集群相关的所有任务的信息

      这个接口返回下面的结果:

    Retrieve information from a particular task

      同样可以获取特定任务的信息。下面的例子中获取了任务oTUltX4IQMOUUVeiohTt8A:124的信息:

      如果没有找到该任务,API返回一个404。

      获取指定任务的所有子任务:

      如果父级任务不存在,API返回一个404。

    Get more information about tasks

      你也可以使用detailed这个请求参数来获取更多关于运行中的任务信息。对用来区分任务很有用,不过需要一定的开销。例如,下面是使用detailed请求参数获取到的所有的查询:

      API返回下面的结果:

      description字段包含了某任务正在执行的特定请求相关的可读的内容,例如上面示例中搜索任务正在执行的搜索请求。有些其他类型的任务有不同的描述,比如_reindex中同时有search以及destination,或者_bulk中有请求的数量和目标索引。许多请求的描述都是空的,是因为这些请求更加详细的信息不能轻易获取或者对于明确这个请求不是很有帮助。

    IMPORTANT:带有detailed_task请求可能也会返回一个status。它是任务内部状态的一个报告。因此不同的任务有不同的格式。我们尝试对于某一个任务的状态在不同的版本间保持一致性,但这通常是不可能的,因为我们有时会更改实现方式。因此对于某些特定的请求,我们可能会移除status这个字段,那在minor release后,对这个字段进行解析可能会出错

    Wait for completion

      task API可以等待特定任务结束后再返回。下面的请求会阻塞10秒或者id为oTUltX4IQMOUUVeiohTt8A:12345的任务完成后返回。

      你也可以等待某些动作对应的任务的完成。下面的命令会等待所有reindex任务的完成:

    Task Cancellation

      如果某个运行时间很长的任务支持取消,那可以通过这个API取消。下面的例子取消了oTUltX4IQMOUUVeiohTt8A:12345这个任务:

      取消任务命令支持跟上文中说到的一些参数,因此可以在同一时间取消多个任务。例如,下面的命令会取消在节点nodeId1nodeId2上运行的所有reindex任务。

      有些任务被取消后,可能还会继续运行一段时间,因为它可能无法立即安全地停止当前活动。罗列任务的API(list tasks API)会继续列出这些已取消的任务,直到它们完成。list tasks API的响应中的cancelled标志表明取消命令已被处理,任务将尽快停止。

    Task Grouping

      可以通过task API的group_by参数对任务根据节点(默认)或者根据父级任务进行分组。下面的命令根据父级任务分组:

      可以指定group_by的参数为none来关闭分组:

    Identifying running tasks

      当在HTTP请求头中提供X-Opaque-Id头部时,它将在响应头以及任务信息的headers字段中返回。这允许跟踪特定调用,或将某些任务与启动它们的客户端关联起来。这个功能有助于更好地管理和识别正在运行的任务:

      返回下面的结果:

      第1行,id作为响应中header的一部分   第17行,由REST请求初始化的这个任务的id,   第30行,子任务中由REST请求初始化的这个任务的id

     

    Voting configuration exclusions API

    (8.2)link

      添加或者移除voting configuration exclusion list中的master-eligible 节点。

    Request

    POST /_cluster/voting_config_exclusions?node_names=<node_names>

    POST /_cluster/voting_config_exclusions?node_ids=<node_ids>

    DELETE /_cluster/voting_config_exclusions

    Prerequisites
    Description

      默认情况下,如果集群中有超过三个具备主节点资格的节点,并且一次性移除的这些节点少于一半,那么voting configuration会自动缩减。

      如果需要将voting configuration缩减到少于三个节点,或一次性移除一半或更多的master-eligible的节点,必须使用此 API 手动从voting configuration中移除已离开的节点。这包括在voting configuration的排除列表中为该节点添加条目,促使集群尝试重新配置voting configuration以移除该节点并防止其返回。

      如果接口调用失败,你可以安全的进行重试。一旦有成功的响应,那么就能保证节点从voting configuration总移除并且不会重新加入(reinstated)。

    NOTE:投票排除(voting exclusions)仅在短时间内从集群中移除至少一半的master-eligible时才需要。在移除master-ineligible或少于一半的具备主节点资格的节点时,不需要投票排除。

      更多信息见: Removing master-eligible nodes

    Query parameters
    Examples

      将名为nodeName1nodeName2的节点添加到voting configuration排除列表中:

      Remove all exclusions from the list:

    Create or update desired nodes API

    (8.2)link

    NOTE:这个功能不能直接使用,而是设计为只被Elasticsearch ServiceElastic Cloud EnterpriseElastic Cloud on Kubernetes使用。不支持直接使用。

      创建或者更新所需节点。

    Request
    Query parameters
    Description

      这个接口创建或者更新所需节点。外部编排器(external orchestrator)可以使用此API来让Elasticsearch了解集群拓扑,包括未来的变化,如添加或移除节点。利用这些信息,系统能够做出更好的决策。

    Examples

      In this example, a new version for the desired nodes with history Ywkh3INLQcuPT49f6kcppA is created. This API only accepts monotonically increasing versions.

      这个API返回下面的结果:

    Get desired nodes API

    (8.2)link

    NOTE:这个功能不能直接使用,而是设计为只被Elasticsearch ServiceElastic Cloud EnterpriseElastic Cloud on Kubernetes使用。不支持直接使用。

      获取所需节点

    Request
    Description

      这个接口获取最新的所需的节点。

    Examples

      这个例子获取最新的所需的节点。

      返回以下结果:

    Delete desired nodes API

    (8.2)link

    NOTE:这个功能不能直接使用,而是设计为只被Elasticsearch ServiceElastic Cloud EnterpriseElastic Cloud on Kubernetes使用。不支持直接使用。

      删除所需节点

    Request
    Description

      这个接口删除所需节点。

    Examples

      下面的例子删除当前所需节点

    Cross-cluster replication APIs

    (8.2)link

      你可以使用这些接口来执行CCR操作。

    Top-Level
    Follow
    Auto-follow

    Get cross-cluster replication stats API

    (8.2)link

      获取cross-cluster replication的统计信息。

    Request
    Prerequisites
    Description

      这个API获取CCR的统计信息。它返回跟CCR相关的所有统计信息。该接口返回auto-following信息、以及跟get follower stats API一样的分片层(shard-level)的信息。

    Response body
    Example

      这个例子获取CCR的统计信息:

      该接口返回以下结果:

    Create follower API

    (8.2)link

      创建一个follower index。

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须在follower index上有writemonitormanage_follow_index的index privilege。在leader index上必须要有readmonitor的index privilege。在包含follower index的集群上要有manage_ccr的cluster privilege。更多信息见Security privileges

    Description

      该接口用来创建一个新的follower index配置为跟随(follow)一个被引用的leader index。。该接口返回后,生成了follower index,然后CCR开始从leader index执行复制操作到follower index中

    Path parameters
    Query parameters
    Request body
    Default values

      下面的输出来自follower info API,描述了这个接口中请求参数的所有默认值:

    Example

      下面的例子创建了一个名为follower_index的follower index:

      该接口返回下面的结果:

    Pause follower API

    (8.2)link

      暂停一个follower index。

    Request
    Prerequisites
    Description

      该接口用来暂停一个follower index。当接口返回后,follower index不会从leader index中获取任何额外的操作。你可以通过resume follwer API恢复。暂停然后恢复一个follower index可以用来修改following task的配置。

    Path parameters
    Example

      下面的例子暂停了一个名为follower_index的follower index。

      该接口返回以下结果:

    Get auto-follow pattern API

    (8.2)link

      获取auto-follow patterns。

    Request
    Prerequisites
    Description

      该接口获取已配置的auto-follow patterns。返回指定的auto-follow patterns集合。

    Path parameters
    Example

      这个例子获取名为my_auto_follow_pattern的auto-follow pattern 集合。

      这个接口返回以下结果:

    Resume follower API

    (8.2)link

      恢复一个follower index。

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须在follower index上有writemonitor的index privilege。在leader index上必须要有readmonitor的index privilege。在包含follower index的集群上要有manage_ccr的cluster privilege。更多信息见Security privileges

    Description

      显示的通过pause follower API暂停或者在跟随(follow)过程中某些操作由于无法通过重试来执行导致失败而暂停的follower index,可以使用该接口恢复。在接口返回后,follower index将恢复从leader index中获取操作。

    Path parameters
    Request body
    Default values

      下面的输出来自follower info API,描述了这个接口中请求参数的所有默认值:

    Example

      下面的例子恢复了一个名为follwer_index的follower index:

      该接口返回以下结果:

    Unfollow API

    (8.2)link

      将一个follower index转化为一个常规索引(regular index)。

    Request
    Prerequisites
    Description

      该接口会停止相关follower index的following task并且从CCR中移除相关的index metadata以及settings。将follower index视为一个常规索引。follower index必须先暂停并且关闭才能调用该接口

    NOTE:当前CCR不支持将一个现有的常规索引转化为一个follower index。因此将一个follower index转化为一个常规索引是一个不可逆的操作

    Path parameters
    Example

      这个例子将名为follower_index的follower Index转化为一个常规索引:

      该接口返回以下结果:

    Forget follower API

    (8.2)link

      从leader中移除follower retention leases(保留租约)。

    Request
    Prerequisites
    Description

      一个following index会在其leader index上创建保留租约(retention leases)。这些保留租约用于提高leader index的分片保留following index分片需要执行复制的操作历史的可能性。当一个following index通过unfollow API转换为一个常规索引时(无论是通过显式执行此API还是通过索引生命周期管理隐式执行),这些保留租约会被移除。然而,移除这些保留租约有可能失败(例如,如果包含leader index的远程集群不可用)。虽然这些保留租约最终会自动过期,但它们延长存在的时间可能导致leader index保留比必要更多的历史记录,并阻止索引生命周期管理在leader index上执行某些操作。此API的存在是为了在unfollow API无法做到这一点时,手动移除这些保留租约。

    NOTE:该接口不会停止following index的复制。如果你对一个仍然处于跟随(following)的follower index使用该接口,following index将会重新添加保留租约。这个接口只处理在unfollow API调用后无能移除保留租约的情况。

    Path parameters
    Request body
    Example

      下面的例子从leader_index中移除follower_index的保留租约。

      该接口返回以下结果:

    Get follower stats API

    (8.2)link

      获取follower的统计信息。

    Request
    Prerequisites
    Description

      这个接口获取follower的统计信息。这个接口将返回指定索引中与每一个分片相关的follower task

    Path parameters
    Response body
    Example

      下面的例子来获取follower的统计信息:

      该接口返回以下结果:

    Get follower info API

    (8.2)link

      获取所有follower index的信息。

    Request
    Prerequisites
    Description

      该接口列出了每一个follower index的参数以及状态。例如,响应中会包括follower的索引名称,leader 索引名称。复制选项(replica options)以及follower index处于活跃还是暂停中。

    Path parameters
    Response body
    Example

      下面的例子获取follower信息:

      如果follower index的statusactive,接口返回下面的结果:

      如果follower index的statuspaused,接口返回下面的结果:

    Delete auto-follow pattern API

    (8.2)link

      删除auto-follow patterns。

    Request
    Prerequisites
    Description

      删除一个已配置的auto-follow patterns集合。

    Path parameters
    Example

      这个例子删除了一个名为my_auto_follow_pattern的auto-follow pattern集合。

      该接口返回以下结果:

    Create auto-follow pattern API

    (8.2)link

      创建一个auto-folllow pattern。

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须在leader index patterns上有readmonitor的index privilege。在包含follower index的集群上要有manage_ccr的cluster privilege。更多信息见Security privileges

    Description

      该接口对请求体中指定的集群创建了auto-follow pattern集合。在远端集群中新创建的索引会自动在本地配置follower index。另外,这个接口可以用来更新现有的auto-follow patterns。注意的是即使在更新auto-follow pattern后它们不再匹配新的pattern,之前自动配置的follower index将保持不变。

    Path parameters
    Request body
    Default values

      下面的输出来自follower info API,描述了这个接口中请求参数的所有默认值:

    Example

      这个例子创建了一个名为my_auto_folowe_pattern的auto-follow pattern:

      这个接口返回以下结果:

    Pause auto-follow pattern API

    (8.2)link

      暂停一个auto-follow pattern。

    Request
    Prerequisites
    Description

      该接口暂停一个auto-follow pattern。接口返回后,这个auto-follow pattern则为inactive并且忽略所有在远端集群上创建的并且匹配的新索引。暂停auto-follow pattern会将将GET auto-follow patterns API中的active的值设置为false

      你可以使用resume auto-follow pattern API恢复。一旦恢复,auto-follow pattern再次为active并且匹配到远端集群上创建的新索引后在本地创建follower index。创建的索引即使在pattern被暂定后也可以被跟随(follow),除非同时被关闭或者删除。

    Path parameters
    Example

      下面的例子暂停名为my_auto_follw的auto-follow pattern:

      该接口返回以下结果:

    Resume auto-follow pattern API

    (8.2)link

      恢复一个auto-follow pattern。

    Request
    Prerequisites
    Description

      该接口返回一个通过pause auto-follow pattern API暂停的auto-follow pattern。接口返回后,将会恢复并继续为远端集群中新创建的并且匹配的索引在本地配置follower index。创建的索引即使在pattern被暂定后也可以被跟随(follow),除非同时被关闭或者删除。

    Path parameters
    Example

      这个例子恢复了一个名为my_auto_follow_pattern的被暂停的auto-follow pattern:

      该接口返回以下结果:

    Data stream APIs

    (8.2)link

      下面的API用来管理data stream

      更多概念跟教程见Data streams

    Create data stream API

    (8.2)link

      创建一个新的data stream

    Request
    Prerequisites
    Path parameters

    Delete data stream API

    (8.2)link

      删除一个或多个data streams以及它们的backing indices。见Delete a data stream

    Request
    Prerequisites
    Path parameters
    Query parameters

      默认是open

    Get data stream API

    (8.2)link

      获取一个或多个data stream的信息。见Get information about a data stream

    Request
    Prerequisites
    Path parameters
    Query parameters

      默认是open

    Response body
    Example

      这个请求返回以下响应:

    Migrate to data stream API

    (8.2)link

      index alias转化为一个data stream

    Request
    Prerequisites
    Path parameters

      成功后,该请求会移除别名并且创建一个名称相同的data stream。别名的索引变成这个流的backing indices。别名的writer index变成流的writer index。

    Data stream stats API

    (8.2)link

      获取data streams的统计信息。

    Prerequisites
    Request
    Path parameters
    Query parameters

      默认是open

    Response body

    NOTE:这个时间戳可能不是最大的。如果满足以下一个或多个条件,那么可能data stream中存在比@timestamp数值更大的值:

    Example

      API返回下面的响应:

    Promote data stream API

    (8.1)link

      这个接口的目的是将通过CCR复制的data stream转换成一个常规的data stream。

      通过CCR的Auto Following,远端的data stream可以被复制到本地集群中。这些data stream不能再本地集群中rollover 。只有当上游的data stream执行了rollover后,这些被复制的data stream才能执行rollover。当远端集群不可用时,本地集群的data stream可以提升为一个常规的data stream,运行在本地集群中执行rollover。

    Request
    Prerequisites
    Path parameters

    Modify data streams API

    (8.2)link

      在一个原子操作内执行一个或者多个data stream的修改动作。

    Request
    Request body

     

    Document APIs

    link

      

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Example

    Reading and Writing documents

    (8.2)link

    Introduction

      Elasticsearch中的每一个索引会divided into shards并且每一个分片都有多个拷贝。这些拷贝就是所谓的replication group并且当文档添加或者删除后,每一个replica都要保持同步。如果无法做到同步,那么可能就会导致从不同的拷贝中读取的结果各不相同。保持副本分片间的同步以及读取副本分片的处理过程称为data replication model

      Elasticsearch的data replication model基于主备模式(primary-backup model),微软的一篇论文PacificA paper很好的描述了这种模式。这个模型就是从replication group中拿出一个拷贝作为主分片(primary shard),其他的拷贝作为副本分片。主分片用于服务所有索引操作的入口点(entry point)。主分片负责非法检查并保证索引操作的正确性。一旦主分片接受了某个索引操作,主分片负责对其他的副本分片复制这次索引操作。

      本章的内容从high level的视角来了解Elasticsearch的replication model并讨论读操作与写操作之间不同的交互(interaction)带来的影响(implication)。

    Basic write model

      Elasticsearch中的每一个索引操作首先基于文档编号(document ID)通过routing解析(resolve)replication group。一旦检测到replication group,这个操作会在内部转发到组中当前的主分片中。这个索引阶段称为coordinating stage

      索引阶段的下一个阶段就是primary stage,在主分片上执行。主分片负责对索引操作进行验证并转发到其他副本分片。由于副本分片可能处于离线状态,主分片不要求一定要转发到所有的副本分片。Elasticsearch维护了副本分片的列表,这些副本会收到主分片的转发。这个列表称为in-sync copies 并且master node负责维护。正如in-sync这个名称一样,列表中的都是"good" 副本分片并且它们已经处理好了所有的索引和删除操作并且响应给了用户。主分片负责维护这个列表因此会复制操作给列表中的每一个副本分片。

      主分片遵循下面基本的步骤:

      in-sync中的副本分片在本地执行索引操作。这个索引阶段称为replica stage

      这些索引阶段(coordination,primary,replica)是有序执行的。为了能实现内部重试(to enable internal retries),每一个阶段的时间(lifetime)包括(encompass)了 它的下一个阶段的时间。例如,coordination stage直到每一个primary stage完成才算是完成,primary stage可能会分散(spread out)到不同的主分片,等待它们完成。每一个primary stage直到每一个replica stage完成才算是完成,replica stage需要等到每一个副本分配完成本地的文档索引操作并且能成功的响应。

    Failure handling

      在索引期间会有很多事情会导致发生错误。磁盘损坏(corruption)节点失去连接或者一些错误的配置导致某个操作能在主分片上成功执行但是在副本分片上发生错误。尽管这些问题不常见,但是主分片必须负责处理这些问题。

      如果主分片自身发生了错误,主分片所在的节点会像master node发送消息。索引操作会等待(默认一分钟),直到master晋升(promote)一个副本分片成为主分片。这个索引操作会被转发到新的主分片进行处理。注意的是master node会监控节点的健康度,可能会主动(proactive)降级(demote)一个主分片。发生这种情况一般是拥有主分片的节点因为网络问题从集群中分离(isolate)出来了。

      一旦在主分片上成功的完成操作,主分片必须要处理在执行复制操作给副本分片后,replica stage出现错误的问题。有可能在副本分片上真的出现了错误或者因为网络问题导致复制操作无法到达副本分片,或者副本分片的响应无法到达主分片。这样的问题最终都有相同的结局:a replica which is part of the in-sync replica set misses an operation that is about to be acknowledged。In order to avoid violating the invariant,主分片往master node发送请求要求这个副本分配从in-sync中移除。Only once removal of the shard has been acknowledged by the master does the primary acknowledge the operation. Note that the master will also instruct another node to start building a new shard copy in order to restore the system to a healthy state。

      在转发操作到副本分片时,主分片也可以利用副本分配来检查自己是否仍然是active primary。如果主分片由于network partition(long GC)已经被隔离了。它在认识到自己被降级前仍然继续处理索引操作。副本分配会reject来自失效的(stale)的主分片的操作。当主分片接收到副本分配的reject响应后,由于它不再是主分片,它会联系(reach out )master node然后了解到自己的主分片地位被替换了。然后这个操作会路由到新的主分片。

    如果没有replica的话会发生什么 由于索引配置或者简单来说所有的副本分配都失效的场景是存在的。在这种场景下,主分片处理操作并不需要任何外部的验证,看起来是有问题的。另一方面,主分片不能自己让其他shard而是需要向master node代表它这样做。这意味着master node知道这个主分片唯一"good"的分片。我们因此保证了master node 不会晋升其他的shard成为新的主分片,因此在这个主分片上的任意的索引操作都不会丢失。当然了,由于我们只在一个数据副本上允许,物理的硬件问题会导致数据丢失。见Active shards了解一些mitigation选项。

    Basic read model

      通过查找ID在Elasticsearch中读取是非常轻量的(weightlight),而带有复杂聚合操作的heavy 查询请求则会要求non-trivial的CPU power。主备模式(primary-backup)模式的优点之一是它让所有的副本分片的数据保持一致(with the exception of in-flight operations)。因此单个in-sync的分片足够用于服务读取请求。

      当一个节点接收到一个读请求,这个节点负责转发这个请求到拥有相关分片的节点上,整合(collate)结果并响应给客户端。我们称那个节点为coordinating node。基本的流程如下所示:

    1. 解析(resolve)这个请求对应的分片。注意的是由于大部分的请求都会被发送一个或者多个索引,所以通常来说都需要从多个分片中读取,每一个分片返回的内容都是一个数据子集

    2. 从replication group中选择一个相关的分片的active copy。可以是主分片或者是副本分片。默认情况下,Elasticsearch使用adaptive replica selection来选择分片

    3. 发送分片级别(shard level)的读请求到选择的分片上

    4. 组合结果和响应。注意的是在通过ID查询的场景中,只有一个分片是相关的,因此这个步骤可以跳过

    Shard failures

      当一个分片错误的响应读请求后,coordinating node会将请求发送到同属replication group中的其他分片。重复的失败会导致没有可用的分片。

      为了保证快速的响应,下面的APIs在出现一个或者多个失败后返回部分结果:

      包含部分结果的响应仍旧提供一个200 OK的HTTP 状态码。Shard failure会在响应头的timed_out_shards 中指出。

    A few simple implications

      这些基本流程中的每一个都决定了Elasticsearch作为一个读写系统的行为。进一步的说,由于读写请求可以并发执行,它们相互影响。

    Efficient reads

      正常情况下一次读操作只会读取相关的replication group中的分片一次。只有在出错的情况下才会对多个相同的分片执行相同的查询。

    Read unacknowledged

      由于主分片先在自己本地进行索引,然后再复制这个请求到其他分片。有可能出现一个并发的读操作会看到这个未确认(等待其他所有副本分片更改完成的确认)的更改。

    Two copies by default

      主备模型可以在在仅仅维护两个副本的情况下实现容错,而相较于quorum-based的系统中用于容错的最小的副本数量需要3个。

    Failures

      发生错误后,下面的情况仍然可能发生。

    A single shard can slow down indexing

      每一个操作中,由于主分片会等待in-sync中所有的副本分片完成。单个slow分片会导致整个replication group变慢。这个是上文Efficient reads带来的代价。当然一个slow分片也会降低路由到这个分片的查询。

    Dirty reads

      被隔离的(isolate)的主分片仍然会暴露未被确认的数据。这是由于这个分片不会意识到自己已经被隔离了直到它发送请求到副本分片或者通过master node得知。在这个时间点,索引操作已经索引到主分片本地并且可以被并发的读操作读取变更。Elasticsearch通过每一秒对master node进行ping来缓解(mitigation)这个风险,并且在不知道主节点时reject索引操作。

    The Tip of the Iceberg

      当前这篇文档提供了一个high level的角度介绍了Elasticsearch如何处理数据,当然在底层有着更多的内容。例如primary terms,cluster state publishing以及master election,所有这一切都是为了让这个系统有正确的行为。这篇文档同样没有覆盖已知的并且重要的bug( closed以及open)。我们认识到GitHub is hard to keep up with,所以我们在页面维护了一个专门的resiliency page,强烈建议阅读这些内容。

    Index API

    link

    document IDs automatically
    Routing(Index API)

      

    Active shards

    Get API

    link

    Delete API

    link

    Update API

    link

    Update By Query API

    (8.2)link

      更新满足满足指定Query的文档。如果没有指定,执行data stream或索引中每一篇文档的更新,但是不修改源数据,用来应用mapping的更改是非常有用的。

    Request
    Prerequisites

      如果开启了Elasticsearch security feature,你必须要有目标data stream,index或者alias的这些 index privilege

    Description

      你在请求URI指定查询规则或者在请求体中使用跟Search API相同的语法。

      当你提交了该接口的请求,Elasticsearch在开始处理请求时会获取数据流或索引的快照,并使用内部版本控制(internal versioning)来更新匹配的文档。当版本匹配时,文档会被更新并且提高版本号。如果在获取快照和处理更新操作之间,文档发生了变化,这会导致版本冲突,从而使操作失败。你可以通过将conflicts设置为proceed,使得接口统计发生版本冲突的数量而不是停止并返回。注意的是如果选择这种方式,那么这次接口操作会尝试从源中更新更多的文档直到更新了max_doc数量的文档,或者覆盖了查询范围内的所有文档。

    NOTE:如果文档的版本号是0,那么就不能通过这个接口更新,因为内部版本控制不支持该值,它不是一个有效的版本号

      在处理通过查询更新(update by query)请求时,Elasticsearch会顺序执行多个搜索请求来找到所有匹配的文档。每批匹配的文档会执行一次批量更新请求。任何查询或更新失败都会导致通过查询更新请求失败,并且失败信息会显示在响应中。已经成功完成的更新请求会保持不变,它们不会被回滚

    Refreshing shards

      指定refresh参数使得在请求完成后对所有的分片执行refresh。不同于Update API中的refresh参数,它只会让收到请求的分片执行refresh。不同于Update API,该接口不支持wait_for

    Running update by query asynchronously

      如果请求中包含wait_for_completion=false。Elasticsearch会执行一些预检查(preflight check),启动请求,并返回一个task,你可以用它来取消任务或获取任务状态。Elasticsearch会在.tasks/task/${taskId}处以文档形式记录这个任务。完成任务后,你应该删除任务文档,以便Elasticsearch回收空间。

    Waiting for active shards

      wait_for_active_shards控制在执行这个请求前应该有多少数量的分片是活跃的(active)。见Active shards查看详情。timeout控制写请求等待那些不见用的分片变得可用的时间。这两个设置在Bulk API](#Bulk API)中的工作方式完全相同。Update by Query在实现内部使用了滚动搜索(scroll search),因此你也可以指定scroll参数来控制它保持搜索上下文活跃的时间长短,例如?scroll=10m。默认值是5分钟。

    Throttling update requests

      若要控制Update By Query以多快的速率发出一批批更新操作,你可以将requests_per_second设置为任何正小数。这会给每批操作添加/填充等待时间,以此来控制速率。将requests_per_second设置为-1可以禁用节流。

      节流通过在批次之间填充等待时间来实现,使得内部scroll请求在设置超时时间时要考虑到这个等待时间。即批次大小除以requests_per_second与写入花费的时间差值。默认批次大小为1000,因此如果requests_per_second设置为500:

      因为批量请求("Update By Query"操作中找到的符合条件的文档集合,这些文档将作为一个批次通过Elasticsearch的_bulk API进行更新)作为单个的_bulk请求发出,较大的批量大小会导致Elasticsearch创建许多请求并在开始下一组之前等待。这种方式是“bursty突发”的而不是“smooth平滑”的。

    Slicing

      该接口支持sliced scroll 以并行化更新过程,这可以提高效率并提供一种将请求分解成更小部分的便捷方式。

      slices设置为auto会为大多数data stream和index选择一个合理的数量。如果你手动切片或以其他方式调整自动切片,请记住:

      查询或更新性能哪个占据运行时间的主导因素取决于被reindex的文档和集群资源。

    Path parameters
    Query parameters
    Request body
    Response body
    Example

      _update_by_query最简单的使用方式就是对data stream或index中每一个文档执行更新并且不修改原文档。比如说pick up a new property或者在线修改mapping。

      若要更新指定文档,可以在请求体中指定一个query:

      第3行,跟Search API一样的方式,在query字段中指定内容。你也可以像Search API一样使用q参数。

      在多个data stream或index中更新文档:

      指定路由值要求在指定分片上执行查询:

      默认Update By Query中每一个scroll查询最多获取1000篇文档。你可以通过scroll_size参数修改这个值:

      使用唯一属性(即user.id)来更新一篇文档

    Update the document source

      可以使用脚本更新文档中的内容。例如下面的请求中对索引my-index-000001中字段名为user.id字段值为kimchy的文档中的count字段实现加一:

      注意到的是,这个例子中没有指定conflicts=proceed。因此当遇到版本冲突时会终止处理值得你可能处理这个问题。

      Update API一样,你可以设置ctx.op的值来修改执行的操作:

      该接口支持updatenoopdelete。将ctx.op设置成其他值都会报错。设置ctx的其他字段也会报错。这个接口只能让你更改匹配到的文档的内容,你不能移动它们。

    Update documents using an ingest pipeline

      可以通过指定一个pipeline来使用ingest pipelines的功能:

    Get the status of update by query operations

      可以通过Task API获取所有运行中的Update By Query请求的状态:

      相应如下:

      第18行,该对象包含实际的状态。它类似于响应的JSON,但重要的增加了total字段。total是reindex预期执行的操作总数。你可以通过加上updated、created和deleted字段来估计进度。当这些字段的和等于total字段时,请求将完成

      根据任务id你可以直接查看这个任务。下面的例子获取了任务r1A2WoRbTwKZ516z6NEs5A:36619:的信息:

      这个API的优势在于它与wait_for_completion=false集成,以透明方式返回已完成任务的状态。如果任务已完成且在其上设置了wait_for_completion=false,则它会返回带有结果或错误字段的响应。这个特性的成本是在.tasks/task/${taskId}创建的文档。删除该文档的责任在于用户。

    Cancel an update by query operation

      通过使用Task Cancel API取消Update By Query:

      可以通过tasks API获取任务ID。

      取消操作很快就发生但可能需要一点时间。task status API会继续列出Update By Query直到它意识到自己被取消了并终止自己。

    Change throttling for a request

      可以通过_rethrottle接口对运行中的Update By Query修改requests_per_second的值:

      可以通过tasks API获取任务ID。

      在设置_update_by_query API时,requests_per_second可以设为-1禁用节流,或设为任何小数如1.712来限制到该级别的速率。加速查询的重新节流(Rethrottling)立即生效,而减速查询的重新节流将在完成当前批次后生效,以防止滚动超时。

    Slice manually

      在请求中通过提供slice id和slice的总数来手动对Update By Query进行切分:

      你可以通过下面的方式进行验证:

      生成类似下面的合理的(sensible)total

    Use automatic slicing

      你可以使用sliced scroll根据id切分来自动实现并行。指定slices的数量来使用它:

      佴可以通过下面方式验证:

      生成类似下面的合理的(sensible)total

      slices设置为auto时,Elasticsearch会自动选择切片数量,通常是每个分片一个切片,直到达到上限。如果存在多个data stream或index,它会根据分片数最少的index或backing index来确定切片数。

      _update_by_query中添加切片,实际上是自动化了手动过程,产生了一些特性(quirk):

    Pick up a new property

      比如说你没有使用动态mapping创建了一个索引,写入了数据并且然后添加了mapping来从数据获取更多的字段:

      第4行,意味着新的字段不会被索引,只保存在_source   第21行,添加新的flag字段到mapping中。但是你需要reindex才能查询到flag的信息

      查询这个flag字段不会有任何数据:

      但是你可以发起_update_by_query来添加新的mapping:

      当你向多字段(multifield)添加一个字段时,可以做同样的事情。

    Bulk API

    link

    Reindex API

    link

      从一个源拷贝文档到目的地。

       数据源可以是现有的索引、别名、或者data stream。目的地跟源必须是不同的。比如你不能将data stream reindex到自身。

    IMPORTANT:Reindex要求源中的文档开启_source 目的地应该在调用_reindex之前进行配置。Reindex不会从源拷贝settings以及相关的模板。 Mapping、分片数量、副本分片等等必须提前配置好

    Request
    Prerequisites
    Description

      从源索引中提取document Source,然后索引到目标索引中。你可以拷贝所有的文档到目标索引,或者Reindex文档的子集。

      就像_update_by_query_reindex会获取源的快照,但不同的是目的地不能是自身(update_by_query是对自身更新),因此不会出现version conflict的问题(文档的版本号,响应中_version字段)。

    Path parameters
    Query parameters
    Response body
    Example
    Reindex from remote

    Term vectors API

    link

    ?refresh(api)

    link

    Enrich APIs

    (8.2)link

      下面enrich API用来管理 enrich policies

    Create enrich policy API

    (8.2)link

      创建一个enrich policy。

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须要有:

    Description

      使用该接口来创建一个enrich policy

    WARNNING:enrich policy一旦创建完毕,你就不能更新或者修改,不过你可以:

    • 创建并且execute一个新的enrich policy

    • 在使用中的enrich processor中用新的enrich policy替换之前的

    • 使用delete enrich policy删除之前的enrich policy

    Path parameters
    Request body

    Delete enrich policy API

    (8.2)link

      删除一个现有的enrich policy和它的enrich index

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须要有:

    Description

      使用该接口删除一个现有的enrich policy和enrich index。

    IMPORTANT:删除之前,你必须从ingest Pipeline中移除该策略。你不能移除一个正在被使用的enrich policy

    Path parameters

    Get enrich policy API

    (8.2)link

      返回enrich policy的信息。

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须要有:

    Path parameters
    Example
    Get a single policy

      该接口返回以下响应:

    Get multiple policies

      该接口返回以下响应:

    Get all policies

      该接口返回以下响应:

    Execute enrich policy API

    (8.2)link

      执行一个现有的enrich policy

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须要有:

    Description

      使用该接口为现有的enrich policy创建enrich index。

      enrich index中包含了策略中的source index。enrich index 的名称总是以.enrich-*开头,只读索引,并且force merged

    WARNING:enrich index应该只被enrich processor使用,避免使用enrich index用于其他目的。

      创建之后,你不能向enrich Index中更新或者添加文档。而是更新你的source index然后再次execute enrich policy。这样会从更新后的source Index中创建新的enrich index。之前的enrich index会使用一个maintenance job稍后删除。默认是每15分钟。

      由于这个接口执行好多操作,可能需要等一段时间才会返回。

    Path parameters
    Query parameters

    Enrich stats API

    (8.2)link

      返回当前执行中的enrich policy的信息以及enrich coordinator的信息。

    Request
    Response body
    Example

      接口返回以下响应:

    EQL APIs

    link

    EQL search API

    link

    Features APIs

    link

    Get Features API

    link

    Reset features API

    link

    Index APIs

    link

      Index APIs用来管理索引的settings、aliases(别名)、mappings和索引模板(Index Template)。

    Index management
    Mapping management
    Alias management
    Index settings
    Index templates

      索引模板自动将settings、mappings、aliases应用到新的索引上。它们通常用于时序数据中rolling indices时使用,使得新的索引跟之前的有相同的配置。data stream中关联的索引模板会配置backing indices。更信息见Index Template

    Dangling indices API

    Alias exists API

    (8.2)link

      检查某个alias是否存在。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response codes

    Aliases API

    (8.2)link

      在一个原子操作内执行一个或多个alias动作

    Request
    Prerequisites
    Query parameters
    Response body

    Analyze API

    (8.2)link

      在文本上执行analysis并返回生成的token。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    No index specified

      你可以对文本字符串应用一个内置的分词而不用指定索引。

    Array of text strings

      如果text参数提供了字符串数组,则按照多值字段进下处理

    Custom analyzer

      你可以使用这个接口测试自定义的包含tokenizers、token filters以及char filter的分词器。Token filter使用filter参数:

      也可以通过下面的方式指定自定义的tokenizers, token filters 以及 character filters:

    Specific index

      你可以对指定的索引调用这个接口:

      上面的例子会对this is a test这个文本进行分词,使用名为analyze_sample的索引中默认的分词器。可以在analyzer参数中指定一个不同的分词器:

    Derive analyzer from a field mapping

      也可以通过某个字段的mappings获取分词器,例如:

      将会使用obj1.fields在mappings中定义的分词器进下分词(如果没有指定分词器,则使用索引默认分词器)

    Normalizer(analyzer API)

      可以为名为analyze_sample的索引中keyword类型的字段,使用normalizer参数。

      或者自定义构建一个没有token filter和char filter的normalizer。

    Explain analyze

      若要获取更多的信息,可以将explain设置为true(默认为false),它会为每一个token输出其属性。你可以通过attributes参数过滤token属性。

    NOTE:额外的详细信息在Lucene中标记为实验性质的,可能在未来发生变更

      第7行,设置了keyword使得只输出keyword属性。

      上面的请求返回以下结果:

      第36行,因为在请求中设置了attributes参数,因此只输出了keyword属性

    Setting a token limit

    &emsp生成过多的token可能导致节点出现OOM。下面的设置可以限制生成的token数量:

    Analyze index disk usage API

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      分析index或data stream中每一个字段的磁盘使用情况。这个API可能不支持在旧版本中创建的索引。对于较小的索引,由于 API 可能无法分析索引的某些部分,结果可能不准确。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example

      这个API返回:

      第8行,索引中被仅分析的分片的存储大小   第11行,索引中被分析的分片的存储总量。这个总量通常比第8行中指定的索引大小小,因为一些小型元数据文件被忽略,而 API 可能未扫描数据文件的某些部分。   第36行,_id字段的存储大小   第54行,_source字段的存储大小。由于存储字段使用了压缩格式存储在一起,因此只是尽量估算了存储字段的大小。_id字段的存储大小,可能不太准确。_id 字段的存储大小可能被低估,而 _source字段可能被高估

    Clear cache API

    link

      

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Example

    Clone index API

    (8.2)link

      克隆一个现有的索引。

    Request
    Prerequisites

      比如说,下面的请求禁止了my_source_index索引的写操作,因此它可以被克隆。像删除索引这种元数据更改仍然是允许的。

      Data stream当前的write index不能被克隆。若要克隆当前的write index,data stream必须先执行roolled over,使得创建一个新的write index,那么之前的write index就可以被克隆了。

    Description

      使用该接口将现有的索引克隆到一个新的索引中,每一个源主分片会被克隆到新索引的新的主分片中。

    IMPORTANT:Elasticsearch不会将索引模板应用到生成的索引中。该接口同样不会从源索引中拷贝索引元数据。索引元数据包括aliases,ILM阶段定义以及CCR follower信息。例如,如果你克隆一个CCR follower index,生成的克隆索引不会成为一个follower index。 这个接口会从源索引中拷贝索引设置到生成的索引中,除了index.number_of_replicasindex.auto_expand_replicas。若要在生成的索引中设置副本分片的数量,需要在请求该接口时指定

    How cloning works

      克隆工作方式如下:

    Clone an index

      若要克隆my_srouce_index到一个名为my_target_index的新索引中,可以发起下面的请求:

      目标索引添加到集群状态后,该接口就会马上返回,它不需要等待克隆操作开始。

    IMPORTANT:只有满足以下的要求,索引才可以被克隆:

    • 目标索引必须不存在

    • 源索引必须跟目标索引有相同的主分片

    • 目标索引中的主分片数量必须是源索引的因子。源索引必须比目标索引有更多的主分片

    • 处理克隆操作的节点必须要有足够多空闲磁盘来容纳现有索引的第二个副本

      该接口类似create index API,因此目标索引接受settingsaliases

      第4行,目标索引的分片数量。必须跟源索引中的分片数量一致。

    NOTE:Mapping不需要在_clone请求中指定,源索引中的mapping将用于目标索引。

    Monitor the cloning process

      克隆处理进度可以通过_cat recovery API查看,或者可以调用cluster health API以及参数wait_for_status设置为yellow来等待所有的主分片分配结束。

      只要目标索引被添加到集群状态中,在分片分配结束之前,该接口就会马上返回。在这个时间点,所有的分片处于unassigned状态。如果因为任何原因导致目标索引不能分配到收缩节点上,索引的主分片仍然会处于unassigned状态直到可以被分配到那个节点上。

      一旦主分片分配结束,就切换成initializing状态,然后克隆处理就开始了。当克隆操作完成,就切换成active状态。在这个时间点,Elasticsearch会尽量分配副本分片并且可能决策出将主分片重新分配到其他节点。

    Wait for active shards

      由于克隆操作创建一个新的索引来克隆分片,因此在索引创建时的wait for active shards设置也适用于克隆索引操作。

    Path parameters
    Query parameters
    Response body

    Close index API

    (8.2)link

      关闭一个索引。

    Request
    Prerequisites
    Description

      你可以使用这个接口关闭打开中的索引。

      关闭后的索引不能执行打开中的索引允许的读/写操作。不能向关闭后的索引写入/查询文档。这样不需要为写入/查询文档维护内部的数据结构,使得对集群有较小的开销。

      当打开或者关闭一个索引时,对于重启索引分片,master要负责反应索引新的状态。分片才能进行正常的恢复操作。集群会对打开/关闭的索引自动进行replicate,保证总是有足够的shard copies。

      你可以打开/关闭多个索引。如果请求中显示引用了缺失的索引则会抛出错误。当然可以通过ignore_unavailable=true来关闭这个行为。

      你可以显示指定要打开/关闭的索引名称。若要使用_all*或者其他通配符表达式打开/关闭索引,需要将action.destructive_requires_name修改为false。可以通过cluster update settings API更新这个参数。

      关闭的索引会消耗大量的磁盘空间,这可能在受控环境中引发问题。可以通过cluster settings API,将 cluster.indices.close.enable 设置为 false 来禁用关闭索引的功能。默认值为 true

    Path parameters
    Query parameters
    Example

      下面的例子中展示了如果关闭一个索引:

      该接口返回以下结果:

    Create index API

    (8.2)link

      创建一个新的索引。

    Request
    Prerequisites
    Description

      你可以使用该接口将一个新索引添加到集群中。在创建一个索引时,你可以指定下面的内容:

    Path parameters

      索引名称必须满足下面的规范:

    Query parameters
    Response body
    Example
    Index settings(create index api)

      每一个创建的索引都可以有关联settings,在请求体中定义:

      第5行,number_of_shards的值为1。   第6行,number_of_replicas的值为1(一个主分片有一个副本分片)。

      或者可以更简单一点:

    NOTE:你不需要再settings字段下显示的指定index字段

      更多关于在创建索引时,不需要关心的索引层设置(index level settings)的内容见index modules

    Mappings(create index api)

      该接口提供了mapping定义:

    Aliases(create index api)

      该接口同样可以提供别名的集合:

      索引别名同样支持date math

    Wait for active shards

      默认情况下,索引操作(Index operation)只有在每一个分片的主分片启用后才会返回一个响应,或者请求超时。索引操作的响应中告知发生了哪些事情:

      acknowledged描述的是否索引在集群中成功创建,shards_acknowledged描述的是在超时之前,索引中每一个分片要求的分片数量(shard copies,包含主分片跟副本分片)是否都已经启用(started)。注意的是有可能索引创建成功了,但是acknowledgedshards_acknowledged的值为false。这些值简单的描述了是否在超时之前完成了操作。如果acknowledgedfalse,超时之前,集群状态都未包含新创建的索引,但可能稍后就创建成功了。如果shards_acknowledgedfalse,超时之前,已启用的分片数量未达到要求(默认只需要主分片都已经启用)。即使集群状态已经成功包含了新创建的索引(比如acknowledged=true)。

      我们可以通过索引设置index.write.wait_for_active_shards使得只要求主分片都已经启用(注意的是修改这个设置同样会影响接下俩的写操作的wait_for_active_shards):

      或者通过请求参数wait_for_active_shards修改:

      关于wait_for_active_shards的详细介绍以及可选的配置值见Index API中的Active shards

    Create or update alias API

    (8.2)link

      像某个alias中添加一个data stream或index。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body
    Example

    Create or update component template API

    (8.2)link

      创建或个新一个组件模版(component template)。组件模版是构造索引模板(index template)的块,指定了mappingssettingsaliases

    Request
    Prerequisites
    Description

      一个索引模板可以由多个组件模版组成。若要使用一个组件模版,只需要在索引模板中的composed_of字段中指定即可。组件模板只有作为满足匹配的索引模板的一部分才能用于data stream和indices上。

      在索引模板中或者create index请求中直接指定的settings和mappings会覆盖组件模版中的定义。

      组件模版只在索引创建时使用,对于data streams,包括data stream创建时以及流中backing indices创建时。对组件模版的修改不会影响已有的索引,包括流中的backing indices。

    Comments in component templates

      你可以使用C风格的/**/在索引模板中添加注释。在请求体的任何位置都可以包含注释,但JSON开头的大括号之前除外。

    Path parameters
    Query parameters
    Response body
    Example
    Component template with index aliases

      你可以在组件模版中包含index aliases

      第16行,在别名中,{index}占位符将在索引创建时替代真正的索引名称。

    Applying component templates

      你可以使用version字段像索引模板中添加版本号。内部系统能通过这个版本号简单的管理模板。

      version字段是可选的,Elasticsearch不会自动生成该字段。

      若要unset这个version,用未定义该字段的模板替换。

      你可以通过get component template API检查这个verison字段。

    Component template metadata

      你可以使用_meta字段来添加任意的元数据到索引模板中。这个用户定义的对象存储在集群中,因此最好简短些。

      _meta字段是可选的,Elasticsearch不会自动生成该字段。

      若要unset这个_meta,用未定义该字段的模板替换。

      你可以使用get component template查看_meta字段。

    Create or update index template API

    (8.2)link

      创建/更新一个索引模板(index template)。索引模板中定义了settingsmappingsaliases ,使得自动的应用到新的索引上。

    Request
    Prerequisites
    Description

      Elasticsearch基于通配模式匹配索引名称将索引模板作用到新的索引上。

      在创建data stream或者index时应用索引模板。对于data stream,当流中的backing index创建时应用settings和mappings。

      create index请求中定义的settings和mappings会覆盖某个索引模板中的settings和mapping。

      索引模板的变更不会应用到现有的索引,包括data stream中现有的backing indices。

    Comments in index templates

      你可以使用C风格的/**/在索引模板中添加注释。在请求体的任何位置都可以包含注释,但JSON开头的大括号之前除外。

    Path parameters
    Query parameters
    Response body
    Example
    Index template with index aliases

      你可以在索引模板中包含index aliases

      第16行,在别名中,{index}占位符将在索引创建时替代真正的索引名称。

    Multiple matching templates

      如果匹配到了多个索引模板,那么使用优先级的高的索引模板。例如:

      对于以te*开头的索引,它将启动_source、2个主分片以及1个副本分片,因为只有template_2应用到以te*开头的索引。

    NOTE:拥有相同优先级且索引模式重叠的多个模板是不允许的,当尝试创建一个与现有相同优先级的索引模板匹配的模板时,系统会抛出错误。

    Template versioning

      你可以使用version字段像索引模板中添加版本号。内部系统能通过这个版本号简单的管理模板。

      version字段是可选的,Elasticsearch不会自动生成该字段。

      若要unset这个version,用未定义该字段的模板替换。

      你可以通过get index template检查这个verison字段。

    Template metadata

      你可以使用_meta字段来添加任意的元数据到索引模板中。这个用户定义的对象存储在集群中,因此最好简短些。

      _meta字段是可选的,Elasticsearch不会自动生成该字段。

      若要unset这个_meta,用未定义该字段的模板替换。

    Data stream definition

      若要为data stream定义一个模板,模板中必须包含data_stream字段。见create an index template

    Composing aliases, mappings, and settings

      当在索引模板的composed_of字段中指定了多个组件模板时,它们会按照指定的顺序合并,这意味着后面的组件模板会覆盖前面的组件模板。来自父索引模板的任何映射、设置或别名随后会被合并进来。最后,索引请求本身的任何配置也会被合并。

    在这个例子中,两个组件模板的顺序改变了索引的分片数量。

      在这种情况下,匹配t*的索引将会有三个主分片。如果组成模板的顺序颠倒了,索引将会有两个主分片。

      Mapping定义是递归合并的,这意味着后来的Mapping组件可以引入新的字段Mapping并更新Mapping配置。如果一个字段Mapping已经在前面的组件中存在,它的定义将被后来的组件完全覆盖。

      这种递归合并策略不仅适用于字段mappings,也适用于像dynamic_templatesmeta这样的根选项。如果前面的组件包含一个dynamic_templates块,那么默认情况下新的dynamic_templates会被添加到末尾。如果已经存在一个具有相同键的key,那么它将被新定义覆盖。

    Create or update index template API(legacy)

    (8.2)link

    IMPORTANT:这篇文档介绍legacy index templates。在Elasticsearch7.8中legacy index templates已被弃用并且使用可组合的模板(composable template)代替。更多关于composable templates的信息见Index templates

      创建或者更新一个index template

    Request

    PUT /_template/<index-template>

    Prerequisites
    Description

      index template定义了settingsmappings并且自动应用到新建的索引上。Elastic search基于index pattern匹配索引名称来应用到新的索引上。

    NOTE:可组合的索引(composable templates)总是优先于(take precedence)legacy templates。如果composable templates没有匹配到新的索引,则根据其顺序应用匹配的旧模板

      只在索引创建期间应用index template。index template的更改不会影响现有的索引。create index API请求中指定的settings和mappings会覆盖模板中settings和mapping。

    Comments in index templates

      你可以在index template中使用 C 风格的 /* */ 块注释。除了开始的大括号之前,你可以在请求正文中的任何位置包含注释。

    Getting templates

      Get index template (legacy)

    Path parameters
    Query parameters
    Request body
    Example
    Index template with index aliases

      你可以在索引模板中包含index aliases

      第15行,在别名中,{index}占位符将在索引创建时替代真正的索引名称。

    Indices matching multiple templates

      多个索引模板可能匹配同一个索引,因此,settings和mappings会被合并到最终的索引配置中。通过参数order控制合并顺序,优先级低的优先应用,随后优先级高的覆盖它们。例如:

      上面会关闭对_source的存储,但对于以tes*开头的索引的_source则是开启的。对于mappings,是所谓的深度合并,意味着mappings中的object/property可以在更高优先级的模式进下添加/覆盖,并且低等级的模板提供部分配置

    NOTE:有相同优先级并且匹配到相同的索引会导致无法确定的合并顺序

    Template versioning

      你可以使用version参数像索引模板中添加一个可选的版本号。系统内部可以使用这个版本号对模板进行简单管理

      version参数是可选的,不会由Elasticsearch自动生成。

      若要移除version,那么就不指定这个参数并且重新替换这个模板:

      你可以通过get index template查看version,并且使用请求参数filter_path使得只返回版本号。

      返回下面的响应:

    Delete component template API

    (8.2)link

      删除一个已有的的组件模版。

    Request
    Prerequisites
    Description

      这个接口用来 删除一个或多个组件模版,组件模版用于构造索引模板index template,来指定mappings、settings以及aliases。

    Path parameters
    Query parameters

    Delete dangling index API

    (8.2)link

      删除一个dangling Index。

    Request
    Prerequisites
    Description

      如果Elasticsearch遇到的索引数据不在当前集群状态中,那么这些索引会被认为是dangling Index。例如,当Elasticsearch节点下线时你删除了超过cluster.indices.tombstones.size数量的索引就有可能发生。

      通过索引的UUID来删除一个dangling Index。可以使用List dangling indices API获取索引的UUID。

    Path parameters
    Query parameters

    Delete alias API

    (8.2)link

      从一个alias中移除一个data stream或index。

    Request
    Prerequisites
    Path parameters
    Query parameters

    Delete index API

    (8.2)link

      删除一个或多个索引。

    Request
    Prerequisites
    Description

      删除某个索引会删除它的文档、分片以及元数据。他不会删除相关的Kibana组件,比如Data views、visualizations或者dashboards。

      你不能删除某个data stream 中当前的write index。若要删除它,你必须roll overdata stream,使得可以生成一个新的write index。随后你就可以使用这个接口删除它。

    Path parameters
    Query parameters

    Delete index template API

    (8.2)link

      删除一个index template

    Request

      <index-template>可以是用逗号隔开的多个模版,如果指定了多个模板名称并且没有使用通配符,那么提供的模版名称必须准确匹配现有的模板。

    Prerequisites
    Description

      使用该接口来删除一个或多个索引模板。索引模板中定义的settingsmappingsaliases会自动应用到新的索引上。

    Path parameters
    Query parameters

    Exists API

    (8.2)link

      检查某个data stream,index或者alias是否存在。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response codes

    Field usage stats API

    link

      

    Request
    Prerequisites
    Description
    Path parameters
    Query parameters
    Response body
    Example

    Flush API

    link

    Force merge API

    link

    Get alias API

    (8.2)link

      获取一个或多个aliases

    Request
    Prerequisites
    Path parameters
    Query parameters

    Get component template API

    (8.2)link

      获取一个或多个组件模版(component template)的信息。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Get component templates using a wildcard expression
    Get all component templates

    Get field mapping API

    (8.2)link

      获取一个或多个字段的mapping definitions。对于data stream,该接口返回流中backing indices的字段的mapping。

      当你不需要完整的mapping,或者当某个索引中包含很多数量的字段时,这个接口就非常的有用。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Examples
    Example with index setup

      你可以在创建一个新的索引时提供字段的mappings。下面create index API的请求创建了一个名为publications的索引,并且定义了一些字段的mappings。

      下面只返回了title的mapping:

      这个API返回以下响应:

    Specifying fields

      该接口允许你指定用逗号隔开的字段的列表。

      例如选择了author字段的子字段id,你必须使用全名author.id

      返回如下:

      该接口也支持通配符表达式:

      返回:

    Multiple targets and fields

      该接口可以用来通过单次请求从多个data streams或者indices中获取多个字段的mapping。

      <target><field>参数都支持用逗号隔开的列表以及通配符表达式。

      你可以忽略<target>参数或者使用*_all来获取集群中所有的data streams和indices。

      同样的,你可以忽略<field>参数或者使用*来获取目标data stream或者index中所有字段的mapping。然而,<field>参数不支持_all

      比如,下面的请求从名为my-index-000001my-index-000002的data stream或index中获取名为message的字段的mapping。

      下面的请求获取集群中data stream 或者index中名为message以及user.id的mapping。

      下面的请求获取集群中data stream 或者index中有id属性的所有字段的mapping。

    Get index API

    (8.2)link

      返回一个或多个索引信息。对于data stream,该接口返回流中的backing indices。

    Request
    Prerequisites
    Path parameters
    Query parameters

    Get index settings API

    link

      从一个或多个索引中返回设置信息(setting information)。对于data stream,返回的时backing indices的设置信息

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Multiple data streams and indices

      这个接口使得通过单次调用获取多个data stream或index的设置。若要获取集群中所有索引的设置,你可以使用在<targer>中使用_all*。支持通配符表达式。例如:

    Filtering settings by name

      通过通配符对设置进下过滤:

    Get index template API(legacy)

    (8.2)link

    IMPORTANT:这篇文档介绍legacy index templates。在Elasticsearch7.8中legacy index templates已被弃用并且使用可组合的模板(composable template)代替。更多关于composable templates的信息见Index templates

      获取一个或多个索引模板的信息。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Get multiple index templates
    Get index templates using a wildcard expression
    Get all index templates

    Get index template API

    (8.2)link

      获取一个或多个索引模板的信息。

    Request
    Prerequisites
    Path parameters

      (Optional, string)待返回的模板名称。接受通配符表达式。如果忽略这个参数则返回所有的模板。

    Query parameters
    Example
    Get index templates using a wildcard expression
    Get all index templates

    Get mapping API

    (8.2)link

      获取一个或多个索引的mapping definitions。对于data streams。这个接口获取流中backing indices的mappings。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Multiple data streams and indices

      该接口可以通过单次调用获取一个或多个data stream或index的信息。通常可以按照下面的语法来使用:

      如果你想要获取集群中所有索引的mapping,以下几个请求都是等效的:

    Import dangling index API

    (8.2)link

      导入dangling Index。

    Request
    Prerequisites
    Description

      如果Elasticsearch遇到的索引数据不在当前集群状态中,那么这些索引会被认为是dangling Index。例如,当Elasticsearch节点下线时你删除了超过cluster.indices.tombstones.size数量的索引就有可能发生。

      通过索引的UUID将这个索引导入到集群中。可以使用List dangling indices API获取索引的UUID。

    Path parameters
    Query Parameters
    Examples

      下面的例子描述了如何导入一个dangling Index:

      API返回下面的响应:

    Index segments API

    link

    Index stats API

    link

    Rollover API

    (8.2)link

      data stream或者index aliases创建一个新的索引。

    Request
    Prerequisites
    Description

    TIP:我们建议使用ILM的rollover动作来自动执行rollover。见Index lifecycle

      该接口为data stream或index aliases创建一个新的索引。这个接口的行为取决于rollover目标。

    Roll over a data stream

      如果你要roll over一个 data stream,该接口会为这个流创建一个新的write index。这个流之前的write index会成为一个普通的backing index。rollover同样会提高data stream的generation。见Rollover

    Roll over an index alias with a write index

    TIP:在Elasticsearch7.9之前,你通常使用index alias with a write index 来管理时序数据。Data stream替代了这个功能,要求更少的维护成本,自动跟data tiers集成。 Convert an index alias to a data stream

      如果索引别名指向多个索引,其中一个索引肯定是write index。该接口会为这个别名创建一个新的write index,把is_write_index设置为true。API同样会将之前的write index的is_write_index设置为false

    Roll over an index alias with one index

      如果rollover一个索引别名,并且它只指向一个索引,那该接口会为别名创建一个新的索引并且移除别名中原来的索引。

    Increment index names for an alias

      当你rollover一个索引别名,你可以为新的索引指定一个名称。如果你不指定,那么当前的索引会以-以及一个数字结尾,比如my-index-000001my-index-3,新的索引名会提高结尾的数字。例如你roll over一个别名,并且当前的索引名称为my-index-000001,那么创建出的新索引会命名为my-index-000002。无论之前的索引名称是什么,这个数值总是6个字符并且0作为填充值。

    Use date math with index alias rollovers 如果你使用索引别名用于时序数据,你可以在索引名称中使用date math来追踪rollover的日期。比如你可以创建一个别名,他指向名为<my-index-{now/d}-000001>的索引。如果你在2099年5月6日创建了索引,那索引名称就是my-index-2099.05.06-000001。如果你在2099年5月7日rollover了这个别名,那索引名称就是my-index-2099.05.07-000002。见Roll over an index alias with a write index中的例子

    Wait for active shards

      rollover会创建新的索引并且受限于wait_for_active_shards设置。

    Path parameters
    Query parameters
    Request body
    Response body
    Example
    Roll over a data stream

      下面的请求无条件 的rollover一个data stream。

      下面的请求只有在当前write index满足下面的条件才会rollover:

      这个API返回:

    Roll over an index alias with a write index

      下面的请求创建了<my-index-{now/d}-000001>并且让其作为my-alias的write index。

      下面的请求只有在当前write index满足下面的条件才会rollover:

      这个API返回:

      如果别名的索引名称使用来date math并且按照一定的间隔规律进下rollover,你可以使用data math来缩小查询范围。例如,下面的查询目标是最近三天的数据。

    Roll over an index alias with one index

      下面的请求创建了<my-index-{now/d}-000001>以及他的别名my-write-alias

      下面的请求只有在当前write index满足下面的条件才会rollover:

      这个API返回:

    Specify settings during a rollover

      通常你可以使用index template在rollover时自动配置索引。如果你rollover一个索引别名,你可以在接口添加额外的index settings或者覆盖模板中的settings。Data stream中不支持settings参数。

    Shrink index API

    (8.2)link

      将现有的索引收缩为一个拥有更少主分片的新索引。

    Request
    Prerequisites

      为了让分片分配更简单,我们建议你移除索引的副本分片。你可以最后重新添加副本分片,并且这个操作作为收缩操作的一部分。

      你可以通过update index settings API移除索引的副本分片,将剩余的分片重新分配到同一个节点,并且让索引为只读。

      第4行,移除索引的副本分片   第5行,将索引的分片重新分配到名为shrink_node_name上,见Index-level shard allocation filtering   第6行,阻止索引的写操作。但元数据的变更,比如删除索引,仍然是允许的

      重新分配索引需要花费一定的时间。处理进度可以通过_cat recovery API查看,或者可以调用cluster health API以及参数wait_for_no_relocating_shards等待所有的分片重新分配结束。

    Description

      该接口将现有的索引收缩为一个拥有更少主分片的新索引。目标索引中请求的主分片数量必须是源索引中分片数量的因子(factor)。例如,具有 8 个主分片的索引可以收缩为具有 4、2 或 1 个主分片,而具有 15 个主分片的索引可以收缩为具有 5、3 或 1 个主分片。如果索引中的分片数是质数(prime number),则只能收缩为单个主分片。在收缩之前,索引中每个分片(主分片或副本)必须存在于同一节点上。

      data stream当前的write index不能收缩。若要收缩当前的write index,data stream必须先rolled over,这样新的write Index会被创建,那么之前的write index就可以收缩了。

    How shrinking works

      收缩操作:

    1. 创建一个跟源索引有相同定义的目标索引,但是有更少的主分片

    2. 建立源索引跟目标索引的hard-links segments。(如果系统不支持hard-linking,那么所有的段会拷贝到新的索引,这样花费更多的处理时间。同样的如果使用了多个数据路径,并且它们不在同一个磁盘上,由于hardlink不支持跨磁盘,那么就要求完全拷贝段文件)

    3. 恢复后的目标索引就像是一个被关闭的索引,并且刚刚被打开

    Shrink an index

      若要将源索引my_source_index收缩到名为my_target_index的目标索引中,可以发起下面的请求:

      第4行,清除目标索引中来自源索引的索引设置allocation requirement   第5行,清除目标索引中来自源索引的索引设置index wrtie block

      一旦目标索引添加到集群状态,上面的请求就会马上返回。他不会等待收缩操作开始。

    IMPORTANT:只有满足以下的要求,索引才可以被收缩:

    • 目标索引必须不存在

    • 源索引必须比目标索引有更多的主分片

    • 目标索引中的主分片数量必须是源索引的因子。源索引必须比目标索引有更多的主分片

    • 如果目标索引是单个分片,那么源索引中所有分片的文档数量总和不能超过2,147,483,519,因为这是单个分片能处理的最大文档数量

    • 处理收缩操作的节点必须要有足够多空闲磁盘来容纳现有索引的第二个副本

      _shrink操作类似create index API,接受对目标索引提供settingsaliases参数:

      第5行,目标索引的主分片数量。必须是源索引的因子   第6行,best compression只有对新写入到目标索引的数据生效,比如通过force-merging将分片合并为单个段。

    Monitor the shrink process

      收缩处理进度可以通过_cat recovery API查看,或者可以调用cluster health API以及参数wait_for_status设置为yellow来等待所有的主分片分配结束。

      只要目标索引被添加到集群状态中,在分片分配结束之前,该接口就会马上返回。在这个时间点,所有的分片处于unassigned状态。如果因为任何原因导致目标索引不能分配到收缩节点上,索引的主分片仍然会处于unassigned状态直到可以被分配到那个节点上。

      一旦主分片分配结束,就切换成initializing状态,然后收缩处理就开始了。当收缩操作完成,就切换成active状态。在这个时间点,Elasticsearch会尽量分配副本分片并且可能决策出将主分片重新分配到其他节点。

    Wait for active shards

      由于收缩操作创建一个新的索引来收缩分片,因此在索引创建时的wait for active shards设置也适用于收缩索引操作。

    Path parameters
    Query parameters
    Response body

    Simulate index API

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束。

      返回索引的配置,这些配置从匹配到的Index template索引模板中获得。

    Request
    Prerequisites
    Path Parameters
    Query parameters
    Request body
    Examples

      下面的例子展示的是应用到my-index-000001索引的现有模板的配置信息。

      第1行,创建一个组件模版(ct1),定义主分片数量为2。   第10行,创建第二个组件模版(ct2)定义0个副本分片以及一个mapping   第26行,创建一个索引模板(final-template)并且使用了两个组件模版   第33行,展示将应用到my-index-000001的配置信息

      响应中展示了由final-template提供的settings、mappings以及aliases:

    Simulate index template API

    (8.2)link

      返回将被某个索引模板(index template)应用的索引配置信息。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body
    Response body
    Example
    Simulating an existing template

      下面的例子中创建并且模拟了一个组件模版:

      第1行,创建一个组件模版(ct1),定义主分片数量为2。   第10行,创建第二个组件模版(ct2)定义0个副本分片以及一个mapping   第26行,创建一个索引模板(final-template)并且使用了两个组件模版   第33行,展示了由final-template应用后的配置

      响应中展示了由final-template应用的settings、mappings以及aliases:

      第5行,来自ct1中主分片的数量   第6行,来自ct2中副本分片的数量   第16行,来自ct1中的mappings

    Simulating an arbitrary template configuration

      若要将模板添加到集群之前,先看下它里面的设置,你可以在请求中测试模板配置。如果存在更高等级的模版,那么则使用现有的模板而不是使用请求体中指定的。

      会在响应中的overlapping中有相同的index_patterns但是优先级低的模版。

    Split index API

    (8.2) link

      将现有索引切分为拥有更多主分片的新索引。

    Request
    Prerequisites

      在开始切分这个索引前需要满足下面的条件

      你可以通过下面的方式将索引设置为只读:

      不允许写入的索引跟deleting index一样仍然允许进行元数据metadata的更改。

      当前处于数据流data streams的write index不能被切分,如果要切分当前的write index,那么数据流必须先要执行roll over,使得一个新的write index被创建并且之前的write index就可以被切分了。

    Description

      索引切分API允许你将现有的索引切分到新的索引中,原本的一个主分片会被切分到两个或者多个主分片中。

      索引被切分的次数取决于index.number_of_routing_shards,该值用于在内部将文档使用一致性哈希分布到分片上。例如,一个拥有5个分片,并且index.number_of_routing_shards的值设置为30时,那么每个分片可以按照因子2或者3进行划分,换句话说,可以按照下面的方式进行划分:

      index.number_of_routing_shards是一个static索引设置,只能在索引创建时期或者关闭时设置。

    Index creation example

      下面create index API中创建了名为my-index-000001的索引,并且设置index.number_of_routing_shards的值为30。

      index.number_of_routing_shards的默认值取决于原先的索引的主分片数量。默认情况下允许按照因子2进行切分直到最大切分数量为1024。然而原先的分片数量会被考虑进来。比如5个主分片的索引可以被切分为10, 20, 40, 80, 160, 320, 或者最大值640 (一次或者多次切分)。

      如果原先的索引的主分片数量是1(或者多个分片的索引被收缩shrunk到一个主分片),那么它会被切分为比1大的一个任意数值。默认的 routing shards的数量会被应用(apply)到新的索引中。

    How splitting works

      切分操作:

    1. 创建一个跟源索引(source index)定义相同的目标索引(target index),但是目标索引拥有更多主分片数量。

    2. 建立源索引到目标索引的硬链接(hard-linking)(如果操作系统不支持硬链接,那么所有的段会被复制到新的索引中,这是一个开销较大的过程)。

    3. 对所有的文档进行hash操作,在low level files都创建后,删除那些属于不同的分片的文档

    4. 恢复目标索引,就像是一个关闭的索引刚刚被重新打开那样

    Why doesn’t Elasticsearch support incremental resharding?

      从N个分片到N+1分片,又名增量分片,确实是许多键值存储支持的功能。 添加新分片并仅向该新分片中推送新数据不是一种选择:这可能是一个索引瓶颈,鉴于文档的_id属于哪个分片,这是获取、删除和更新请求所必需的,这将变得相当复杂。 这意味着我们需要使用不同的散列方案重新平衡现有数据。

      键值存储最常用的高效方法是使用一致的散列。 当分片数量从N增加到N+1时,一致的哈希只需要迁移1/N的键。 然而,Elasticsearch的存储单位是Lucene的索引。 由于其面向搜索的数据结构,占用Lucene索引的很大一部分,无论是只有5%的文档,删除它们并在另一个碎片上索引通常比键值存储的成本高得多。 如上一节所述,当通过乘法因子增加分片数量时,这一成本是合理的:这允许Elasticsearch在本地执行拆分,这种允许在索引级别执行拆分,而不是对需要移动的文档进行重新索引,并使用硬链接进行高效的文件复制。

      对于仅追加数据,可以通过创建新索引并将新数据推送到其中,同时添加涵盖读取操作的旧索引和新索引的别名,从而获得更大的灵活性。 假设新旧索引中分别有M和N个分片,与搜索具有M+N分片的索引相比,这没有开销。

    Split an index

      执行下面的请求将名为my_source_index的索引切分到名为my_target_index

      上述的请求在索引my_target_index被添加到集群后就会返回,它不需要等待开始切分操作。

    IMPORTANT: 索引在满足下面的要求后才能被切分

    1. 目标索引必须不存在

    2. 源索引必须比目标索引的主分片数量少

    3. 目标索引的主分片数量必须是源索引的倍数

    4. 处理切分的节点必须有足够的磁盘空间,要能容纳现有索引以及一份拷贝的大小

      对于目标索引,API_splitcreate index api一样接收参数settingsaliases

      第4行中,目标索引的主分片数量一定要大于源索引的主分片数量。

    NOTE:Mappings may not be specified in the_split request.

    Monitor the split process

      切分过程可以通过_cat recovery API进行监控,也可以通过调用cluster health API ,等待所有主分片被分配完成后,参数wait_for_status被设置为yellow

      _split接口在目标索引添加到集群后,所有分片被分配前就会马上返回。在这个时间点,所有的分片处于unassigned状态,如果目标索引因为任何原因导致无法被分配,主分片会一直unassigned,直到在这个节点上能被分配。

      一旦主分片被分配好了,它的状态就会变为initializing,然后切分操作就会开始。当切分操作结束后,主分片的状态就会变为active,这个时候,Elasticsearch就会尝试对主分片进行副本分片的分配,并将主分片迁移到其他节点。

    Wait for active shards

      因为切分操作会创建一个新的索引用于对分片的切分,索引创建中的wait for active shards这个设置同样应用于索引的切分。

    Path parameters
    Query parameters
    Request body

    Index template exists API(legacy)

    (8.2)link

    IMPORTANT:这篇文档介绍legacy index templates。在Elasticsearch7.8中legacy index templates已被弃用并且使用可组合的模板(composable template)代替。更多关于composable templates的信息见Index templates

      查看某个legacy索引模板是否存在:

    Request
    Prerequisites
    Description

      使用这个接口判断一个或多个索引模板是否存在。

      索引模板定义了 settingsmappingsaliases,可以自动应用到新创建的索引上。

    Path parameters
    Query parameters
    Response codes

    List dangling indices API

    (8.2)link

      该API用于列出dangling index。

    Request
    Prerequisites
    Description

      如果Elasticsearch遇到的索引数据不在当前集群状态中,那么这些索引会被认为是dangling Index。例如,当Elasticsearch节点下线时你删除了超过cluster.indices.tombstones.size数量的索引就有可能发生。

      可以使用这个API列出dangling Index,你也可以import或者delete这些索引。

    Examples

      API返回下面的响应:

    Open index API

    (8.2)link

      打开一个关闭的索引。对于data streams,这个接口打开所有关闭的backing indices。

    Request
    Prerequisites
    Description

      你可以使用这个接口重新打开一个关闭的索引。如果请求目标是一个data stream,则会打开流中所有的关闭的backing indices。

      当打开或者关闭一个索引时,对于重启索引分片,master要负责反应索引新的状态。分片才能进行正常的恢复操作。集群会对打开/关闭的索引自动进行replicate,保证总是有足够的shard copies。

      你可以打开/关闭多个索引。如果请求中显示引用了缺失的索引则会抛出错误。当然可以通过ignore_unavailable=true来关闭这个行为。

      你可以显示指定要打开/关闭的索引名称。若要使用_all*或者其他通配符表达式打开/关闭索引,需要将action.destructive_requires_name修改为false。可以通过cluster update settings API更新这个参数。

      关闭的索引会消耗大量的磁盘空间,这可能在受控环境中引发问题。可以通过cluster settings API,将 cluster.indices.close.enable 设置为 false 来禁用关闭索引的功能。默认值为 true

    Wait for active shards

      由于打开/关闭索引都会分配分片,创建索引时使用的wait_for_active_shards也会应用到_open_close的索引动作上。

    Path parameters
    Query parameters
    Example

      下面的例子重新打开了一个名为my-index-000001的索引。

      这个接口返回以下结果:

    Resolve index API

    (8.2)link

      解析指定的indices、aliases、data streams的Index pattern或者名称。支持多个pattern以及远端集群

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example

      这个接口返回以下响应:

      第2行,所有匹配了提供的名称或者表达式的索引   第6行,index attribute可以是open, closed, hidden, system, frozen   第25行,所有匹配了提供的名称或者表达式的别名   第34行,所有匹配了提供的名称或者表达式的data stream

    Refresh API

    link

    Unfreeze index API

    (8.2)link

    WARNING:Deprecated in 7.14 在8.0中,我们移除了冻结索引的能力。在之前的版本中,冻结索引能降低内存开销。然而由于recent improvements in heap memory usage使得冻结索引不再有用了。你可以使用这个API解冻那些在7.x中冻结的索引,并且这些索引没有关联frozen data tier。

      解冻一个索引。

    Request
    Prerequisites
    Path parameters
    Example

      下面的请求解冻了一个索引:

    Update index settings API

    (8.2)link

      实时更新一个dynamic index setting

      对于data stream,索引设置(Index setting)默认应用到所有的backing indices上。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body
    Example
    Reset an index setting

      若要将设置还原为默认值,使用null,例如:

      可以通过Index modules查看所有live Index可以更新的动态设置。若不想要现有的设置被更改,可以将请求参数preserve_existing设置为true

    Bulk indexing usage

      这个Update index settings API可以用来动态更改索引设置使得bulk indexing性能更高,然后将回到实时索引状态。在bulk indexing之前,使用:

      (另一个优化选项就是不开启副本分片,写入后再开启,不过这种方式取决于用户场景)

      随后一旦bulk indexing完成,再更新设置(恢复到默认值):

      并且应该调用一次force merge:

    Update index analysis

      你只在在关闭的索引上定义新的analyzer。

      若要添加一个analyzer,你必须关闭索引,定义好analyzer然后重新打开索引。

    NOTE:你不能关闭data stream的writer Index 若要更新data stream的write Index的analyzer以及以后的backing indices,可以通过index template used by the stream更新analyzer。然后通过roll over the data stream将新的analyzer应用到流中的write Index以及以后的backing indices上。在rollover后,将会影响查询以及新添加到流中的数据。然而,它不会影响data stream中的backing indices或现有的数据。

    若要为现有的backing indices更改analyzer,你必须创建一个新的data stream然后reindex你的数据。见Use reindex to change mappings or settings

      例如,下面的命令将名为content的analyzer添加到my-index-000001索引中:

    Update mapping API

    (8.2)link

      添加新的字段到一个现有的data stream或index中。你可以使用这个接口修改现有字段(existing field)的查询设置(search setting)。

      对于data stream,这些变更默认应用到backing indices上。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Example
    Example with single target

      该接口要求一个现有的data stream或index。下面的create index请求创建了名为publications的索引并且没有mapping。

      下面的请求中向索引publications中新增了名为titletext类型的字段。

    Multiple targets

      该接口可以通过单次请求应用到多个data streams或indices。例如,你可以同一时间向my-index-000001my-index-000002调用该接口:

    Add new properties to an existing object field

      你可以使用这个这个接口,将新的属性(properties)添加到现有的object字段中。若要观察它是如何工作,见下面的例子:

      使用create index接口创建一个名为name的object类型的字段以及name下名为firsttext类型的子字段。

      使用当前接口在name下添加一个新的名为lasttext类型的子字段。

    Add multi-fields to an existing field

      multi-fields可以让你对同一个字段定义不同的mappings 类型。你可以使用该接口更新mappings 参数fields,为现有的字段开启multi-fields。

      若要观察它是如何工作,见下面的例子:

      使用create index创建一个索引,索引中定义了名为citytext类型的字段

      text类型的字段用于全文检索,keyword类型的字段不会被分词但更适合用于排序或聚合。

      使用该接口为city字段开启multi-filed,下面的请求添加了名为city.rawkeyword类型的multi-field,他可以用于排序

    Change supported mapping parameters for an existing field

      mapping parameter中的文档指明了是否可以使用当前接口更新这些mapping参数。比如你可以使用这个接口更新ignore_above参数。

      若要观察它是如何工作,见下面的例子:

      使用create index接口创建一个索引,它包含名为user_idkeyword类型的字段。user_id字段有一个ignore_above参数,该值为20

      使用该接口将ignore_above的值改为100

    Change the mapping of an existing field

      除了支持修改mapping parameters,你不能更改现有字段的mapping类型。修改现有字段的类型可能使已经索引的数据无效。

      如果你需要修改data stream的backing indices中字段的类型,见Change mappings and settings for a data stream

      如果你需要修改其他索引中的字段的类型,你只能创建一个新的索引,并且使用正确的mapping类型,让通过reindex重新写入数据。

      若要观察它是如何工作,见下面的例子。

      使用create index接口创建一个新的索引,它包含名为user_idlong类型的字段。

      使用index接口写入一些带有user_id字段数据的文档。

      若要将user_id字段修改为keyword类型,则使用create index API创建一个新的索引,并且定义正确mapping。

      使用reindex API从旧索引中拷贝到新索引中。

    Rename a field

      重命名字段的名称会让旧名称的字段对应的数据失效。你可以添加一个alias来作为替代方案。

      例如,使用create index创建一个索引,它包含了名为user_identifier的字段。

      使用该接口向现有的字段user_identifier中添加名为user_id的字段的别名(field alias)。

    Ingest APIs

    (8.2)link

      使用ingest API来管理ingest pipeline和processor的相关的任务以及资源。

    Ingest pipeline APIs

      使用下面的接口来创建。管理以及测试ingest pipeline:

    Stat APIs

      使用下面的接口获取ingest 处理的统计信息:

    Create or update pipeline API

    (8.2)link

      创建或者更新一个ingest pipeline。使用这个接口做出的变更能立即生效。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Example
    Pipeline metadata

      你可以使用_meta参数添加任意的元数据到某个pipeline中。这是用户定义的对象,存储在集群状态中,因此尽量简短些。

      _meta参数是可选的并且不会由Elasticsearch自动生成

      若要移除_meta,更新pipeline并且不指定该值。

    Get pipeline API

    (8.2)link

      返回一个或多个ingest pipeline的信息。则个API返回pipeline的本地引用。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Get information for a specific ingest pipeline

      这个接口返回下面的响应:

    Delete pipeline API

    (8.2)link

      删除一个或多个ingest pipeline。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Example
    Delete a specific ingest pipeline
    Delete ingest pipelines using a wildcard expression
    Delete all ingest pipelines

    GeoIP stats API

    (8.2)link

      获取用于geoip processor的 GeoIP2 数据库的下载统计信息。

    Request
    Prerequisites
    Response body

    Simulate pipeline API

    (8.2)link

      对提供的文档集合执行一个ingest pipeline。

    Request
    Prerequisites
    Description

      这个接口对请求体中提供的文档集合执行指定的pipeline。   你可以对提供的文档执行一个现有的pipeline或者在请求体中定义一个pipeline。

    Path parameters
    Query parameters
    Response body
    Example
    Specify a pipeline as a path parameter

      该接口返回下面内容:

    Specify a pipeline in the request body

      该接口返回下面内容:

    View verbose results

      你可以使用该接口查看pipeline中每一个processor是如何影响被提取(ingest)的文档的。若要查看在模拟请求中每一个processor的中间结果,你可以在请求中添加verbose 参数。

      该接口返回下面内容:

    Index lifecycle management APIs

    (8.2)link

      你可以使用下面的API设置策略来自动的管理索引的生命周期。更多关于索引生命周期index lifecycle management (ILM)的信息见ILM: Manage the index lifecycle

    Policy management APIs
    Index management APIs
    Operation management APIs

    Create or update lifecycle policy API

    (8.2)link

      创建或更新生命周期策略。见Index lifecycle了解策略组成的定义

    Request
    Prerequisites
    Description

      创建一个生命周期策略。如果指定的策略已经存在,那么就替换该策略并提高版本号。

    NOTE:只有最新版本的策略才会被存储,你不能倒退到之前的版本。

    Path parameters
    Query parameters
    Examples

      下面的例子创建了一个名为my_policy的新策略。另外,你可以使用_meta参数添加任意的元数据到策略中,这个_meta参数是可选的并且不会自动生成,不会被Elasticsearch使用。若要取消_meta,可以替换策略而不需要再指定一个。若要检查_meta,你可以使用Get lifecycle policy

      如果请求成功,你会收到如下结果:

    Get lifecycle policy API

    (8.2)link

      获取一个生命周期策略。

    Request
    Prerequisites
    Description

      返回指定策略的定义。包含了策略版本和最后一次改动的时间。如果没有指定策略,那么返回所有定义好的策略。

    Path parameters
    Query parameters
    Examples

      下面的例子获取了一个名为my_policy的生命周期策略:

      如果请求成功,响应中的内容包含了策略定义:

      第3行,当策略更新后,策略版本号则会提高   第4行,上一次策略更改时间   第25行,哪些索引、data streams或者模版正使用这个策略

    Delete lifecycle policy API

    (8.2)link

      删除一个索引生命周期策略。

    Request
    Prerequisites
    Description

      删除指定的生命周期策略定义。你不能删除一个正在被使用的策略。如果策略正在被用于管理任意的索引,请求会失败并且返回一个错误。

    Path parameters
    Query parameters
    Examples

      下面的例子删除了一个名为my_policy的策略:

      当成功删除了一个策略,你会收到以下结果:

    Move to lifecycle step API

    (8.2)link

      触发执行生命周期策略中的指定的一个步骤。

    Request
    Prerequisites
    Description

    WARNING:这个操作可能会导致数据丢失。手动将某个索引移动到一个指定步骤,即使该步骤已经执行过也会再次执行。 这是一项潜在的破坏性操作,应将此视为专家级别的API。

      手动将某个索引移动到一个指定步骤并且执行该步骤。你必须在请求体中执行当前步骤和需要执行的步骤。

      如果当前步骤不匹配索引当前正在执行的步骤,请求则会失败。这样的目的是防止索引从一个非期望的步骤移动到下一步。

      当指定了索引被移动的目标阶段(next_step)后,name或者actionname是可选的。如果只指定了阶段(共有Hot、Warm、Cold、Frozen、Delete这五个阶段,索引刚被管理时处于一个new阶段),索引会被移动到目标阶段的第一个动作的第一步。如果阶段跟动作都制定了,那么索引会被移动到指定阶段的指定动作的第一步。只指定动作是合法的,索引不能被移动不是策略的一部分的步骤。

    Path parameters
    Query parameters
    Request body
    Examples

      下面的例子将名为my-index-000001的索引从初始化步骤移动到forcemerge步骤:

      第3行,期望索引正处于的步骤   第8行,你想要执行的步骤   第10行,索引将被移动到某个动作(可选)   第11行,索引将被移到某一步骤(可选)   如果请求成功,你会收到如下结果:

      如果索引不在current_step中指定的new阶段,请求将失败。

    Remove policy from index API

    link

      从某个Index或者data stream的backing indices中移除被分配的生命周期策略。

    Request
    Prerequisites
    Description

      对于indices,这个接口将移除indices被分配的生命周期策略并且停止管理策略中指定的索引

      对于data streams,这个接口将移backing indices被分配的生命周期策略并且停止管理策略中指定的索引

    Path parameters
    Query parameters
    Examples

      下面的例子将移除名为my-index-000001的索引,它被分配的策略。

      如果请求成功,你会收到以下结果:

    Retry policy execution API

    (8.2)link

      对正处于ERROR步骤的索引,重试它对应的策略。

    Request
    Prerequisites
    Description

      将策略回到错误发生的地方然后继续步骤。使用ILM Explain API 查看某个索引是否处于ERROR步骤。

    Path parameters
    Query parameters
    Examples

      下面的例子对名为my-index-000001的索引进行重试:

      如果请求成功,你会收到以下结果:

    Get index lifecycle management status API

    (8.2)link

      获取当前索引生命周期index lifecycle management (ILM)的状态。

      你可以通过start ILMstop ILM来分别启动和停止ILM

    Request
    Prerequisites
    Query parameters
    Request body
    Examples

      下面的例子获取ILM插件状态:

      如果请求成功,响应中的内容会展示操作模式(operation mode):

     

    Explain lifecycle API

    (8.2)link

      为一个或多个索引获取当前生命周期状态。对于data streams,这个接口为流中的backing indices获取当前生命周期状态。

    Request
    Prerequisites
    Description

      获取索引当前的生命周期状态,比如当前执行中的阶段,动作和步骤。展示索引进入时间、运行中的阶段的定义、以及关于任何相关的错误信息。

    Path parameters
    Query parameters
    Examples

      下面的例子获取了名为my-index-000001的索引的生命周期状态:

      当索引刚刚由ILM接管,explain中会显示索引处于管理中并且处于new阶段:

      第5行,当索引创建后,这个时间戳用来决定什么时候开始rollover   第6行,索引创建后到现在的时间(通过max_mag计算什么时候开始rollover)   第7行,显示索引是否被ILM管理。如果没有被管理,其他字段将不会显示   第8行,正用于管理这个索引的ILM的策略名称   第9行,用于min_age的时间戳   第10行,索引的年龄(用来计算什么时候进入下一阶段)   第12行,当前阶段是什么时候进入的   第14行,当前动作是什么时候进入的   第16行,当前步骤是什么时候进入的

      一个某个策略在索引上运行,响应中会包含一个phase_execution对象来展示当前阶段的定义。对策略进行修改不会影响这个索引,直到当前阶段完成。

      第23行,当索引进入到这个阶段,显示这个阶段的JSON格式的定义   第31行,加载的策略版本   第32行,上一次策略修改时间   第33行,上一层策略修改时间(epoch time)

      如果ILM正在等待某个步骤的完成,响应中会包含在索引上正在执行中的步骤状态信息。

      第21行,正在处理中的步骤状态

      如果在执行策略中某一步骤时发生错误,则索引会移动到ERROR步骤,那么你必须采取行动使得能让其进入下一步骤。有些步骤在特定环境下会安全的自动重试。若要帮助你诊断问题,这个接口的响应中会显示失败的步骤,提供错误相关信息,以及尝试重试这个失败步骤的信息。

      第21行,发生错误的步骤   第22行,指示是否重试这个步骤可以解决这个错误,如果为true,ILM会自动重试这一步骤   第23行,尝试重试执行失败步骤的次数   第24行,出现的问题信息

    Start index lifecycle management API

    (8.2)link

      启动索引生命周期管理插件(index lifecycle management (ILM) plugin)。

    Request
    Prerequisites
    Description

      如果ILM插件停止了,则启动它。当形成集群后,ILM会自动启动ILM。只有在使用Stop ILM API停止ILM插件后才有必要重新启动它。

    Path parameters
    Examples

      下面的例子启动了ILM插件。

      如果请求成功,你会收到以下结果:

    Stop index lifecycle management API

    (8.2)link

      停用生命周期管理插件(index lifecycle management (ILM) plugin)。

    Request
    Prerequisites
    Description

      暂停所有的生命周期管理操作并且停止ILM插件。当你想要对集群进行维护并且需要防止ILM对你的索引执行任何操作时是非常有用的。

      这个接口在被确认后会马上返回,但是插件可能还会继续运行直到处理中的操作完成并且插件能被正确的停止。使用Get ILM Status API查看ILM是否运行中。

    Path parameters
    Examples

      下面的例子停用了ILM插件。

      如果请求没有遇到错误,你会收到如下结果:

    Migrate to data tiers routing API

    link

    Machine learning APIs

    link

    Open anomaly detection jobs API

    link

    Start datafeeds API

    link

    Set upgrade mode API

    link

    Node lifecycle APIs

    link

    Rollup APIs

    link

    Create rollup jobs API

    link

    Delete rollup jobs API

    link

    Get rollup jobs API

    link

    Get rollup job capabilities API

    link

    Get rollup index capabilities API

    link

    link

    Start rollup jobs API

    link

    Stop rollup jobs API

    link

    Script APIs

    (8.2)link

      使用下面的API来管理、存储以及测试你的script

    Script support APIs

      使用script support APIs获取支持的脚本内容和脚本语言。

    Stored script APIs

      使用stored script APIs来管理stored scriptssearch templates.

    Painless APIs

      在生成中使用之前,先使用Painless execute API 安全的测试Painless脚本。

    Create or update stored script API

    (8.2)link

      创建或更新一个stored script或者search template

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body

    Delete stored script API

    (8.2)link

      删除一个stored Scriptsearch template

    Request
    Prerequisites
    Path parameters
    Query parameters

    Get script contexts API

    (8.2)link

      获取支持的脚本内容和它们的方法。

    Request
    Prerequisites

    Get script languages API

    (8,2)link

      获取支持的script languages和它们的上下文。

    Request
    Prerequisites

    Get stored script API

    (8.2)link

      获取一个stored Scriptsearch template

    Request
    Prerequisites
    Path parameters
    Query parameters

    Search APIs

    link

    Search templates(Search APIs)

    Search API

    link

    Query parameters

    link

    allow_partial_search_results
    ccs_minimize_roundtrips
    preference
    query
    search_type

    (8.2)link

      该接口可以让你执行异步的查询请求,监视查询的过程,并且当可用时获取部分结果。

    Submit async search API

      异步执行一个查询请求。它跟search API有相同的请求参数跟请求内容。

      响应中包含了正在执行查询的标识符。你可以使用这个ID随后获取查询的最终结果。当前可见的查询结果作为response对象中的一部分返回。

      第2行,异步搜索的标识符,用来监视查询进程,获取查询结果或者删除这次查询   第3行,当这个Query不处于运行中,会表明查询是否失败或者在所有分片上都成功完成。当Query处于执行中,is_partial总是为true   第4行,查询是否处于执行中还是已经完成   第12行,将在多少个分片上进行查询   第13行,在多少个分片成功完成查询   第19行,当前多少文档匹配了Query,这些文档属于已经成功完成查询的分片

    NOTE:尽管查询不处于运行中,因此 is_running 被设置为 false,但结果可能是部分的。这种情况发生在一些分片返回结果后搜索失败,或者协调异步搜索的节点停止运行的情况下。

      可以通过设置 wait_for_completion_timeout 参数来实现阻塞并等待,直至搜索操作在指定的超时时间内完成,默认这个超时时间是1秒。如果在超时时间内完成异步查询,响应中不会包含Id,因为结果不会存储在集群中。keep_on_completion参数,默认为false,当查询在wait_for_completion_timeout完成时,可以设置为true以后的查询存储查询结果。

      你也可以通过keep_alive参数指定异步查询应该保持多久,默认是5d(5天)。以后的异步查询和其他保存的查询结果将在这个周期后删除。

    NOTE:当你对搜索结果进行排序,而这些结果的排序依据(即主要排序字段)是一个已经被索引的字段时,Elasticsearch可以根据每个分片持有该字段的最小值和最大值来对这些分片进行排序。因此,根据你请求的排序标准,部分结果可以变得可用,即使搜索还没有完全完成。

      异步搜索支持跟Search API相同的参数,但有些参数的默认值是不同的:

    WARNING:异步搜索不支持scroll,也不支持包含suggest section的查询请求。只有在ccs_minimize_roundtrips设置为false时才支持CCS查询

    WARNING:默认情况下Elasticsearch不允许存储超过10Mb的异步查询结果,尝试这么做会导致出现错误。可以通过修改集群设置search.max_async_search_response_size来修改存储异步查询结果允许的最大值

      该接口根据之前提交的异步查询返回的ID进行查询。如果开启了Elasticsearch security features。指定的异步查询若要访问结果需要受限于the user or API key that submitted it

      第2行,当这个Query不处于运行中,会表明查询是否失败或者在所有分片上都成功完成。当Query处于执行中,is_partial总是为true   第3行,查询是否处于执行中还是已经完成   第6行,异步查询的过期时间   第10行,表示执行归并的结果的数量。如果相比较上一次的查询结果,这个值变大了,那么你可以在查询响应中获取更多额外的结果   第13行,执行这个Query的分片数量。注意的是为了分片的结果能包含在查询响应中,它们首先会被归并(reduce)   第25行,部分聚合结果,来自那些已经完成Query的分片的结果

      在调用 Get Async Search API 时,也可以提供 wait_for_completion_timeout 参数,以便等待搜索完成直到提供的超时时间。如果在超时到期之前可用,将返回最终结果,否则一旦超时到期,将返回当前可用的结果。默认情况下没有设置超时,这意味着将返回当前可用的结果,无需任何额外等待。

      keep_alive 参数指定异步搜索在集群中应该保持可用的时间长短。未指定时,将使用对应的提交异步请求时设置的 keep_alive。否则,可以覆盖此值并延长请求的有效性。当此期限到期时,如果搜索仍在进行中,则会被取消。如果搜索已完成,其保存的结果将被删除。

    Get async search status

      该接口不会获取查询结果,而是根据ID只显示之前提交的异步查询的状态。如果开启了Elasticsearch security features,访问该接口受限于monitoring_user role

      第9行,表示目前执行了Query的分片数量

      第13行,表示异步查询完成但是出错了。

      你可以使用这个接口根据ID手动删除一个异步查询。如果查询在运行中,那么它会被取消。否则,已保存的查询结果会被删除。

      如果开启了Elasticsearch security features,删除异步操作受限于:The authenticated user that submitted the original search request. * Users that have the cancel_task cluster privilege。

    Point in time API

    (8.2)link

      默认在目标索引的最新可见数据上执行查询请求称为point in time。Elasticsearch PIT是一个轻量级针对于数据状态the state of the data的视图view,在数据初始化后就存在了。在有些场景中,更偏向于使用PIT来执行多次查询。例如,如果refreshes发生在多个search_after请求之间,那么这些请求的结果可能不一致,因为每一次都在最新的PIT上执行查询。

    Prerequisites
    Examples

      PIT被用来搜索前必须显示的打开,参数keep_alive告诉Elasticsearch我们需要保留这个PIT的时间。比如?keep_alive=5m。

      上述请求的结果会返回一个_id,用于设置请求中参数pit中的id

    1. 使用pit查询的请求不能指定indexrouting参数,因为这些参数都已经从PIT中复制过来了。

    2. 参数id告诉Elasticsearch在哪一个PIT上执行查询

    3. 参数keep_alive告诉Elasticsearch延长这个PIT的live时间

    IMPORTANT:对于打开PIT的请求以及每一个后续的请求都会收到不一样的id,因此下一次查询总是用这个最新的id

    Keeping point in time alive

      参数keep_alive用于打开PIT的请求以及后续的查询请求,用来延长expand对应的PIT的存活时间time to live,这个值表示需要在这个时间内执行下一次查询,而不是在这个时间内必须处理完所有的结果。

      通常来说,后台的段的合并操作会将一些较小的段合并成一个更大的新的段。一旦这些较小的段(已经被合并了)不再被使用那么就会被删除。然后PIT会使得这些段防止被删除因为它们还在使用中。

    TIP:保留旧的段意味着要求更多的磁盘空间以及文件句柄,确保在你的节点上配置好充足的ample的文件句柄,见File Descriptors

      此外,如果一个段包含已删除或更新的文档,那么PIT必须跟踪段中的每个文档在初始化搜索请求时是否是live的(没有被删除)。如果你的节点上在某个索引上有很多PIT并且不管的有删除或者更新操作,保证节点上有足够的磁盘空间。注意的是PIT不会阻止它关联的索引被删除。

      你可以使用nodes stats API目前打开了多少个PIT。

    Close point in time API

      keep_alive过期后,PIT会自动的关闭。基于上文中的介绍,保留PIT的开销是很大,当PIT不再需要用于查询时应该马上关闭它。

      上述调用返回下面的内容:

    1. 如果是true,PIT关联的所有search contexts都被成功关闭了

    2. 成功关闭的search contexts的数量

    Search slicing

      当分页查询一个较大数据集时,可以切分成多次查询来消费数据集切分后的数据集。

    1. id是切分编号

    2. 切分后的数据子集数量

      第一个请求的结果返回属于第一个片的文档(id: 0),第二个请求的结果返回属于第二个片的文档。由于切片的最大数量被设置为2,所以这两个请求的结果的并集等价于没有切片的时间点搜索的结果。默认情况下,首先在分片上进行分割,然后在每个分片上进行本地分割。本地分割基于Lucene的文档id将分片划分为连续的范围。

      例如,如果分片的数量等于2,用户请求了4个切片,那么切片0和切片2被分配给第一个分片,切片1和切片3被分配给第二个分片。

    IMPORTANT:应该对所有片使用相同的时间点ID。如果使用不同的PIT id,则片可能会重叠和遗漏文档。这是因为拆分标准是基于Lucene文档id的,这些文档id在索引更改时变的不稳定。

    Search template API

    (8.2)link

      使用search template运行一个查询。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body

    Multi search template API

    (8.2)link

      使用单个请求执行多个templated searches

    Request
    Prerequisites
    Query parameters
    Request body

      请求体必须是按照以下格式的换行符分隔的 JSON(NDJSON):

      每一个headerbody对代表一次查询请求。

      The<header> supports the same parameters as the multi search API's <header>. The<body> supports the same parameters as the search template API's request body.

    Response codes

      如果请求自身出错则返回400。如果请求中一个或多个查询失败了,接口返回200并且在响应中包含一个error对象描述每一个错误。

    Response body
    curl requests

      如果提供了文本文件或者文本输入通过curl执行,使用--data-binary而不是-d防止newlines。

    Render search template API

    (8.2)link

      渲染一个search template为查询的request body

    Request
    Prerequisites

      如果开启了Elasticsearch security features,你必须在至少一个index pattern上有readindex privilege

    Path parameters
    Request body

    Search shards API

    link

    Suggesters

    link

    Completion Suggester

    Multi search API

    link

    Validate API

    link

      

    Request
    Prerequisites
    Description
    Path parameters
    Query parameters
    Response body
    Example

    Profile API

    link

    Field capabilities API

    link

    Vector tile search API

    link

    Searchable snapshots APIs

    (8.2)link

      你可以使用下面的API执行searchable snapshots的操作。

    Mount snapshot API

    (8.2)link

      挂载一个快照使其成为一个searchable snapshot index。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body
    Example

      从名为my_repository的快照仓库中挂载一个现有的名为my_snapshot的快照中的名为my_docs的索引。

      第3行,挂载的快照中的索引名称   第4行,待创建的索引名称   第5行,添加到新的索引的settings   第8行,挂载快照中的索引后,需要移除这个索引的settings

    Cache stats API

    (8.2)link

      partially mounted indices获取关于shared cache的统计信息。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Example

      从所有节点中为partially mounted indices获取shared cache的统计信息:

      响应如下:

    Searchable snapshot statistics API

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束.

      获取searchable snapshots的统计信息。

    Request
    Prerequisites
    Path parameters
    Example

      获取名为my-index的索引的统计信息:

    Clear cache API

    (8.2)link

    WARNING:这个功能目前处于技术预览阶段,未来的版本中可能会进行更改或移除。Elastic会努力修复任何问题,但是技术预览中的功能不受官方正式发布(GA)功能的支持服务级别协议(SLA)约束.

      partially mounted indices清除shared cache中的indices和data streams。

    Request
    Prerequisites
    Path parameters
    Example

      清除名为my-index的缓存:

    Security APIs

    link

      

    Request
    Prerequisites
    Description
    Path parameters
    Query parameters
    Response body
    Example

    Role mappings

    link

    Snapshot and restore APIs

    (8.2)link

      你可以使用下面的APIs来设置快照仓库、管理快照备份以及将快照回到一个运行中的集群中。

      更多信息见Snapshot and restore

    Snapshot repository management APIs
    Snapshot management APIs

    Create or update snapshot repository API

    (8.2)link

      注册或更新一个snapshot repository

    Request
    Prerequisites
    Path parameters
    Query parameter

    IMPORTANT:这个API的有些选项可以通过请求参数(query parameter)或者请求体(query body)指定。如果同时指定了,那么只会使用请求参数。

    Request body

    Verify snapshot repository API

    (8.2)link

      验证某个快照仓库是否功能正常。见Verify a repository

    Request
    Prerequisites
    Query parameters
    Response bdy

    Repository analysis API

    link

    Get snapshot repository API

    (8.2)link

      获取关于一个或多个已注册的snapshot repositories信息。

    Request
    Prerequisites
    Path parameters
    Query parameters
    Response body
    Examples

      这个API返回下面的响应:

    Delete snapshot repository API

    (8.2)link

      注销一个或多个snapshot repositories

      当快照仓库注销后,Elasticsearch只是移除了对该位置的引用,这个仓库仍然存放着快照。快照本身保持不变,且位置不动。

    Request
    Prerequisites
    Path parameters
    Query parameters

    Clean up snapshot repository API

    (8.2)link

      触发对快照仓库的审查并且删除不会现有快照引用的陈旧数据。见Clean up a repository

    Request
    Prerequisites
    Query parameters
    Response body
    Example

      这个API返回下面的响应:

    Clone snapshot API

    link

    Create snapshot API

    (8.2)link

      指定data stream和Index生成一个快照。见take a snapshot

    Request
    Prerequisites
    Path parameters
    Query parameters
    Request body
    Examples

      下面的请求创建了包含index_1index_2的快照。

      这个API返回下面的响应:

    Get snapshot API

    (8.2)link

      获取一个或多个快照的信息。

    Request
    Prerequisites
    Path parameters

    NOTE:所有存在不可用的快照,使用_all的请求会失败。将ignore_unavailable(见下文中的请求参数)设置为true来返回可见的快照。

    Query parameters

    NOTE:after参数和next字段允许在迭代快照时提供一些关于快照的并发创建或删除的一致性保证。它保证了任何在迭代开始时存在且未被并发删除的快照将在迭代过程中被看到。在迭代过程中可能会看到并发创建的快照。

    NOTE:当参数verbose为false时,size, order, after, from_sort_value, offset, slm_policy_filter 以及 sort参数将不被支持。且verbose=false的请求的排序顺序是未定义的。

    Response body
    Example

      下面的请求返回了快照仓库my_repository中名为snapshot_2的快照

      这个API返回下面的响应:

      下面的请求返回了快照仓库my_repository中快照名以snapshot开头的快照。

      这个API返回下面的响应:

      接下里的请求来获取剩余的快照(上一个请求中remaining的值为1,说明没有返回所有的快照),使用上面响应中next的值作为下一次请求参数after的值。

      这个API返回下面的响应:

      获取使用偏移值2来跳过已经获取的两个快照也能获取相同的结果。

      这个API返回下面的响应:

      下面的请求返回了快照仓库my_repository中快照名以snapshot开头的快照,除了名为snapshot_3的快照。

      这个API返回下面的响应:

      当使用默认的升序,并且按照快照名称排序,下面的请求返回了在snapshot_2之后的所有快照:

      这个API返回下面的响应:

      当使用默认的升序,并且按照快照处理的开始时间排序,下面的请求返回了快照名以snapshot_开头并且快照处理的开始时间在1577833200000(Jan 1st 2020) 之后(包含)的所有快照:

      这个API返回下面的响应:

    Get snapshot status API

    (8.2)link

      获取快照中每一个分片当前状态的详细描述。

    Request
    Prerequisites
    Description

      使用这个API来获取快照中每一个分片当前状态的详细描述。

      如果你忽略<snapshot>这个请求参数,那么请求只会获取当前运行中的快照的信息。推介这种方式。

      如果有需要,你可以指定<repository><snapshot>来获取指定快照的信息,即使它们不在运行中。

    WARNING:使用这个API获取任意的快照比获取当前运行中的快照需要的开销更高。这个API会读取快照仓库中每一个快照的每一个分片。例如,如果你有100个快照,每个快照有1000个分片。那么这个API请求读取所有快照时会要求100000次读取(100 snapshots * 1000 shards) 基于你存储介质的延迟,这种请求可能会需要相当长的时间才能返回。这些请求还可能消耗机器资源,并且在使用云存储时,可能会产生高昂的处理成本

    Path parameters
    Query parameters
    Response body
    Example

      下面的请求返回快照仓库myZ_repository中名为snapshot_2的快照中详细的状态信息。响应中相比较Get snapshot API,包含额外的信息,比如分片状态跟文件统计。

    Restore snapshot API

    link

      恢复集群或者data streams和indices的某个snapshot

    Request
    Prerequisites

      如果没有这样的模板,你可以create one或者restore a cluster state,其中包含了这样的模板。没有一个匹配的索引模板,data stream无法roll over或者创建backing indices

    Path parameters
    Query parameters
    Request body

    Delete snapshot API

    (8.2)link

      删除一个snapshot

    Request
    Prerequisites
    Path parameters
    Example

      下面的请求删除了快照仓库my_repository中名为snapshot_2snapshot_3的两个快照

      上面的API返回以下响应:

    Snapshot lifecycle management APIs

    (8.2)link

      你可以使用下面的API设置策略来自动的生成快照并且控制保留时间。

      更多关于snapshot lifecycle management(SLM)的信息见Automate snapshots with SLM

    Policy management APIs
    Snapshot management APIs
    Operation management APIs

    Create or update snapshot lifecycle policy API

    (8.2)link

      创建或者更新一个snapshot lifecycle policy。

    Request
    Prerequisites
    Description

      create or update snapshot lifecycle policy API用来创建或更新一个snapshot lifecycle policy。

      如果策略已存在,这个请求会更新策略的版本。只有最新的策略才会被存储。

    Path parameters
    Query parameters
    Request body
    Example

      创建一个名为daily-snapshots的生命周期策略:

      第3行,生成快照的时间,在这个例子中是每天的1:30am   第4行,每一个快照给定的名称   第5行,存储快照的仓库   第6行,额外的快照配置   第7行,快照中包含的data streams和indices   第11行,可选的保留快照的配置   第12行,快照保留30天   第13行,总是至少保留最新的5个状态为成功的快照,即使快照30天才过期   第14行,最多保留不超过50个状态为成功的快照,即使快照30天才过期

    Get snapshot lifecycle policy API

    (8.2)link

      获取一个或者多个snapshot lifecycle policy 的定义以及l最新尝试创建快照成功和失败的信息。

    Request
    Prerequisites
    Description

      返回指定策略的定义以及最新尝试创建快照成功和失败的信息。

    Path parameters
    Examples
    Get a specific policy

      获取名为daily-snapshots的策略:

      这个请求返回以下响应:

      第3行,快照策略的版本号,只有最新版本的策略才会被存储,每次更新策略会增加这个版本号的值   第4行,上一次策略更改的时间   第28行,下一次策略执行的时间

    Get all policy

    Delete snapshot lifecycle policy API

    (8.2)link

      删除一个现有的snapshot lifecycle policy

    Request
    Prerequisites
    Description

      删除指定的生命周期策略定义。可以防止新快照的生成,但是不会取消正在进行中的任务,不会移除之前生成的快照。

    Path parameters
    Examples

    Execute snapshot lifecycle policy API

    (8.2)link

      不等待定时计划时间,立即根据生命周期策略生成一个快照。

    Request
    Prerequisites
    Description

      手动应用快照策略,立即创建一个快照。快照策略通常根据定时计划时间,但是你可能想要手动的,在执行一次升级或者其他维护之前执行一个策略。

    Path parameters
    Example

      若要根据名为daily-snapshots的策略立即生成一个快照:

      如果成功了,请求会返回生成的快照名:

      快照在后台生成。你可以使用snapshot APIs或者monitor the status of the snapshot来观察快照生成状态。

      若要查看某个策略对应的最新的快照,你可以使用get snapshot lifecycle policy API

    Execute snapshot retention policy API

    (8.2)link

      根据策略的保留规则,删除过期的快照。

    Request
    Prerequisites
    Description

      手动应用保留策略来强制立即移除过期的快照。保留策略通常根据定时计划时间执行。

    Examples

      若要强制移除过期的快照:

      该操作在后台异步运行。

    Get snapshot lifecycle management status API

    (8.2)link

      获取snapshot lifecycle management (SLM)的状态

    Request
    Description

      返回SLM插件的状态。响应中的operation_mode字段展示了三种状态之一:RUNNING STOPPING STOPPED。可以使用stopstart API来分别暂定以及重启SLM插件。

    Query parameters
    Prerequisites
    Examples

      这个请求返回以下结果:

    Get snapshot lifecycle stats API

    (8.2)link

      返回全局的以及策略层级的由SLM(snapshot lifecycle management)执行的动作(操作)的统计信息。

    Request
    Prerequisites
    Examples

      这个请求返回以下响应:

    Start snapshot lifecycle management API

    (8.2)link

      开启snapshot lifecycle management (SLM)。

    Request
    Prerequisites
    Description

      如果SLM插件不在运行中,则启动。当形成集群后,SLM会自动开始。只有通过使用Stop snapshot lifecycle management停止SLM插件后,才有手动启动SLM的必要。

    Query parameters
    Examples

      启动SLM插件:

      如果启动成功,请求返回如下内容:

    Stop snapshot lifecycle management API

    (8.2)link

      关闭snapshot lifecycle management (SLM)。

    Request
    Prerequisites
    Description

      暂停所有的snapshot lifecycle management (SLM)的操作并且停止SLM插件。当你想要对集群进行维护并且需要防止SLM对你的data streams和indices执行任何操作时是非常有用的。停止SLM不会停止处理中的快照。即使SLM已经停止了,你可以通过Execute snapshot lifecycle policy手动的触发快照的生成。

      请求再被确认后会马上返回一个响应,但是在处理中的操作完成并且正确的被停止前,插件可能仍然在运行。

      使用Get snapshot lifecycle management status查看SLM是否运行中。

    Query parameters
    Examples

    SQL APIs

    link

    Request
    Prerequisites
    Query parameters
    Description
    Examples

    SQL search API

    link

    Transform APIs

    link

    Create transform API

    link

    Delete transform API

    link

    Get transforms API

    link

    Create API key API

    link

    Create or update role mappings API

    link

    Create or update roles API

    link

      

    Request
    Prerequisites
    Description
    Path parameters
    Query parameters
    Response body
    Example

    Get transform statistics API

    link

    Preview transform API

    link

    Reset transform API

    link

    Start transform API

    link

    Stop transforms API

    link

    Update transform API

    link

    Cross-cluster search, clients, and integrations

    link

    Adding and removing nodes

    (8.2)link

      Add and remove nodes in your cluster

    Avoid oversharding

    (8.2)link

      Size your shards

    Configure TLS

    (8.2)link

    Encrypt internode communication-1

      Encrypt internode communication

    Cluster-level shard allocation filtering-1

    (8.2)link

      Cluster-level shard allocation filtering

    Cluster-level shard allocation

    (8.2)link

      Cluster-level shard allocation settings

    Cron expressions-1

    (8.2)link

      Cron expressions

    Dangling indices-1

    (8.2)link

      Dangling indices

    Date math support in system and index alias names-1

    (8.2)link

      Date math support in index and index alias names

    fielddata mapping parameter-1

    (8.2)link

      fielddata mapping parameter

    Full cluster restart upgrade

    (8.2)link

      当Elasticsearch升级到8.0或者更高版本时,你必须先升级到7.17,即使你优先执行一个full-cluster restart而不是rolling upgrade。更多关于upgrade的信息见Upgrading to Elastic 8.2.3

    Grok basics

    (8.2)link

      Grokking grok

    Create users

      参考elasticsearch-reset-password 工具来为内置的用户重置密码。

    Manage existing periodic indices with ILM

    (8.2)link

      Apply policies to existing time series indices

    Multi-target syntax-1

    (8.2)link

      Multi-target syntax

    Hidden data streams and indices-1

      Hidden data streams and indices

    Request body search-1

    link

    Stored fields-1

      Stored fields

    Snapshot module-1

    (8.2)link

      Snapshot and restore

    Stored scripts-1

    (8.2)link

      Store and retrieve scripts

    Repository plugins

      Self-managed repository types.

    Rescoring parameter for request body search API-1

      Rescore filtered search results

    Change index settings during restore

      Request body

    Shard allocation awareness-1

    link

      Shard allocation awareness