将标签存储在图数据库中

7
我在关系型文档数据库中找到了一些设置标记系统的建议,但没有针对图形/多模型数据库的内容。
我正在尝试为ArangoDB中的文档(我们称之为“文章”)设置标记系统。我可以想到两种在多模型(图形+文档)数据库中存储标记的明显方法,如下:
  • 将每篇文章文档作为数组存储(文档数据库风格)
  • 将每个标记作为唯一文档的单独文档类,并使用边缘将标记文档连接到文章文档(更接近关系型数据库风格的方式)
这两种方法是否是实现标记系统的主要方法?两种方法都不是很理想。例如:
  • 如果我在每个文章文档中存储标签,我可以对标签进行索引,而且 ArangoDB 会优化它们所使用的空间。然而,我无法使用图形特性来链接或遍历标签(或者我必须单独执行它)。
  • 如果我将标签作为单独的标签文档存储,当我只想获取文档上标签列表时,似乎会产生额外的开销(一个额外的查询)。

这让我有一个明确的问题:关于后一种选项,是否有任何简单的方法使连接的“标签”文档显示在文章文档中?例如,是否有一个数组属性可以以某种方式“镜像”连接的标签文档的 tag.name 属性?

欢迎提供一般建议。


1
答案对你有用吗?如果有,能否将最佳答案标记为“已接受”?如果没有,缺少什么? - dothebart
请参阅此示例:https://neo4j.com/blog/soundcloud-recommendations-neo4j/ - Magne
3个回答

4

@Joachim Bøggild 将Mike Williamson的文章链接在了一起:https://mikewilliamson.wordpress.com/2015/07/16/data-modeling-with-arangodb/

我同意Williamson的观点,即“默认情况下紧凑”通常是正确的做法。如果需要,你可以从属性中提取出顶点(即节点)。这样还避免了创建过于相互连接的图形结构,这会导致各种遍历查询变得缓慢。

但在这种情况下,我认为拥有标签顶点(即您所说的“文档”)很好,因为您可以在标签上存储元数据(如计数),并将其连接到其他标签和子标签。这在标签的特定情况下似乎非常有用且可以预见。拥有一个顶点,如果/当需要时可以添加更多关系,也非常可扩展,因此您可以保持未来选项更加开放(至少更容易)。

Williamson似乎也认为标签值得特别考虑:

"但是,并非所有东西都应该放在一起。包含复杂数据结构(如“评论”数组或“标签”数组)的任何属性都应该仔细检查,因为它可能作为自己的顶点(或顶点)合理。"

@ropeladder的原始问题提出了主要反对意见,即需要额外的开销(额外的查询)。我认为在这个阶段过于关注性能可能是过早的优化。毕竟;额外的查询可能很快,或者实际上可以与原始查询连接和包含。无论如何,我想引用以下内容:

“通常,试图将节点合并以保持查询时间效率是不好的做法。如果我们按照对数据提出的问题进行建模,就会出现领域的准确表示。即使存储大量数据,图数据库也能保持快速的查询时间。学会信任我们的图形数据库在学习如何构建我们的图形结构时非常重要,而不需要去规范化它们。” ---来自Neo4j创始人Eifrem所写的书籍《图形数据库》第64页,“避免反模式”一章。 Neo4j是另一个非常流行的本地图形数据库。该书免费在线提供,网址:https://neo4j.com/graph-databases-book/

此外,还请参考这篇有关一些反模式(密集vs稀疏图)的文章,以补充Williamson的观点:https://neo4j.com/blog/dark-side-neo4j-worst-practices/

为了完整性,以下为想要更深入了解这个问题的人提供额外的部分:
回答Williamson本身关于决定是否应该将某些内容作为单独的顶点/节点,而不是将其留在文档顶点的属性上的标准:
它能够被单独访问吗?(例如:显示标签而不显示文档)
是的。浏览系统中可用的标签可能会很有用。
您是否会对其运行图测量(例如GRAPH_BETWEENNESS)?
不确定,可能不会。
它会被单独编辑吗?
是的,可能会。用户可以单独编辑它。也许管理员/版主想要清理标签名称(纠正拼写错误),或者清理它们的结构(如果您有子标签)。
标签是否具有自己的关系?(假设您关心)
是的。他们可以。子标签或其他类型的内容,而不仅仅是文档。实际上,点击标签并立即查看具有该标签的所有文档非常有用。使用属性数组将标签存储在每个文档上可能不是最优选择,而图形数据库从根本上针对查询与其他顶点(也称为节点)相邻的顶点的情况进行了优化。
该属性是否应存在其父顶点之外?
是的。即使删除了最后一个标记的文档,标记也可能/应该存在。有人以后可能想要使用该标签,并且它代表您可能想保留的领域信息。

3

您已经提到了大部分可用的决策标准。也许我可以补充一些:

文档内的关系标签可以使用数组索引对它们进行过滤,这可以使对它们的查询更快。然而,如果您想为该标签数组中的每个项目添加评级或解释,则无法实现。如果您想计算已标记的文档,则可能比计算从特定标签起源的所有边缘或查找与搜索条件匹配的所有标签更昂贵。

多模型的优势之一是,您不需要在这两种方法之间做出决策。您可以有一个边缘集合连接具有属性的标签和文档,并在文档内具有相同(平面)标签的索引数组。如果您发现所有(或大部分)查询都只使用一种方法,请尝试转换其余部分并删除其他解决方案。如果这行不通,那么您的应用程序就需要同时使用这两种方法。

在两种情况下,找到其他标记文档都可以在子查询中完成:

LET docs=(FOR ftDoc IN FULLTEXT(articles, 'text', 'search')
    COLLECT tags = ftDoc.tags INTO tags RETURN {tags, ftDoc})
LET tags = FLATTEN(FOR t IN docs[*].tags RETURN t)
LET otherArticles = (FOR oneTag IN tags 
    FOR oneD IN articles FILTER oneTag IN oneD.tag RETURN oneD._key)
RETURN {articles: docs, tags: tags, otherArticles: otherArticles}

1
很遗憾,针对您明确提出的问题,即连接文档是否可以自动显示在您的文档中,答案是否定的。我已经使用ArangoDB图形创建了单独的标签文档,但是我正在认真考虑将其转换为单个项目上的属性,因为标签似乎符合属性而不是相关项目的标准。Mike Williamson撰写了一篇不错的博客文章:https://mikewilliamson.wordpress.com/2015/07/16/data-modeling-with-arangodb/。他认为,从单个顶点到许多边缘会变慢,并且从受欢迎的Tag顶点到许多边缘也是如此。

我本来想在这里发表评论的,因为我基本上同意你分享的威廉姆森在文章中的观点。但我认为你可能读得有点快了。请看看我的回答:https://dev59.com/q5Tfa4cB1Zd3GeqPT6uz#55574236 - Magne

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