当然可以指定您希望payload 包含哪些可查询字段以及这些字段的映射应该是什么。
假设 每个 文档将包含字段 payload.livemode 和 payload.created_at。如果您只想对这两个字段执行查询,并且您想禁用 dynamic, index-time mappings autogenerated by Elasticsearch 用于其余字段,您可以使用dynamic templates,如下所示:
PUT my-payload-index
{
"mappings": {
"dynamic_templates": [
{
"variable_payload": {
"path_match": "payload",
"mapping": {
"type": "object",
"dynamic": false,
"properties": {
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"livemode": {
"type": "boolean"
}
}
}
}
}
],
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"origin": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
}
}
}
}
然后,当您提取文档时:
POST my-payload-index/_doc
{
"name": "abc",
"origin": "web.dev",
"payload": {
"created_at": "2021-04-05 08:00:00",
"livemode": false,
"abc":"def"
}
}
POST my-payload-index/_doc
{
"name": "abc",
"origin": "web.dev",
"payload": {
"created_at": "2021-04-05 08:00:00",
"livemode": true,
"modified_at": "2021-04-05 09:00:00"
}
}
并验证
GET my-payload-index/_mapping
不会为字段payload.abc 和payload.modified_at 生成新的映射。
不仅如此 - 新字段也将被忽略,根据 documentation:
这些字段不会被索引或搜索,但仍会出现在返回匹配的_source 字段中。
旁注:如果字段既不存储也不可搜索,则它们实际上与 enabled 相反。
大局
使用单个顶级对象的可变内容是非常标准的。以条纹event object 为例——每个事件都有一个id、一个api_version 和一些其他共享参数。然后是类似于 payload 字段的 data 对象。
现在,一切都很好,直到您需要汇总 payload 的内容。看,因为内容是可变的,所以数据路径/访问器也是可变的。但是聚合路径中的通配符don't work in Elasticsearch。脚本确实是onerous to maintain。
回到条纹。他们通过所谓的多态、类型化哈希部分解决了这个问题——正如in their blog on API design 所讨论的那样:
一种非常简洁的方法,值得效仿。
附:我在my ES Handbook 的chapter "Mapping Automation" 中更详细地讨论了动态模板。