8

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

考虑这个示例文档:

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

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

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

我们认为解决方案是在创建customData索引时不创建任何映射,但随后它变得不可查询(这与ES 文档所说的相反)。如果对非映射属性的查询有效,这将是理想的解决方案,并且这种方法没有性能问题。但是,在为此进行了多次测试之后,我们无法让它发挥作用。

这是需要任何特殊配置的东西吗?还是文档不正确?非常感谢您对为什么它不起作用的一些澄清。

由于这目前不适合我们,我们已经想到了几个替代解决方案:

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

  2. 使用多重匹配查询:每次 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"]
        }
      }
    }'
    

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

    这也只是感觉像是一种 hack,应该由 ES 本地处理。我错过了什么吗?

任何关于这方面的建议将不胜感激。

谢谢!

4

2 回答 2

3

你说得对,Elasticsearch 并不是真正的无模式。如果未指定映射,Elasticsearch 会根据它为该字段看到的第一个值推断字段类型原语。因此,如果您第一次看到"favoriteColor": 10后面跟着"favoriteColor": "red".

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

于 2015-08-12T17:14:21.570 回答
0

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

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

于 2015-07-21T07:56:33.797 回答