您可以使用相同的映射来映射具有不同名称的元素,但这不太可能有用(取决于您的用例)。
主要有两种选择:
- 使用
dynamic_templates描述重复结构的数据;
- 重塑数据并使用
nested 数据类型
dynamic_templates
优点:
缺点:
重塑 + nested
优点:
缺点:
下面是详细信息。
对dynamic_templates 使用动态映射
一般来说,使用dynamic mapping 可以添加任意结构的对象,其类型将根据some predefined rules 动态猜测。
动态映射使您对数据结构的控制更少,并可能导致mapping explosion。
如果您对动态映射很满意,并且只想调整其应用方式,您可以使用dynamic_templates。
您必须在插入任何数据之前创建一个映射,可能如下所示:
PUT dyno
{
"mappings": {
"dyno": {
"dynamic_templates": [
{
"dynoField": {
"path_match": "myPath.*",
"mapping": {
"properties": {
"ip": {
"type": "keyword"
},
"danger": {
"type": "float"
},
"countryName": {
"type": "keyword"
},
"countryCode": {
"type": "keyword"
},
"frequency": {
"type": "integer"
},
"updown": {
"type": "float"
},
"viewCount": {
"type": "integer"
}
}
}
}
}
],
"properties": {
"myPath": {
"type": "object"
}
}
}
}
}
这里dynamic_templates 部分应用于myPath 对象的所有键(0、1、2、3、4 等)。
索引第一个文档后,您从 ES 获得的映射实际上如下所示:
{
"dyno": {
"aliases": {},
"mappings": {
"dyno": {
"dynamic_templates": [
...
],
"properties": {
"myPath": {
"properties": {
"0": {
"properties": {
"countryCode": {
"type": "keyword"
},
"countryName": {
"type": "keyword"
},
"danger": {
"type": "float"
},
"frequency": {
"type": "integer"
},
"ip": {
"type": "keyword"
},
"updown": {
"type": "float"
},
"viewCount": {
"type": "integer"
}
}
},
"1": {
"properties": {
"countryCode": {
"type": "keyword"
}, ...
},
"2": {
"properties": {
"countryCode": {
"type": "keyword"
}, ...
},
"3": {
"properties": {
"countryCode": {
"type": "keyword"
}, ...
}
}
}
}
}
}
}
}
}
请注意,对于对象的每个不同“名称”,ES 都会创建一个单独的映射部分。
虽然这完全符合您的要求,但它可能没有用。如果您有一个用例,希望选择具有特定countryCode 的所有文档,您可以构建这样的查询:
POST dyno/dyno/_search
{
"query": {
"match": {
"myPath.1.countryCode": "VN"
}
}
}
但这只会返回与“名称”1 的对象匹配。如果“名称”集合很大和/或事先不知道,那么查询它们将非常复杂。
重塑数据并使用nested 类型
为了能够搜索任何对象的countryCode,您可能需要通过以下方式重塑您的数据:
{
"myPath": [
{
"__name": "0",
"ip": "147.135.210.114",
"countryName": "United States",
"countryCode": "US",
"frequency": "46",
"updown": -0.25579565572885,
"viewCount": "28"
},
{
"__name": "1",
"ip": "171.255.199.129",
"danger": "94.42262",
"countryName": "Viet Nam",
"countryCode": "VN",
"frequency": "40",
"updown": -0.088216630501414,
"viewCount": null
}, ...
]
}
棘手的部分是,为了能够单独搜索myPath列表中的项目,必须使用nested数据类型。
在这种情况下,您的映射可以是 dynamic 或 strict,无论哪种方式最适合您。 dynamic 案例中的映射可能看起来很简单:
PUT dyno
{
"mappings": {
"dyno": {
"properties": {
"myPath": {
"type": "nested"
}
}
}
}
}
这将允许您进行这样的查询:
POST dyno/dyno/_search
{
"query": {
"nested": {
"path": "myPath",
"query": {
"match": {
"myPath.countryCode.keyword": "VN"
}
}
}
}
}
请注意,要查询nested 字段,您必须使用nested query。开始使用nested 数据类型的好地方是指南的this chapter。
关于嵌套字段的最后说明
事实上,对于nested 字段,ES 为列表中的每个项目索引一个隐式文档,因此索引和搜索这种类型的对象比非嵌套对象慢。
您可以考虑将这些具有不同“名称”的对象拆分为单独的 ES 文档。
希望有帮助!