从搜索中检索选定字段

编辑

默认情况下,搜索响应中的每个命中都包含文档的 _source,它是索引文档时提供的整个 JSON 对象。有两种推荐的方法可以从搜索查询中检索选定字段

  • 使用 fields 选项提取索引映射中存在的字段的值
  • 如果您需要访问索引时传递的原始数据,请使用 _source 选项

您可以同时使用这两种方法,尽管首选 fields 选项,因为它会同时参考文档数据和索引映射。在某些情况下,您可能需要使用其他方法来检索数据。

fields 选项

编辑

要检索搜索响应中的特定字段,请使用 fields 参数。因为 fields 参数会参考索引映射,所以它比直接引用 _source 具有几个优点。具体来说,fields 参数:

其他映射选项也受到尊重,包括ignore_aboveignore_malformednull_value

fields 选项返回的值与 Elasticsearch 索引它们的方式相匹配。对于标准字段,这意味着 fields 选项会在 _source 中查找值,然后使用映射对其进行解析和格式化。跳过在 _source 中找不到的选定字段。

检索特定字段
编辑

以下搜索请求使用 fields 参数检索 user.id 字段、所有以 http.response. 开头的字段以及 @timestamp 字段的值。

使用对象表示法,您可以传递一个 format 参数来自定义返回的日期或地理空间值的格式。

resp = client.search(
    index="my-index-000001",
    query={
        "match": {
            "user.id": "kimchy"
        }
    },
    fields=[
        "user.id",
        "http.response.*",
        {
            "field": "@timestamp",
            "format": "epoch_millis"
        }
    ],
    source=False,
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      match: {
        'user.id' => 'kimchy'
      }
    },
    fields: [
      'user.id',
      'http.response.*',
      {
        field: '@timestamp',
        format: 'epoch_millis'
      }
    ],
    _source: false
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  query: {
    match: {
      "user.id": "kimchy",
    },
  },
  fields: [
    "user.id",
    "http.response.*",
    {
      field: "@timestamp",
      format: "epoch_millis",
    },
  ],
  _source: false,
});
console.log(response);
POST my-index-000001/_search
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "fields": [
    "user.id",
    "http.response.*",         
    {
      "field": "@timestamp",
      "format": "epoch_millis" 
    }
  ],
  "_source": false
}

接受完整字段名称和通配符模式。

使用 format 参数为字段的值应用自定义格式。

默认情况下,当请求的 fields 选项使用像 * 这样的通配符模式时,不会返回诸如 _id_index 之类的文档元数据字段。但是,当使用字段名称明确请求时,可以检索 _id_routing_ignored_index_version 元数据字段。

响应始终返回数组
编辑

fields 响应始终为每个字段返回一个值数组,即使 _source 中只有一个值也是如此。这是因为 Elasticsearch 没有专门的数组类型,并且任何字段都可能包含多个值。fields 参数也不保证数组值以特定顺序返回。有关更多背景信息,请参阅有关数组的映射文档。

响应在每个命中的 fields 部分中包含一个平面列表形式的值。因为 fields 参数不会获取整个对象,所以只返回叶子字段。

{
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "0",
        "_score" : 1.0,
        "fields" : {
          "user.id" : [
            "kimchy"
          ],
          "@timestamp" : [
            "4098435132000"
          ],
          "http.response.bytes": [
            1070000
          ],
          "http.response.status_code": [
            200
          ]
        }
      }
    ]
  }
}
检索嵌套字段
编辑
详细信息

nested 字段fields 响应与常规对象字段的响应略有不同。虽然常规 object 字段内的叶子值以平面列表形式返回,但 nested 字段内的值会分组以保持原始嵌套数组中每个对象的独立性。对于嵌套字段数组中的每个条目,值再次以平面列表形式返回,除非父嵌套对象内部有其他 nested 字段,在这种情况下,对于更深的嵌套字段,会再次重复相同的过程。

