我们的REST API允许用户将自定义的无模式JSON添加到我们的一些REST资源中,我们需要它可以在Elasticsearch中进行搜索。在相同类型的资源之间,此自定义数据及其结构可以完全不同。

考虑以下示例文档:

{
  "givenName": "Joe",
  "username": "joe",
  "email": "[email protected]",
  "customData": {
    "favoriteColor": "red",
    "someObject": {
      "someKey": "someValue"
    }
  }
}

customData之外的所有字段均遵循模式。 customData始终是JSON对象,但是该对象中的所有字段和值在资源之间可能会发生巨大变化。无法保证customData中任何给定的字段名称或值(甚至值类型)在任何两个资源上都是相同的,因为用户可以根据需要编辑这些字段。

支持搜索的最佳方法是什么?

我们认为一种解决方案是在创建索引时不为customData创建任何映射,而是使其变得不可查询(这与ES docs say相反)。如果对非映射属性的查询有效,并且此方法没有性能问题,那么这将是理想的解决方案。但是,在为此进行了多次测试之后,我们无法使其正常运行。

这需要任何特殊的配置吗?还是文档不正确?对于它为什么不起作用的一些澄清将不胜感激。

由于目前这不适用于我们,因此我们想到了几种替代解决方案:
  • 重新索引:这将是昂贵的,因为我们需要重新索引包含该文档的每个索引,并且每次用户更新具有不同值类型的属性时都需要重新索引。确实对性能不利,因此这可能不是一个真正的选择。
  • 使用multi-match query:每当customData对象发生更改时,我们都会通过在customData字段名称后附加一个随机字符串来做到这一点。例如,这就是要建立索引的文档的样子:
    {
      "givenName": "Joe",
      "username": "joe",
      "email": "[email protected]",
      "customData_03ae8b95-2496-4c8d-9330-6d2058b1bbb9": {
        "favoriteColor": "red",
        "someObject": {
          "someKey": "someValue"
        }
      }
    }
    

    这意味着ES将为每个“随机”字段创建一个新的映射,并且在执行查询时,我们会使用短语多匹配查询,并在字段名称中使用“开头为”通配符。例如:
    curl -XPOST 'eshost:9200/test/_search?pretty' -d '
    {
      "query": {
        "multi_match": {
          "query" : "red",
          "type" :  "phrase",
          "fields" : ["customData_*.favoriteColor"]
        }
      }
    }'
    

    这可能是一个可行的解决方案,但是我们担心这样的映射过多会影响性能。索引上的映射过多会对性能产生影响吗?也许定期重新编制索引可以减轻过多的映射?

    这也感觉就像是黑客一样,应该由ES native 处理。我想念什么吗?

  • 任何有关此的任何建议将不胜感激。

    谢谢!

    最佳答案

    您是对的,Elasticsearch不是真正的无模式。如果未指定任何映射,Elasticsearch将根据对该字段看到的第一个值来推断字段类型原语。因此,如果您首先看到"favoriteColor": 10"favoriteColor": "red",那么不确定的customData对象可能会给您带来麻烦。

    根据您的需求,您应该看一下SIREn Solutions Elasticsearch plugin,它提供了无模式解决方案以及高级查询语言(使用Twig)和自定义Lucene索引格式,以加快对不确定性数据的索引和搜索操作。

    关于json - Elasticsearch 查询的无模式支持,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31171987/

    10-11 08:44