Elasticsearch 数据建模最佳实践 学习

本文探讨了Elasticsearch的数据建模策略,包括关联关系处理、字段管理、避免正则查询、空值处理及映射元信息的重要性。通过具体案例,如Nested对象使用和Inner Object优化,展示了如何提升查询效率和数据维护。

Elasticsearch 数据建模最佳实践

建模建议(⼀):如何处理关联关系

Object •优先考虑 Denormalization
Nested •当数据包含多数值对象(多个演员),同时有查询需求
Child/Parent ●关联⽂档更新⾮常频繁时

建模建议(⼆): 避免过多字段

● ⼀个⽂档中,最好避免⼤量的字段
○ 过多的字段数不容易维护
○ Mapping 信息保存在 Cluster State 中,数据量过⼤,对集群性能会有影响 (Cluster
State 信息需要和所有的节点同步)
○ 删除或者修改数据需要 reindex
● 默认最⼤字段数是 1000,可以设置 index.mapping.total_fields.limt 限定最⼤字段数。
● 什么原因会导致⽂档中有成百上千的字段?
Dynamic v.s Strict
● Dynamic(⽣产环境中,尽量不要打开 Dynamic) ○ true - 未知字段会被⾃动加⼊
○ false - 新字段不会被索引。但是会保存在 _source
○ strict - 新增字段不会被索引,⽂档写⼊失败
● Strict
○ 可以控制到字段级别

Cookie Service

##索引数据,dynamic mapping 会不断加入新增字段

PUT cookie_service/_doc/1
{
  "url": "www.google.com",
  "cookies": {
    "username": "tom",
    "age": 32
  }
}

PUT cookie_service/_doc/2
{
  "url": "www.amazon.com",
  "cookies": {
    "login": "2019-01-01",
    "email": "xyz@abc.com"
  }
}

我0们会发现会有很多字段被生成

GET cookie_service
DELETE cookie_service
#使用 Nested 对象,增加key/value
PUT cookie_service
{
  "mappings": {
    "properties": {
      "cookies": {
        "type": "nested",
        "properties": {
          "name": {
            "type": "keyword"
          },
          "dateValue": {
            "type": "date"
          },
          "keywordValue": {
            "type": "keyword"
          },
          "IntValue": {
            "type": "integer"
          }
        }
      },
      "url": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

##写入数据,使用key和合适类型的value字段

PUT cookie_service/_doc/1
{
 "url":"www.google.com",
 "cookies":[
    {
      "name":"username",
      "keywordValue":"tom"
    },
    {
       "name":"age",
      "intValue":32

    }

   ]
 }


PUT cookie_service/_doc/2
{
 "url":"www.amazon.com",
 "cookies":[
    {
      "name":"login",
      "dateValue":"2019-01-01"
    },
    {
       "name":"email",
      "IntValue":32

    }

   ]
 }

Nested 查询,通过bool查询进行过滤

POST cookie_service/_search
{
  "query": {
    "nested": {
      "path": "cookies",
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "cookies.name": "age"
              }
            },
            {
              "range": {
                "cookies.intValue": {
                  "gte": 30
                }
              }
            }
          ]
        }
      }
    }
  }
}
通过 Nested 对象保存 Key/Value 的⼀些不⾜
● 可以减少字段数量,解决 Cluster State 中保存过多 Meta 信息的问题,但是
● 导致查询语句复杂度增加
● Nested 对象,不利于在 Kibana 中实现可视化分析

建模建议(三):避免正则查询

● 问题:
● 正则,通配符查询,前缀查询属于 Term 查询,但是性能不够好
● 特别是将通配符放在开头,会导致性能的灾难
● 案例:
● ⽂档中某个字段包含了 Elasticsearch 的版本信息,例如 version: “7.1.0” ● 搜索所有是 bug fix 的版本?每个主要版本号所关联的⽂档?

解决⽅案:将字符串转换为对象

GET softwares/_mapping
PUT softwares/_doc/1
{
  "software_version":"7.1.0"
}

DELETE softwares
# 优化,使用inner object
PUT softwares/
{
  "mappings": {
    "_meta": {
      "software_version_mapping": "1.1"
    },
    "properties": {
      "version": {
        "properties": {
          "display_name": {
            "type": "keyword"
          },
          "hot_fix": {
            "type": "byte"
          },
          "marjor": {
            "type": "byte"
          },
          "minor": {
            "type": "byte"
          }
        }
      }
    }
  }
}

#通过 Inner Object 写入多个文档

PUT softwares/_doc/1
{
  "version":{
  "display_name":"7.1.0",
  "marjor":7,
  "minor":1,
  "hot_fix":0  
  }

}

PUT softwares/_doc/2
{
  "version":{
  "display_name":"7.2.0",
  "marjor":7,
  "minor":2,
  "hot_fix":0  
  }
}

PUT softwares/_doc/3
{
  "version":{
  "display_name":"7.2.1",
  "marjor":7,
  "minor":2,
  "hot_fix":1  
  }
}

通过 bool 查询,

POST softwares/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "match":{
            "version.marjor":7
          }
        },
        {
          "match":{
            "version.minor":2
          }
        }

      ]
    }
  }
}

建模建议(四):避免空值引起的聚合不准

Not Null 解决聚合的问题

DELETE ratings
PUT ratings
{
  "mappings": {
      "properties": {
        "rating": {
          "type": "float",
          "null_value": 1.0
        }
      }
    }
}


PUT ratings/_doc/1
{
 "rating":5
}
PUT ratings/_doc/2
{
 "rating":null
}


POST ratings/_search
POST ratings/_search
{
  "size": 0,
  "aggs": {
    "avg": {
      "avg": {
        "field": "rating"
      }
    }
  }
}

POST ratings/_search
{
  "query": {
    "term": {
      "rating": {
        "value": 1
      }
    }
  }
}

建模建议(五):为索引的 Mapping 加⼊ Meta 信息

● Mappings 设置⾮常重要,需要从两个维度进⾏考虑
● 功能:搜索,聚合,排序
● 性能:存储的开销;内存的开销;搜索的性能
● Mappings 设置是⼀个迭代的过程
○ 加⼊新的字段很容易(必要时需要 update_by_query)
○ 更新删除字段不允许(需要 Reindex 重建数据) ○ 最好能对 Mappings 加⼊ Meta 信息,更好的进⾏版
本管理
○ 可以考虑将 Mapping ⽂件上传 git 进⾏管理

在Mapping中加入元信息,便于管理

PUT softwares/
{
  "mappings": {
    "_meta": {
      "software_version_mapping": "1.0"
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值