在 Elasticsearch 的说法中, 文档是序列化的 JSON 数据。在典型的麋鹿设置中, 当您发运日志或指标时, 通常会将其发送到 Logstash, groks、突变或以其他方式处理数据 (由 Logstash 配置定义)。生成的 JSON 在 Elasticsearch 中编入索引。

Elasticsearch 文档生活在分片的一段中, 这也是一个 Lucene 索引。随着附加文档的发运, 这些细分将会增长。每次执行搜索时, Elasticsearch 都会检查存储在分片中的每个段。这意味着随着数量的增长, 搜索变得越来越低效。为此, Elasticsearch 将定期将类似大小的线段合并为单个、更大的线段, 并删除原始的、较小的线段。

段是不可变的, 这对文档具有重要意义。最初删除文档时, 它实际上不会立即从 Elasticsearch 中删除。相反, 它被标记为已删除, 使其无法访问用户, 但仍在段中。在段合并期间, 标记为已删除的文档不会写入新段, 因此, 在从 Elasticsearch 删除文档时, 段合并实际上是。段不变性还意味着文档更新的功能方式相同: 当文档 “更新” 时, 它实际上被标记为已删除, 并替换为具有相应字段更改的新文档。就像标记为完全删除的文档一样, 只有当 Elasticsearch 执行段合并时, 才会删除这些文档。

通过 API 的文档

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", 
   ... 
} 
'

如果您正在按顺序更新多个文档, 并且某些文件存在, 而有些则没有, 则您将希望使用 _update doc_as_upsert 设置为 true 的终结点。这将创建文档, 如果它不存在和更新, 如果它。

多个文档

多获取

_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”, 所以现在你要更新 “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"
 }
 },

重新索引

如果您需要更改映射 (下面讨论)、分片计数、分片大小等, 则需要重新编制群集的索引。使用重新索引的 API, 这实际上相当简单:

curl -XPOST '<your_elasticesarch_uri>/_reindex' -d '{
  "source": {
    "index": "original-index"
  },
  "dest": {
    "index": "new-index"
  }
}'

当我谈到重建索引映射时, 将包含相同的代码块。为什么要放两次?因为这很重要映射可以是用户定义的, 并且根据用例的不同, 可以从简单到极其复杂。要深入了解如何创建映射, 请查看我们早期的Elasticsearch 映射博客文章。重要警告: 在 2018年, Elasticsearch 开始实施更改, 目标是删除映射类型。有关详细信息, 请参阅我们的博客文章, 了解今年年初删除映射类型的情况。

答复朦胧: 映射不清楚时

Elasticsearch 用户在映射文档后遇到的最常见问题是映射冲突。当映射值在同一索引中具有不同类型时, 将发生映射冲突。这是怎么发生的?事实证明, 映射冲突通常是由于以下两个原因之一引起的:

#1: 同名, 不同类型

定义映射时, 神交重要的是, 当用户可以在逻辑上分隔字段 a. 响应和 B. 响应, Elasticsearch 不。因此, 如果 A. 响应定义为整数, 例如 HTTP 响应代码和 B. 响应定义为字符串, 例如响应消息文本, 则响应字段具有映射冲突。

#2: 更新的字段定义, 相同的索引

映射的难点之一是, 它要求您作为一个 Elasticsearch 管理员/架构师有点先见之明, 并知道您的字段定义是什么之前发送您的数据。因此, 在定义映射时, 需要已经知道字段定义。这是一个很高的顺序, 特别是因为不断变化的需求会导致对 Elasticsearch 的数据进行更改, 从而要求您更新映射。如果需要更新以前定义为字符串的整数的字段, 会发生什么情况?你猜到了: 映射冲突。

那么, 如何解决这些映射冲突呢?重新索引.在后一种情况下, 每当需要更新现有字段定义时, 都应期望重新索引数据。为什么?要引用 Elasticsearch:

为了使数据可搜索, 数据库需要知道每个字段包含的数据类型以及应如何对其进行索引。如果将字段类型从例如字符串切换到日期, 则已编入索引的字段的所有数据都将变得无用。无论是哪种方式, 您都需要重新索引该字段。()

虽然最初是一个漂亮的手动过程, 如参考的弹性博客文章中所述, 版本2.3 的版本, 弹性增加了 _reindex API 终结点, 大大简化了该过程。如果您在2.3 之后运行 Elasticsearch 版本, 而不是所描述的手动过程, 则只需将原始 (源) 和新 (目标) 索引传递到 _reindex 终结点。请注意, 对于重新索引, 您需要使用新名称创建新索引-不能将文档重新索引到与原始名称同名的新索引中。

curl -XPOST '<your_elasticesarch_uri>/_reindex' -d '{
  "source": {
    "index": "original-index"
  },
  "dest": {
    "index": "new-index"
  }
}'

异常、异常、异常

还有一个常见的映射错误类型: 映射分析器异常。直截了当的说, 这意味着 Elasticsearch 无法解析 JSON, 因为它是根据您定义的映射到达的。这两个常见的原因是, 正在发送无效的 json 请求或 Logstash 已配置, 这样生成的 json 与映射定义所期望的内容不匹配例如, 有人在堆栈溢出上发布了以下内容:

{
   "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 我们非常认真地对待安全。我们通过及时更新各种安全标准的最新要求来保护用户的数据。如果您正在托管您自己的 Elasticsearch 集群, 您将需要确保您的数据在遵守相关监管机构提出的标准时保持安全。若要开始, 应使用 X 包配置文档和字段级访问规则(如适用)。在未来的博客文章中, 我们将深入了解一系列安全主题, 以帮助您保护 Elasticsearch 群集。

Comments are closed.