给定以下映射,其中 user 是一个嵌套字段,在索引以下文档并检索 user 字段下的所有字段之后

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "properties": {
            "group": {
                "type": "keyword"
            },
            "user": {
                "type": "nested",
                "properties": {
                    "first": {
                        "type": "keyword"
                    },
                    "last": {
                        "type": "keyword"
                    }
                }
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    refresh=True,
    document={
        "group": "fans",
        "user": [
            {
                "first": "John",
                "last": "Smith"
            },
            {
                "first": "Alice",
                "last": "White"
            }
        ]
    },
)
print(resp1)

resp2 = client.search(
    index="my-index-000001",
    fields=[
        "*"
    ],
    source=False,
)
print(resp2)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        group: {
          type: 'keyword'
        },
        user: {
          type: 'nested',
          properties: {
            first: {
              type: 'keyword'
            },
            last: {
              type: 'keyword'
            }
          }
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  refresh: true,
  body: {
    group: 'fans',
    user: [
      {
        first: 'John',
        last: 'Smith'
      },
      {
        first: 'Alice',
        last: 'White'
      }
    ]
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    fields: [
      '*'
    ],
    _source: false
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    properties: {
      group: {
        type: "keyword",
      },
      user: {
        type: "nested",
        properties: {
          first: {
            type: "keyword",
          },
          last: {
            type: "keyword",
          },
        },
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  refresh: "true",
  document: {
    group: "fans",
    user: [
      {
        first: "John",
        last: "Smith",
      },
      {
        first: "Alice",
        last: "White",
      },
    ],
  },
});
console.log(response1);

const response2 = await client.search({
  index: "my-index-000001",
  fields: ["*"],
  _source: false,
});
console.log(response2);
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "group" : { "type" : "keyword" },
      "user": {
        "type": "nested",
        "properties": {
          "first" : { "type" : "keyword" },
          "last" : { "type" : "keyword" }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1?refresh=true
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

POST my-index-000001/_search
{
  "fields": ["*"],
  "_source": false
}

响应会将 firstlast 名称分组,而不是以平面列表形式返回它们。

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [{
      "_index": "my-index-000001",
      "_id": "1",
      "_score": 1.0,
      "fields": {
        "group" : ["fans"],
        "user": [{
            "first": ["John"],
            "last": ["Smith"]
          },
          {
            "first": ["Alice"],
            "last": ["White"]
          }
        ]
      }
    }]
  }
}

嵌套字段将按其嵌套路径分组,无论使用何种模式检索它们。例如,如果您仅从上一个示例中查询 user.first 字段

resp = client.search(
    index="my-index-000001",
    fields=[
        "user.first"
    ],
    source=False,
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    fields: [
      'user.first'
    ],
    _source: false
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  fields: ["user.first"],
  _source: false,
});
console.log(response);
POST my-index-000001/_search
{
  "fields": ["user.first"],
  "_source": false
}

响应仅返回用户的名字,但仍保持嵌套的 user 数组的结构

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [{
      "_index": "my-index-000001",
      "_id": "1",
      "_score": 1.0,
      "fields": {
        "user": [{
            "first": ["John"]
          },
          {
            "first": ["Alice"]
          }
        ]
      }
    }]
  }
}

但是,当 fields 模式直接以嵌套的 user 字段为目标时,不会返回任何值,因为该模式与任何叶子字段都不匹配。

检索未映射字段
编辑
详细信息

默认情况下,fields 参数仅返回映射字段的值。但是,Elasticsearch 允许在 _source 中存储未映射的字段,例如将动态字段映射设置为 false 或使用 enabled: false 的对象字段。这些选项会禁用对象内容的解析和索引。

要从 _source 中检索对象中的未映射字段,请使用 fields 部分中的 include_unmapped 选项

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "enabled": False
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    refresh=True,
    document={
        "user_id": "kimchy",
        "session_data": {
            "object": {
                "some_field": "some_value"
            }
        }
    },
)
print(resp1)

