elasticsearch 一对多普通文档子对象边界值问题

得意时要看淡,失意时要看开。不论得意失意,切莫大意;不论成功失败,切莫止步。志得意满时,需要的是淡然,给自己留一条退路;失意落魄时,需要的是泰然,给自己觅一条出路elasticsearch 一对多普通文档子对象边界值问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一般为保证大数据量、低延时业务数据查询都会用到基于lucene的搜索引擎elasticsearch 。ES的出现解决了大数据搜索的一大问题,但是由于某些特殊业务数据就可能出现一些问题。比如:一对多业务普通索引的子对象边界值问题。

什么是子对象边界值
所谓子对象边界值仅出现于一对多普通文档中,文档对象包含一个或多个子对象集合。由于这些子对象里面的字段及其类型都是一样的数组形式,故ES在保存数据的时候就将数据扁平化处理。
比如:

{
  "_index" : "product_info",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "产品1",
    "desc" : "产品1描述",
    "channel" : [
      {
        "channelName" : "产品1渠道1",
        "channelPrice" : 20
      },
      {
        "channelName" : "产品1渠道2",
        "channelPrice" : 30
      }
    ]
  }
}

实际对象数据模拟格式为:

{
    "name" : "产品1",
    "desc" : "产品1描述",
    "channel.channelName" : ["产品1渠道1", "产品1渠道2"],
    "channel.channelPrice" : [20,30]
}

存在问题
1、子对象的相同类型数据都放在一起,不能明确的区分出各个子对象数据。
比如:我们查询 产品1+产品1渠道1+价格30 这个本身不存在的数据,但是ES还是会将该文档响应。

实战演示
我们为方便测试与展示ES执行脚本选用kiibana工具进行脚本演示
比如:
我们的产品对象:
product_info 对象包含属性 name-名称、desc-描述、channel-渠道数组
channel 是 product_info 子对象,属性有 channelName-渠道名称、channelPrice-渠道价值

1、根据产品对象构建索引

PUT product_info
PUT product_info/_mapping
{
  "properties" : {
    "name":{
      "type": "keyword"
    },
    "desc":{
      "type": "keyword"
    },
    "channel":{
      "properties" : {
        "channelName":{
          "type": "keyword"
        },
        "channelPrice":{
          "type": "integer"
        }
      }
    }
  }
}

查看索引结构:

GET product_info

在这里插入图片描述

2、新增两个产品文档

PUT product_info/_doc/1
{
  "name":"产品1",
  "desc":"产品1描述",
  "channel":[
      {
       "channelName":"产品1渠道1",
       "channelPrice": 20
      },
      {
       "channelName":"产品1渠道2",
       "channelPrice": 30
      }
    ]
}

PUT product_info/_doc/2
{
  "name":"产品2",
  "desc":"产品2描述",
  "channel":[
      {
       "channelName":"产品2渠道1",
       "channelPrice": 200
      },
      {
       "channelName":"产品2渠道2",
       "channelPrice": 130
      }
    ]
}

查新当前产品文档:

GET product_info/_search
{ 
}

在这里插入图片描述

3、对产品文档子对象进行边界值查询

GET product_info/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "name": {
              "value": "产品2"
            }
          }
        },
        {
          "term": {
            "channel.channelPrice": {
              "value": 130
            }
          }
        },
        {
          "term": {
            "channel.channelName": {
              "value": "产品2渠道1"
            }
          }
        }
      ]
    }
  }
}

产品2 + 130 + 产品2渠道1
查询预期结果:
由于 产品2渠道1 价值是 200,则预期结果为空才对。

实际查询结果:
在这里插入图片描述

普通一对多文档结论:
优点:
1、查询速度快;
2、不用创建多个文档,父子对象都在同一个文档,简化操作。
缺点:
1、同文档多个子对象有边界值问题,如果业务场景中需要严格区分子对象,不能够使用;
2、由于父子对象都存在同一个文档,文档较大且难以维护。

如果避免边界值问题:

1、业务场景不要求严格区分子对象,可忽略不计
2、业务场景严格要求则可采用 嵌套子文档 进行解决

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/154680.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!