Elasticsearch详解mapping之object
elasticsearch支持某个字段存储一个JSON对象, 这个字段类型就是object.
1 举例: 传统数据库存对象数据
假设有一个人员信息如下:
{
"region": "US",
"manager": {
"age": 30,
"name": {
"first": "John",
"last": "Smith"
}
}
}
如果我们要按照普通方式:建一个字段存一个值,那么会做如下处理
字段 | 值 |
---|---|
region | US |
managerAge | 30 |
managerFirstName | John |
managerLastName | Smith |
- 如果我们是用MySQL创建表记录数据,的确得这么做,一个字段存一个值.
- 但是它的缺点是字段扁平化后, 无法直观的表现原来数据的层级关系: age和name是属于manager的, first和last是属于name的.
2 ES存对象数据
ES中,一条数据都是一个JSON格式的文档,JSON格式本身就包含嵌套的层级关系.
2.1 创建mapping
PUT pigg_test_object
{
"mappings": {
"properties": {
"region": {
"type": "keyword"
},
"manager": {
"properties": {
"age": {
"type": "integer"
},
"name": {
"properties": {
"first": {
"type": "keyword"
},
"last": {
"type": "keyword"
}
}
}
}
}
}
}
}
上面的mapping可以看出mapping字段层级关系和数据层级关系一致
- 一层有2个字段: region和manager
- manager包含2个字段: age和name
- name包含2个字段: first和last
2.2 插入数据
PUT pigg_test_object/_doc/1
{
"region": "US",
"manager": {
"age": 30,
"name": {
"first": "John",
"last": "Smith"
}
}
}
在es内部,这些值其实是类似如下格式存储的
{
"region": "US",
"manager.age": 30,
"manager.name.first": "John",
"manager.name.last": "Smith"
}
2.3 查询object对象数据
查询嵌套的子字段时,得输入字段的全名,如manager.name.first
GET /pigg_test_object/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"region": {
"value": "US"
}
}
},
{
"term": {
"manager.age": {
"value": "30"
}
}
},
{
"term": {
"manager.name.first": {
"value": "John"
}
}
}
]
}
}
}
3 注意点: object类型不要存对象数组
3.1 存入对象数组
PUT pigg_test_object/_doc/1
{
"region":"US",
"manager":[
{
"age":30,
"name":{
"first":"John",
"last":"Smith"
}
},
{
"age":40,
"name":{
"first":"Geen",
"last":"Hank"
}
}
]
}
3.2 验证错误的查询结果
按照正常理解,下面的语句是不应该查询出来结果的
GET /pigg_test_object/_search
{
"query": {
"bool": {
"must": [
{
"term": {
"manager.age": {
"value": "30"
}
}
},
{
"term": {
"manager.name.first": {
"value": "Geen"
}
}
}
]
}
}
}
返回如下:
{
"_index" : "pigg_test_object",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.3616575,
"_source" : {
"region" : "US",
"manager" : [
{
"age" : 30,
"name" : {
"first" : "John",
"last" : "Smith"
}
},
{
"age" : 40,
"name" : {
"first" : "Geen",
"last" : "Hank"
}
}
]
}
}
之所以能够查询到数据是因为在es内部,数据会如下存储
{
"region": "US",
"manager.age": [30, 40],
"manager.name.first": ["John", "Geen"],
"manager.name.last": ["Smith", "Hank"]
}
- 一个object字段只能存入一个JSON对象, 不适合存对象数组
- 如果想要一个字段存一个对象数组,可以使用nested字段类型