Elasticsearch关系映射(一对一和一对多)

38

在我的 ElasticSearch 服务器上,我有一个名为 http://localhost:9200/blog 的索引。

这个 (blog) 索引包含多种类型。

例如:http://localhost:9200/blog/postshttp://localhost:9200/blog/tags

在 tags 类型下,我创建了超过 1000 个标签,并且在 posts 类型下创建了 10 篇文章。

例如:posts

{   
    "_index":"blog",
    "_type":"posts",
    "_id":"1",
    "_version":3,
    "found":true,
    "_source" : {
        "catalogId" : "1",
       "name" : "cricket",
       "url" : "http://www.wikipedia/cricket"
    }
}

例如:标签

{   
    "_index":"blog",
    "_type":"tags",
    "_id":"1",
    "_version":3,
    "found":true,
    "_source" : {
        "tagId" : "1",
        "name" : "game"
    }
}

我想将现有的标签分配给博客文章(即关系 => 映射)。

我如何将标签分配给文章映射?

1个回答

83
在Elasticsearch中处理关系有四种方法。详见Elasticsearch博客文章 - Managing Relations Inside Elasticsearch,建议阅读整篇文章以了解每种方法的细节,然后选择最符合业务需求并技术上恰当的方法。
以下是这四种方法的要点:

内部对象

  • 容易、快速、高效。
  • 仅适用于一对一关系。
  • 无需特殊查询。

嵌套

  • 嵌套文档存储在同一个Lucene块中,有助于读取/查询性能。读取嵌套文档比等效父/子文档更快。
  • 更新嵌套文档(父文档或嵌套子文档)中的单个字段会强制ES重新索引整个嵌套文档。对于大型嵌套文档,这可能非常昂贵。
  • 无法“交叉引用”嵌套文档。
  • 最适用于不经常更改的数据。

父/子

  • 子文档与父文档分开存储,但路由到相同的分片。因此,在读取/查询方面,父/子性能略低于嵌套。
  • 父/子映射具有额外的内存开销,因为ES在内存中维护“连接”列表。
  • 更新子文档不会影响父文档或任何其他子文档,这可能会在大型文档上节省大量索引。
  • 使用Parent/Child进行排序/评分可能会很困难,因为Has Child/Has Parent操作有时可能是不透明的。

去规范化

  • 您可以自己管理所有关系!
  • 最灵活,行政开销最大。
  • 根据您的设置,可能更或少更有效率。

2
优点和缺点的简明清单。 - tacos_tacos_tacos
4
称父子关系查询性能比嵌套略差可能会误导。根据我们的观察,它比嵌套慢1-2个数量级,具体取决于索引大小。 - ischell
2
“Denormalization”和“内部对象”有什么区别? - Joey Yi Zhao
内部对象方法意味着您只需存储一次父文档,并将其子文档添加到该文档的数组中。去规范化意味着您只有“子文档”,并且每个子文档都保存了父数据。 - Călin Bogdan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接