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

ecr*_*omo 7 json schemaless elasticsearch

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

考虑这个示例文档:

{
  "givenName": "Joe",
  "username": "joe",
  "email": "joe@mailinator.com",
  "customData": {
    "favoriteColor": "red",
    "someObject": {
      "someKey": "someValue"
    }
  } 
}
Run Code Online (Sandbox Code Playgroud)

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"
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这意味着ES将为每个"随机"字段创建一个新映射,我们将在执行查询时使用字段名称的"start with"通配符进行短语多匹配查询.例如:

    curl -XPOST 'eshost:9200/test/_search?pretty' -d '
    {
      "query": {
        "multi_match": {
          "query" : "red",
          "type" :  "phrase",
          "fields" : ["customData_*.favoriteColor"]
        }
      }
    }'
    
    Run Code Online (Sandbox Code Playgroud)

    这可能是一个可行的解决方案,但我们担心像这样的映射太多会影响性能.在索引上有太多映射是否有任何性能影响?也许定期重建索引可以减轻映射太多的问题?

    这也只是一种黑客攻击和本地应该由ES处理的东西.我错过了什么吗?

任何有关这方面的建议都将非常感激.

谢谢!

小智 0

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

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