弹性搜索查询的无架构支持

时间:2015-07-01 21:26:43

标签: json elasticsearch schemaless

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

考虑这个示例文档:

{
  "givenName": "Joe",
  "username": "joe",
  "email": "joe@mailinator.com",
  "customData": {
    "favoriteColor": "red",
    "someObject": {
      "someKey": "someValue"
    }
  } 
}

customData以外的所有字段都遵循架构。 customData始终是JSON对象,但该对象中的所有字段和值可能因资源而异。无法保证customData中任何给定的字段名称或值(甚至值类型)在任何两个资源中都是相同的,因为用户可以根据需要编辑这些字段。

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

我们认为解决方案是在创建索引时不为customData创建任何映射,但随后它变得不可信(这与ES docs say相反)。如果对非映射属性的查询起作用,这将是理想的解决方案,并且此方法没有性能问题。但是,在针对该问题运行多个测试之后,我们无法使其工作。

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

由于目前这不适用于我们,我们已经考虑了几种替代解决方案:

  1. 重新索引:这将是昂贵的,因为我们需要重新索引包含该文档的每个索引,并且每次用户使用不同的值类型更新属性时都这样做。对性能非常不利,所以这可能不是一个真正的选择。

  2. 使用multi-match query:我们会在每次customData对象发生更改时将随机字符串附加到customData字段名称。例如,这就是索引文档的样子:

    {
      "givenName": "Joe",
      "username": "joe",
      "email": "joe@mailinator.com",
      "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处理的东西。我错过了什么吗?

  3. 对此任何建议都会非常感激。

    谢谢!

2 个答案:

答案 0 :(得分:2)

您认为Elasticsearch并非真正的无模式。如果未指定映射,Elasticsearch将根据它为该字段查看的第一个值推断字段类型基元。因此,如果您第一次看到"favoriteColor": 10后跟"favoriteColor": "red",则您的非确定性customData对象可能会让您遇到麻烦。

根据您的要求,您应该查看SIREn Solutions Elasticsearch plugin,它提供了一种无模式解决方案,结合了高级查询语言(使用Twig)和自定义Lucene索引格式,以加快索引编制速度,搜索非确定性数据的操作。

答案 1 :(得分:0)

具有相同映射的字段将存储为lucene索引(Elasticsearch shard)中的相同lucene字段。不同的lucene字段将具有单独的反向索引(术语dict和索引条目)和单独的doc值。 Lucene经过高度优化,可以压缩方式存储相同字段的文档。对不同的文档使用不同字段的映射可以防止lucene进行优化。

您应该使用Elasticsearch嵌套文档进行有效搜索。底层技术是Lucene BlockJoin,它将父/子文档索引为文档块。