_source 字段编辑

_source 字段包含在索引时传递的原始 JSON 文档正文。 _source 字段本身未编入索引(因此不可搜索),但它会被存储,以便在执行 *fetch* 请求时可以返回,例如 获取搜索

如果磁盘使用量对您很重要,请查看 合成 _source,它以仅支持映射子集和较慢的提取为代价来减少磁盘使用量,或者(不推荐)禁用 _source 字段,这也会减少磁盘使用量,但会禁用许多功能。

合成 _source编辑

合成 _source 仅适用于 TSDB 索引(index.mode 设置为 time_series 的索引)。 对于其他索引,合成 _source 处于技术预览阶段。 技术预览版中的功能可能会在未来版本中更改或删除。 Elastic 将努力解决任何问题,但技术预览版中的功能不受官方 GA 功能的支持 SLA 的约束。

虽然 source 字段非常方便,但它会占用大量的磁盘空间。 Elasticsearch 可以根据需要在检索时重建源内容,而不是完全按照您发送的方式将源文档存储在磁盘上。 通过在 _source 中设置 mode: synthetic 来启用此功能

response = client.indices.create(
  index: 'idx',
  body: {
    mappings: {
      _source: {
        mode: 'synthetic'
      }
    }
  }
)
puts response
PUT idx
{
  "mappings": {
    "_source": {
      "mode": "synthetic"
    }
  }
}

虽然这种动态重建通常比逐字保存源文档并在查询时加载它们要慢,但它节省了大量的存储空间。

合成 _source 限制编辑

有一些限制需要注意

合成 _source 修改编辑

启用合成 _source 后,与原始 JSON 相比,检索到的文档会 undergoes some modifications。

数组移动到叶字段编辑

合成 _source 数组被移动到叶子。 例如

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    foo: [
      {
        bar: 1
      },
      {
        bar: 2
      }
    ]
  }
)
puts response
PUT idx/_doc/1
{
  "foo": [
    {
      "bar": 1
    },
    {
      "bar": 2
    }
  ]
}

将变成

{
  "foo": {
    "bar": [1, 2]
  }
}

这可能会导致某些数组消失

response = client.index(
  index: 'idx',
  id: 1,
  body: {
    foo: [
      {
        bar: 1
      },
      {
        baz: 2
      }
    ]
  }
)
puts response
PUT idx/_doc/1
{
  "foo": [
    {
      "bar": 1
    },
    {
      "baz": 2
    }
  ]
}

将变成

{
  "foo": {
    "bar": 1,
    "baz": 2
  }
}
字段按其映射方式命名编辑

合成源根据映射中的名称命名字段。 与 动态映射 一起使用时,默认情况下,名称中带有点 (.) 的字段会被解释为多个对象,而字段名称中的点会保留在已禁用 子对象 的对象中。 例如

PUT idx/_doc/1
{
  "foo.bar.baz": 1
}

将变成

{
  "foo": {
    "bar": {
      "baz": 1
    }
  }
}
按字母顺序排序编辑

合成 _source 字段按字母顺序排序。 JSON RFC 将对象定义为“零个或多个名称/值对的无序集合”,因此应用程序不应该关心,但在没有合成 _source 的情况下,原始顺序会保留,并且某些应用程序可能会违反规范,对该顺序做一些事情。

禁用 _source 字段编辑

虽然 source 字段非常方便,但它确实会在索引中产生存储开销。 因此,可以按如下方式禁用它

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      _source: {
        enabled: false
      }
    }
  }
)
puts response
PUT my-index-000001
{
  "mappings": {
    "_source": {
      "enabled": false
    }
  }
}

在禁用 _source 字段之前请三思

用户经常不假思索地禁用 _source 字段,然后后悔莫及。 如果 _source 字段不可用,则不支持许多功能

  • 更新update_by_query重新索引 API。
  • 在 Kibana 发现 应用程序中,不会显示字段数据。
  • 动态 突出显示
  • 能够从一个 Elasticsearch 索引重新索引到另一个索引,无论是更改映射还是分析,还是将索引升级到新的主版本。
  • 通过查看索引时使用的原始文档来调试查询或聚合的能力。
  • 将来可能会自动修复索引损坏的能力。

如果磁盘空间是一个问题,请增加 压缩级别,而不是禁用 _source

包含/排除 _source 中的字段编辑

一项仅限专家使用的功能是能够在索引文档后但在存储 _source 字段之前修剪 _source 字段的内容。

_source 中删除字段与禁用 _source 有类似的缺点,尤其是您无法将文档从一个 Elasticsearch 索引重新索引到另一个索引。 请考虑改用 源过滤

includes/excludes 参数(也接受通配符)可以按如下方式使用

response = client.indices.create(
  index: 'logs',
  body: {
    mappings: {
      _source: {
        includes: [
          '*.count',
          'meta.*'
        ],
        excludes: [
          'meta.description',
          'meta.other.*'
        ]
      }
    }
  }
)
puts response

response = client.index(
  index: 'logs',
  id: 1,
  body: {
    requests: {
      count: 10,
      foo: 'bar'
    },
    meta: {
      name: 'Some metric',
      description: 'Some metric description',
      other: {
        foo: 'one',
        baz: 'two'
      }
    }
  }
)
puts response

response = client.search(
  index: 'logs',
  body: {
    query: {
      match: {
        'meta.other.foo' => 'one'
      }
    }
  }
)
puts response
PUT logs
{
  "mappings": {
    "_source": {
      "includes": [
        "*.count",
        "meta.*"
      ],
      "excludes": [
        "meta.description",
        "meta.other.*"
      ]
    }
  }
}

PUT logs/_doc/1
{
  "requests": {
    "count": 10,
    "foo": "bar" 
  },
  "meta": {
    "name": "Some metric",
    "description": "Some metric description", 
    "other": {
      "foo": "one", 
      "baz": "two" 
    }
  }
}

GET logs/_search
{
  "query": {
    "match": {
      "meta.other.foo": "one" 
    }
  }
}

这些字段将从存储的 _source 字段中删除。

我们仍然可以搜索此字段,即使它不在存储的 _source 中。