美文网首页
巧用es flattened

巧用es flattened

作者: 郭彦超 | 来源:发表于2023-01-08 17:26 被阅读0次

    好久没更新了 今天讲下如何借助ES的flatten数据类型解决字段膨胀的问题

    背景介绍

    目前商城业务中需要使用ES完成一项特殊的排序逻辑:任意一件商品可以被运营划分到多个品类下,当遇到节假日或者热点时,运营同学需要干预商品排序,即在某些品类下的商品可以按照特定字段值进行排序,没有设置运营排序值的则需要按照综合分进行排序

    问题描述

    我们知道ES并不擅长做数据关联,那么如何实现一件商品可以按照不同的品类权重值进行排序呢?

    解决思路

    这里想到的是借助ES的嵌套结构来实现,即每一个嵌套子文档都是一个k/v结构,key为品类id,value为排序值,如下:

     "navigator_sort" : {
                "895729" : 0,
                "895839" : 0 ,
                "895567" : 100,
                "898804" : 0,
                "898805" : 0,
                "895566" : 75 
     }
    

    如果需要按照指定的品类进行排序,那么可以这么做:

      "sort": [
        {
          "navigator_sort.895567": {
            "order": "desc"
          }
        }
      ]
    

    面临的问题

    默认情况下,Elasticsearch 会在提取nested字段中内容时,会自动映射文档中包含的字段。 虽然这是使用 Elasticsearch 的最简单方法,但随着时间的推移,它往往会导致字段爆炸,并且 Elasticsearch 的性能将受到 “内存不足(out of memory)” 错误以及索引和查询数据时性能不佳的影响。

    什么是字段爆炸?
    Elasticsearch 必须为每个新字段更新集群状态,并且该集群状态必须传递给所有节点。跨节点的集群状态传输是单线程操作 , 因此要更新的字段映射越多,完成更新所需的时间就越长。这种延迟通常以性能不佳的集群而结束,有时会导致整个集群停机。这被称为 “映射爆炸(mapping explosion)”。
    这也是 Elasticsearch 从 5.x 及更高版本开始将索引中的字段数限制为 1,000 个的原因之一。如果我们的字段数超过 1,000,我们必须手动更改默认索引字段限制(使用 index.mapping.total_fields.limit 设置)或者我们需要重新考虑我们的架构。

    替代方案 flattened

    使用 Elasticsearch Flattened数据类型,具有大量嵌套字段的对象被视为单个关键字字段。 换句话说,Elasticsearch 扁平化数据类型用于有效减少Mapping中包含的字段数量,同时仍允许我们查询扁平化数据

    # 构建索引
    PUT my-index-000001
    {
      "mappings": {
        "properties": {
          "title": {
            "type": "text"
          },
          "create_user": {
            "type": "keyword"
          },
          "full_path_json": {
            "type": "flattened",
            "similarity": "boolean"
          }
        }
      }
    }
    
    # 保存一条这样的数据
        {
              "title" : "Something really urgent",
              "create_user" : "1",
              "full_path_json" : [
                {
                  "op_user" : "A",
                  "folders" : [
                    "v3",
                    "v4",
                    "v3tv4"
                  ],
                  "A" : {
                    "op_time" : "2022-01-12",
                    "is_share" : 1,
                    "in_folder" : 1
                  }
                },
                {
                  "op_user" : "2",
                  "2" : {
                    "op_time" : "2022-12-12",
                    "is_share" : 1
                  }
                }
              ]
         }
    
    # 查询和排序
    GET my-index-000001/_search
    {
       "sort": [
         {
           "full_path_json.A.op_time": {
             "order": "desc"
           }
         }
       ], 
      "query": {
        "bool": {
          "filter": [
            {
              "term": {
                "title": "urgent"
              }
            },
            {
              "term": {
                "full_path_json.folders": "f3"
              }
            } 
          ]
        }
      }
    }
    
    

    虽然可以查询在单个字段中 “扁平化” 的嵌套字段,但需要注意某些限制。 扁平对象中的所有字段值都存储为keyword 【 keyword类型字段不进行任何类型的文本分词(text tokenization)或分析,而是按原样存储】
    失去的特性:
    1、失去了使用不区分大小写的查询的能力,这样你就不必输入完全匹配的查询
    2、排序仅支持按照字符大小进行排序

    相关文章

      网友评论

          本文标题:巧用es flattened

          本文链接:https://www.haomeiwen.com/subject/qfvucdtx.html