如何避免elasticsearch中的索引爆炸

rmbxnbpk  于 2021-06-10  发布在  ElasticSearch
关注(0)|答案(1)|浏览(468)

我有两个来自同一索引的文档,它们最初看起来像这样(只有 _source (此处显示值)

{
    "id" : "3",
    "name": "Foo",
    "property":{
        "schemaId":"guid_of_the_RGB_schema_defined_extenally",
        "value":{
            "R":255,
            "G":100,
            "B":20
        }
    }
}
{
    "id" : "2",
    "name": "Bar",
    "property":{
        "schemaId":"guid_of_the_HSL_schema_defined_extenally",
        "value":{
            "H":255,
            "S":100,
            "L":20
        }
    }
}

架构(用于验证 value )存储在es之外,因为它与索引无关。如果我不定义Map value 现场将被考虑 Object Map。一旦有了新的子域,它的子域就会增长。
目前,elasticsearch支持展平Maphttps://www.elastic.co/guide/en/elasticsearch/reference/current/flattened.html 以防止索引中出现这种爆炸。但是,由于其限制,它对搜索内部场的支持有限: As with queries, there is no special support for numerics — all values in the JSON object are treated as keywords. When sorting, this implies that values are compared lexicographically. 我需要能够查询索引以找到与给定文档匹配的文档(例如,范围[10,30]中的b)
到目前为止,我想出了一个解决方案,把我的医生组织成这样

{
    "id":4,
    "name":"Boo",
    "property":
    {
        "guid_of_the_normalized_RGB_schema_defined_extenally":
        {
           "R":0.1,
           "G":0.2,
           "B":0.5
        }
}

虽然它并没有解决我的Map爆炸问题,但它减轻了其他一些问题。我现在的Map将类似于这个字段 property ```
"property": {
"properties": {
"guid_of_the_RGB_schema_defined_extenally": {
"properties": {
"B": {
"type": "long"
},
"G": {
"type": "long"
},
"R": {
"type": "long"
}
}
},
"guid_of_the_normalized_RGB_schema_defined_extenally": {
"properties": {
"B": {
"type": "float"
},
"G": {
"type": "float"
},
"R": {
"type": "float"
}
},
"guid_of_the_HSL_schema_defined_extenally": {
"properties": {
"B": {
"type": "float"
},
"G": {
"type": "float"
},
"R": {
"type": "float"
}
}
}
}
}

这解决了字段名称相同但数据类型不同的问题。
有人能给我建议一个解决方案,解决指数爆炸的问题,而不受 `Flattened` 你在找什么?
mrzz3bfm

mrzz3bfm1#

为了避免Map爆炸,最好的解决方案是更好地规范化数据。您可以在Map中设置“dynamic”:“strict”,如果一张单据包含Map中尚未包含的字段,则该单据将被拒绝。之后,仍然可以添加新字段,但必须在Map之前显式添加它们。
您可以添加一个管道,以便在接收数据之前对数据进行清理和规范化。
如果不需要或无法重新索引:
为了使您的查询更容易,即使您不知道您的关键的“中间”部分,您可以使用一个星的多重匹配。

GET myindex/_search
{
  "query": {
    "multi_match": {
      "query": 0.5,
      "fields": ["property.*.B"]
    }
  }
}

但你仍然无法按你的意愿对它进行排序。要在不接触数据的情况下对多个“未知”字段名进行排序,可以使用脚本:https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-sort-context.html
但也许你可以通过在索引中添加一个动态模板来简化整个过程。

PUT test/_mapping
{
  "dynamic_templates": [
    {
      "unified_red": {
        "path_match": "property.*.R",
        "mapping": {
          "type": "float",
          "copy_to": "unified_color.R"
        }
      }
    },
    {
      "unified_green": {
        "path_match": "property.*.G",
        "mapping": {
          "type": "float",
          "copy_to": "unified_color.G"
        }
      }
    },
    {
      "unified_blue": {
        "path_match": "property.*.B",
        "mapping": {
          "type": "float",
          "copy_to": "unified_color.B"
        }
      }
    }
  ],
  "properties": {
    "unified_color": {
      "properties": {
        "R": {
          "type": "float"
        },
        "G": {
          "type": "float"
        },
        "B": {
          "type": "float"
        }
      }
    }
  }
}

然后您可以使用相同的查询查询任何值:

GET test/_search
{
  "query": {
    "range": {
      "unified_color.B": {
        "gte": 0.1,
        "lte": 0.6
      }
    }
  }
}

对于已经存在的字段,您必须自己在Map中添加副本,然后运行一个\u update \u by \u查询来填充它们。

相关问题