resp2 = client.search(
    index="my-index-000001",
    fields=[
        "user_id",
        {
            "field": "session_data.object.*",
            "include_unmapped": True
        }
    ],
    source=False,
)
print(resp2)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      enabled: false
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  refresh: true,
  body: {
    user_id: 'kimchy',
    session_data: {
      object: {
        some_field: 'some_value'
      }
    }
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    fields: [
      'user_id',
      {
        field: 'session_data.object.*',
        include_unmapped: true
      }
    ],
    _source: false
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    enabled: false,
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  refresh: "true",
  document: {
    user_id: "kimchy",
    session_data: {
      object: {
        some_field: "some_value",
      },
    },
  },
});
console.log(response1);

const response2 = await client.search({
  index: "my-index-000001",
  fields: [
    "user_id",
    {
      field: "session_data.object.*",
      include_unmapped: true,
    },
  ],
  _source: false,
});
console.log(response2);
PUT my-index-000001
{
  "mappings": {
    "enabled": false 
  }
}

PUT my-index-000001/_doc/1?refresh=true
{
  "user_id": "kimchy",
  "session_data": {
     "object": {
       "some_field": "some_value"
     }
   }
}

POST my-index-000001/_search
{
  "fields": [
    "user_id",
    {
      "field": "session_data.object.*",
      "include_unmapped" : true 
    }
  ],
  "_source": false
}

禁用所有映射。

包含与此字段模式匹配的未映射字段。

即使字段未映射,响应也会在 session_data.object.* 路径下包含字段结果。 user_id 字段也未映射,但它不会包含在响应中,因为该字段模式的 include_unmapped 未设置为 true

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "1",
        "_score" : 1.0,
        "fields" : {
          "session_data.object.some_field": [
            "some_value"
          ]
        }
      }
    ]
  }
}
忽略的字段值
编辑
详细信息

响应的 fields 部分仅返回索引时有效的值。如果您的搜索请求要求从一个字段中获取值,而该字段因格式错误或过大而忽略了某些值,则这些值将单独在 ignored_field_values 部分中返回。

在此示例中,我们索引一个具有被忽略的值的文档,该值未添加到索引中,因此在搜索结果中单独显示

resp = client.indices.create(
    index="my-index-000001",
    mappings={
        "properties": {
            "my-small": {
                "type": "keyword",
                "ignore_above": 2
            },
            "my-large": {
                "type": "keyword"
            }
        }
    },
)
print(resp)

resp1 = client.index(
    index="my-index-000001",
    id="1",
    refresh=True,
    document={
        "my-small": [
            "ok",
            "bad"
        ],
        "my-large": "ok content"
    },
)
print(resp1)

resp2 = client.search(
    index="my-index-000001",
    fields=[
        "my-*"
    ],
    source=False,
)
print(resp2)
response = client.indices.create(
  index: 'my-index-000001',
  body: {
    mappings: {
      properties: {
        "my-small": {
          type: 'keyword',
          ignore_above: 2
        },
        "my-large": {
          type: 'keyword'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  refresh: true,
  body: {
    "my-small": [
      'ok',
      'bad'
    ],
    "my-large": 'ok content'
  }
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    fields: [
      'my-*'
    ],
    _source: false
  }
)
puts response
const response = await client.indices.create({
  index: "my-index-000001",
  mappings: {
    properties: {
      "my-small": {
        type: "keyword",
        ignore_above: 2,
      },
      "my-large": {
        type: "keyword",
      },
    },
  },
});
console.log(response);

const response1 = await client.index({
  index: "my-index-000001",
  id: 1,
  refresh: "true",
  document: {
    "my-small": ["ok", "bad"],
    "my-large": "ok content",
  },
});
console.log(response1);

const response2 = await client.search({
  index: "my-index-000001",
  fields: ["my-*"],
  _source: false,
});
console.log(response2);
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "my-small" : { "type" : "keyword", "ignore_above": 2 }, 
      "my-large" : { "type" : "keyword" }
    }
  }
}

PUT my-index-000001/_doc/1?refresh=true
{
  "my-small": ["ok", "bad"], 
  "my-large": "ok content"
}

