在Elasticsearch的说法中,文档是序列化的JSON数据。在典型的ELK设置中,当您发送日志或度量标准时,它通常会发送到Logstash,Logstash按照Logstash配置的定义进行格式化,变异处理和以其他方式处理数据。生成的JSON在Elasticsearch中编制索引。
Elasticsearch文档位于分片的一部分中,该分片也是Lucene索引。随着附加文件的发布,细分市场也在增长。每当执行搜索时,Elasticsearch都会检查存储在分片中的每个段。这意味着随着细分市场数量的增长,搜索变得越来越低效。为了解决这个问题,Elasticsearch会定期将类似大小的片段合并为一个更大的片段,并删除原始的较小片段。
细分是不可变的,这对文档具有重要意义。最初删除文档时,实际上不会立即从Elasticsearch中删除它。相反,它被标记为已删除,使用户无法访问,但仍在该段中。在段合并期间,标记为已删除的文档不会写入新段,因此段合并实际上是从Elasticsearch中删除已删除的文档时。段不变性还意味着文档更新的功能相同:当文档“更新”时,它实际上被标记为已删除并替换为具有适当字段更改的新文档。就像被标记为完全删除的文档一样,仅当Elasticsearch执行段合并时才会删除这些文档。
Elasticsearch的API允许您单独和批量创建,获取,更新,删除和索引文档(取决于端点)。虽然自Elasticsearch 2.x以来,与单个文档的交互几乎没有变化,但Elasticsearch 6.x的发布增加了通过查询删除和更新的功能,以及改进以前非常手动的重建索引过程。下面为每个端点提供了一些常规示例,但是如果您想查看更多示例和端点的完整列表,请查看Elasticsearch API文档。
curl -XGET '<your_elasticesarch_uri> / <index> / <type> / <doc_id>?pretty'
curl -XDELETE '<your_elasticesarch_uri> / <index> / <type> / <doc_id>?pretty'
curl -XPUT '<your_elasticesarch_uri>/<index>/<type>/<doc_id>?pretty' -H 'Content-Type: application/json' -d'
{
"field : "value",
...
}
'
curl -XPOST '<your_elasticesarch_uri>/<index>/<type>/<doc_id>/_update' -H 'Content-Type: application/json' -d'
{
"field : "new_value",
...
}
'
如果要按顺序更新多个文档而某些文档存在而某些文档不存在,则需要使用 doc_as_upsert
设置为true的_update
端点。如果文档不存在,这将创建文档,如果文档不存在则更新。
_mget
允许您根据索引,类型或ID检索多个文档。例如,要检索特定类型的文档:
curl -X GET '<your_elasticesarch_uri>/<index>/<type>/_mget' -H 'Content-Type: application/json' -d'
{
"docs" : [
{
"_id" : "1"
},
...
]
}
'
_bulk
允许您在一次调用中发布多个创建,更新,删除等请求。要执行这些操作,您仍需要为每个请求包含完整的JSON。例如:
curl -X POST "<your_elasticsearch_uri>/_bulk" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "<index>", "_type" : "<type>", "_id" : "<first_id>" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "<index>", "_type" : "<type>", "_id" : "<second_id>" } }
'
_update_by_query
完全符合您的期望:允许您更改与给定查询匹配的文档中的数据。由于您将一次使用一个查询,因此您使用漂亮的打印。(旁注:你将能够使用相当既打印 _delete_by_query
也打印 _reindex
)。这个查询有很多选项可供使用,所以更准确的例子就是说你一直在跟踪月食数据,现在想要添加日食。由于到目前为止你只跟踪一种类型的日食,或许你将月蚀数据简单地标记为“日食”,所以现在你要将“eclipse”更新为“lunar_eclipse”(并且传入的数据将被标记为“solar_eclipse”) “ 作为适当的)。这看起来像什么?
curl -XPOST '<elasticesarch_uri>/<index>/_update_by_query?pretty' -d '{
"query": {
"match": {
"phenomenon": "eclipse"
}
},
"script": {
"lang": "painless",
"inline": "ctx._source.phenomenon = 'lunar_eclipse'"
}
}'
为了解决这个问题,脚本正在更改与特定值匹配的现有字段的值。脚本还可用于修改字段或执行更复杂的操作,例如,如果要添加具有默认值的不存在的字段,然后根据一系列条件更新现有值。
最后一个小问题:当您通过查询更新(或删除)时,Elasticsearch会在进行任何修改之前获取并使用索引所处状态的初始快照。如果索引在该快照之后发生更改,则通常的示例是在快照之后但在操作结束之前将附加数据写入索引,那么您将遇到冲突。重要的是要了解在运行更新(或删除)时遇到的冲突,以了解这些冲突是否需要手动解决。在后一种情况下,您可以将“冲突”设置为“继续”。这将计算冲突,但不会更新(或删除)冲突的文档或停止更新(删除)过程:
curl -XPOST '< elasticesarch_uri > / <index> / _ update_by_query?pretty&conflicts = proceed'
继续,查询删除的语法与查询更新非常相似。所以继续上面的例子,如果你想删除所有的eclipse数据(不要这样做!)你会做这样的事情:
curl -XPOST '<elasticesarch_uri>/<index>/_delete_by_query?pretty -d '{
"query": {
"match": {
"phenomenon": "eclipse"
}
},
如果您需要更改映射(下面讨论),分片计数,分片大小等,则需要重新编制群集索引。使用reindex API,这实际上非常简单:
curl -XPOST '<your_elasticesarch_uri>/_reindex' -d '{
"source": {
"index": "original-index"
},
"dest": {
"index": "new-index"
}
}'
当我谈论重建索引映射时,下面将包含相同的代码块。为什么要把它放两次?因为它很重要。Grok吧!
为了构建搜索文档,Elasticsearch依赖于映射。映射可以由用户定义,并且根据用例,可以从简单到极其复杂。
重要提示:在2018年,Elasticsearch开始实施更改,目标是删除映射类型。
Elasticsearch用户在映射文档后遇到的最常见问题是映射冲突。当映射值在同一索引中具有不同类型时,会发生映射冲突。这是怎么发生的?事实证明,映射冲突通常出于以下两个原因之一:
在定义映射时,重要的是要知道,当您作为用户可以在逻辑上分离Elasticsearch没有的字段A.response和B.response。因此,如果A.response被定义为整数,例如HTTP响应代码,并且B.response被定义为字符串,例如响应消息文本,则响应字段具有映射冲突。
映射的一个难点是,它要求您作为Elasticsearch管理员/架构师有点先见之明,并且在发送数据之前知道您的字段定义是什么。因此,当您定义映射时,您需要已经知道您的字段定义。这是一个很高的订单,特别是因为更改需求经常导致发送到Elasticsearch的数据发生更改 - 因此需要您更新映射。那么,如果您需要将先前定义为整数的字段更新为字符串,会发生什么?你猜对了:映射冲突。
那么如何解决这些映射冲突呢?重新编制。在后一种情况下,您应该在需要更新现有字段定义时重新索引数据。为什么?引用Elasticsearch:
“为了使您的数据可搜索,您的数据库需要知道每个字段包含哪些类型的数据以及如何将其编入索引。如果您将字段类型从例如字符串切换到日期,则该字段的所有数据都是你已经索引变得无用。不管怎样,你需要重新索引那个字段。“
虽然最初是一个非常手动的过程,如引用的Elastic博客文章中所述,随着版本2.3的发布,Elastic添加了 _reindex
API端点,大大简化了过程。如果您在2.3之后运行Elasticsearch的版本,而不是所描述的手动过程,您需要做的就是将原始(源)和新(目标)索引传递给 _reindex
端点。请注意,要重新索引,您需要使用新名称创建新索引 - 您无法将文档重新索引到与原始名称相同的新索引中。
curl -XPOST '<your_elasticesarch_uri>/_reindex' -d '{
"source": {
"index": "original-index"
},
"dest": {
"index": "new-index"
}
}'
还有一种常见的映射错误类型:映射解析器异常。直截了当地说,这意味着Elasticsearch无法解析JSON,因为它已经定义了JSON。导致此问题的两个常见原因是要么发送无效的JSON请求,要么已配置Logstash,以使得生成的JSON与映射定义所期望的不匹配。在任何一种情况下,异常文本都提供了错误原因的指南。例如,有人在Stack Overflow上发布了以下内容:
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "object mapping for [comments.comment] tried to parse field [comment] as object, but found a concrete value"
}
],
"type": "mapper_parsing_exception",
"reason": "object mapping for [comments.comment] tried to parse field [comment] as object, but found a concrete value"
},
"status": 400
}
在这个用户的情况下,正如响应者指出的那样,他们发送了无效的JSON。
在Logz.io,我们非常重视安全性。我们通过及时了解各种安全标准的最新要求来保护用户的数据。如果您托管自己的Elasticsearch集群,则需要确保您的数据安全,符合相关监管机构提出的标准。首先,您应该使用X-Pack配置适用的文档和字段级访问规则。
原文标题《Elasticsearch Documents and Mappings》
译者:February
不代表云加社区观点,更多详情请查看原文链接
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系外文翻译,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。