POST my-index-000001/_search
{
  "fields": ["my-*"],
  "_source": false
}

此字段具有大小限制

此文档字段的值超过了大小限制,因此被忽略且未编制索引

响应将在 ignored_field_values 路径下包含被忽略的字段值。这些值是从文档的原始 JSON 来源检索的,并且是原始值,因此不会以任何方式进行格式化或处理,这与成功索引的字段不同,后者在 fields 部分中返回。

{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_id" : "1",
        "_score" : 1.0,
        "_ignored" : [ "my-small"],
        "fields" : {
          "my-large": [
            "ok content"
          ],
          "my-small": [
            "ok"
          ]
        },
        "ignored_field_values" : {
          "my-small": [
            "bad"
          ]
        }
      }
    ]
  }
}

_source 选项

编辑

您可以使用 _source 参数选择返回源中的哪些字段。这称为_源过滤_。

以下搜索 API 请求将 _source 请求正文参数设置为 false。文档源未包含在响应中。

resp = client.search(
    source=False,
    query={
        "match": {
            "user.id": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    _source: false,
    query: {
      match: {
        'user.id' => 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  _source: false,
  query: {
    match: {
      "user.id": "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "_source": false,
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

要仅返回源字段的子集,请在 _source 参数中指定通配符 (*) 模式。以下搜索 API 请求仅返回 obj 字段及其属性的源。

resp = client.search(
    source="obj.*",
    query={
        "match": {
            "user.id": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    _source: 'obj.*',
    query: {
      match: {
        'user.id' => 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  _source: "obj.*",
  query: {
    match: {
      "user.id": "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "_source": "obj.*",
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

您还可以在 _source 字段中指定通配符模式的数组。以下搜索 API 请求仅返回 obj1obj2 字段及其属性的源。

resp = client.search(
    source=[
        "obj1.*",
        "obj2.*"
    ],
    query={
        "match": {
            "user.id": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    _source: [
      'obj1.*',
      'obj2.*'
    ],
    query: {
      match: {
        'user.id' => 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  _source: ["obj1.*", "obj2.*"],
  query: {
    match: {
      "user.id": "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "_source": [ "obj1.*", "obj2.*" ],
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

为了更好地控制,您可以在 _source 参数中指定一个包含 includesexcludes 模式数组的对象。

如果指定了 includes 属性,则仅返回与其中一个模式匹配的源字段。您可以使用 excludes 属性从该子集中排除字段。

如果未指定 includes 属性,则返回整个文档源,排除与 excludes 属性中的模式匹配的任何字段。

以下搜索 API 请求仅返回 obj1obj2 字段及其属性的源,排除任何子 description 字段。

resp = client.search(
    source={
        "includes": [
            "obj1.*",
            "obj2.*"
        ],
        "excludes": [
            "*.description"
        ]
    },
    query={
        "term": {
            "user.id": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    _source: {
      includes: [
        'obj1.*',
        'obj2.*'
      ],
      excludes: [
        '*.description'
      ]
    },
    query: {
      term: {
        'user.id' => 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  _source: {
    includes: ["obj1.*", "obj2.*"],
    excludes: ["*.description"],
  },
  query: {
    term: {
      "user.id": "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "_source": {
    "includes": [ "obj1.*", "obj2.*" ],
    "excludes": [ "*.description" ]
  },
  "query": {
    "term": {
      "user.id": "kimchy"
    }
  }
}

检索数据的其他方法

编辑

一个文档的 _source 在 Lucene 中存储为单个字段。这种结构意味着即使您只请求其中的一部分,也必须加载和解析整个 _source 对象。为了避免这种限制,您可以尝试其他加载字段的选项。

  • 使用 docvalue_fields 参数来获取所选字段的值。当返回少量支持 doc values 的字段(例如关键字和日期)时,这可能是一个不错的选择。
  • 使用 stored_fields 参数来获取特定存储字段的值(使用 store 映射选项的字段)。

Elasticsearch 始终尝试从 _source 加载值。此行为与源过滤具有相同的含义,即 Elasticsearch 需要加载和解析整个 _source 才能仅检索一个字段。

Doc value 字段
编辑

您可以使用 docvalue_fields 参数在搜索响应中返回一个或多个字段的 doc values

Doc values 存储与 _source 相同的值,但存储在基于磁盘的、面向列的结构中,该结构针对排序和聚合进行了优化。由于每个字段都是单独存储的,因此 Elasticsearch 只读取请求的字段值,并且可以避免加载整个文档的 _source

默认情况下,为受支持的字段存储 Doc values。但是,texttext_annotated 字段不支持 doc values。

以下搜索请求使用 docvalue_fields 参数检索 user.id 字段、所有以 http.response. 开头的字段以及 @timestamp 字段的 doc values

resp = client.search(
    index="my-index-000001",
    query={
        "match": {
            "user.id": "kimchy"
        }
    },
    docvalue_fields=[
        "user.id",
        "http.response.*",
        {
            "field": "date",
            "format": "epoch_millis"
        }
    ],
)
print(resp)
response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      match: {
        'user.id' => 'kimchy'
      }
    },
    docvalue_fields: [
      'user.id',
      'http.response.*',
      {
        field: 'date',
        format: 'epoch_millis'
      }
    ]
  }
)
puts response
const response = await client.search({
  index: "my-index-000001",
  query: {
    match: {
      "user.id": "kimchy",
    },
  },
  docvalue_fields: [
    "user.id",
    "http.response.*",
    {
      field: "date",
      format: "epoch_millis",
    },
  ],
});
console.log(response);
GET my-index-000001/_search
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "docvalue_fields": [
    "user.id",
    "http.response.*", 
    {
      "field": "date",
      "format": "epoch_millis" 
    }
  ]
}

接受完整字段名称和通配符模式。

使用对象表示法,您可以传递 format 参数以对字段的 doc values 应用自定义格式。Date 字段 支持 日期 formatNumeric 字段 支持 DecimalFormat 模式。其他字段数据类型不支持 format 参数。

您不能使用 docvalue_fields 参数检索嵌套对象的 doc values。如果您指定一个嵌套对象,则搜索将返回该字段的空数组 ([ ])。要访问嵌套字段,请使用 inner_hits 参数的 docvalue_fields 属性。

存储字段
编辑

还可以使用 store 映射选项来存储单个字段的值。您可以使用 stored_fields 参数在搜索响应中包含这些存储的值。

stored_fields 参数用于在映射中显式标记为存储的字段,默认情况下该字段处于关闭状态,通常不建议使用。请使用 源过滤 来选择要返回的原始源文档的子集。

允许为搜索命中表示的每个文档选择性地加载特定的存储字段。

resp = client.search(
    stored_fields=[
        "user",
        "postDate"
    ],
    query={
        "term": {
            "user": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    stored_fields: [
      'user',
      'postDate'
    ],
    query: {
      term: {
        user: 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  stored_fields: ["user", "postDate"],
  query: {
    term: {
      user: "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "stored_fields" : ["user", "postDate"],
  "query" : {
    "term" : { "user" : "kimchy" }
  }
}

* 可以用于从文档中加载所有存储字段。

空数组将导致仅返回每个命中的 _id_type,例如

resp = client.search(
    stored_fields=[],
    query={
        "term": {
            "user": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    stored_fields: [],
    query: {
      term: {
        user: 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  stored_fields: [],
  query: {
    term: {
      user: "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "stored_fields" : [],
  "query" : {
    "term" : { "user" : "kimchy" }
  }
}

如果请求的字段未存储(store 映射设置为 false),则将忽略它们。

从文档本身获取的存储字段值始终作为数组返回。相反,像 _routing 这样的元数据字段永远不会作为数组返回。

此外,只能通过 stored_fields 选项返回叶子字段。如果指定了对象字段,则将被忽略。

单独使用 stored_fields 不能用于加载嵌套对象中的字段 — 如果字段的路径中包含嵌套对象,则不会返回该存储字段的任何数据。要访问嵌套字段,必须在 inner_hits 块中使用 stored_fields

禁用存储字段
编辑

要完全禁用存储字段(和元数据字段),请使用:_none_

resp = client.search(
    stored_fields="_none_",
    query={
        "term": {
            "user": "kimchy"
        }
    },
)
print(resp)
response = client.search(
  body: {
    stored_fields: '_none_',
    query: {
      term: {
        user: 'kimchy'
      }
    }
  }
)
puts response
const response = await client.search({
  stored_fields: "_none_",
  query: {
    term: {
      user: "kimchy",
    },
  },
});
console.log(response);
GET /_search
{
  "stored_fields": "_none_",
  "query" : {
    "term" : { "user" : "kimchy" }
  }
}

如果使用 _none_,则无法激活 _sourceversion 参数。

脚本字段
编辑

您可以使用 script_fields 参数来检索每个命中的脚本评估(基于不同的字段)。例如

resp = client.search(
    query={
        "match_all": {}
    },
    script_fields={
        "test1": {
            "script": {
                "lang": "painless",
                "source": "doc['price'].value * 2"
            }
        },
        "test2": {
            "script": {
                "lang": "painless",
                "source": "doc['price'].value * params.factor",
                "params": {
                    "factor": 2
                }
            }
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      match_all: {}
    },
    script_fields: {
      "test1": {
        script: {
          lang: 'painless',
          source: "doc['price'].value * 2"
        }
      },
      "test2": {
        script: {
          lang: 'painless',
          source: "doc['price'].value * params.factor",
          params: {
            factor: 2
          }
        }
      }
    }
  }
)
puts response
const response = await client.search({
  query: {
    match_all: {},
  },
  script_fields: {
    test1: {
      script: {
        lang: "painless",
        source: "doc['price'].value * 2",
      },
    },
    test2: {
      script: {
        lang: "painless",
        source: "doc['price'].value * params.factor",
        params: {
          factor: 2,
        },
      },
    },
  },
});
console.log(response);
GET /_search
{
  "query": {
    "match_all": {}
  },
  "script_fields": {
    "test1": {
      "script": {
        "lang": "painless",
        "source": "doc['price'].value * 2"
      }
    },
    "test2": {
      "script": {
        "lang": "painless",
        "source": "doc['price'].value * params.factor",
        "params": {
          "factor": 2.0
        }
      }
    }
  }
}

脚本字段可以处理未存储的字段(上述情况中的 price),并允许返回自定义值(脚本的评估值)。

脚本字段还可以访问实际的 _source 文档,并使用 params['_source'] 从中提取要返回的特定元素。这是一个例子

resp = client.search(
    query={
        "match_all": {}
    },
    script_fields={
        "test1": {
            "script": "params['_source']['message']"
        }
    },
)
print(resp)
response = client.search(
  body: {
    query: {
      match_all: {}
    },
    script_fields: {
      "test1": {
        script: "params['_source']['message']"
      }
    }
  }
)
puts response
const response = await client.search({
  query: {
    match_all: {},
  },
  script_fields: {
    test1: {
      script: "params['_source']['message']",
    },
  },
});
console.log(response);
GET /_search
{
  "query": {
    "match_all": {}
  },
  "script_fields": {
    "test1": {
      "script": "params['_source']['message']"
    }
  }
}

请注意此处的 _source 关键字,以导航类似 json 的模型。

理解 doc['my_field'].valueparams['_source']['my_field'] 之间的区别非常重要。第一个使用 doc 关键字将导致该字段的术语加载到内存(缓存),这将导致更快的执行速度,但会消耗更多的内存。此外,doc[...] 表示法仅允许使用简单值字段(您无法从中返回 json 对象),并且仅对非分析或基于单个术语的字段有意义。但是,如果可能,仍然建议使用 doc 来访问文档中的值,因为每次使用 _source 时都必须加载和解析它。使用 _source 非常慢。