6

我找到了一些在关系文档数据库中设置标记系统的建议,但对于图形/多模型数据库却没有。

我正在尝试在 ArangoDB 中为文档(我们称它们为“文章”)建立一个标记系统。我可以想到两种在像 Arango 这样的多模型(图形+文档)数据库中存储标签的明显方法:

  • 作为每个文章文档中的数组(文档数据库样式)
  • 作为一个单独的文档类,每个标签作为一个唯一的文档,边将标签文档连接到文章文档(更接近于关系数据库样式)

这些实际上是做到这一点的两种主要方法吗?两者似乎都不理想。例如:

  • 如果我在每个文章文档中存储标签,我可以索引标签,并且大概 ArangoDB 正在优化它们使用的空间。但是,我不能使用图形功能来链接或遍历标签(或者我必须单独进行)。
  • 如果我将标签存储为单独的标签文档,那么当我只想获取文档上的标签列表时,这似乎是额外的开销(额外的查询)。

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

也欢迎一般建议。

4

3 回答 3

3

@Joachim Bøggild 链接到 Mike Williamson:https ://mikewilliamson.wordpress.com/2015/07/16/data-modeling-with-arangodb/

我同意威廉姆森的观点,即“默认紧凑”通常是要走的路。然后,如果/当实际需要出现时,您可以从属性中提取顶点(又名节点)。它还避免了创建过度互连的图形结构,这对于各种遍历查询来说都很慢。

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

威廉姆森似乎同意标签需要特别考虑

“但并非所有东西都属于一起。任何包含复杂数据结构的属性(如“comments”数组或“tags”数组)都值得仔细研究,因为它可能作为一个顶点(或多个顶点)本身有意义。”

@ropeladder 的原始问题提出了主要的反对意见,即它需要额外的开销(额外的查询)。我认为在这个阶段过多地考虑性能可能是为时过早的优化。毕竟; 额外的查询可能很快,或者它实际上可能与原始查询结合并包含在原始查询中。无论如何,我会引用这个:

“一般来说,尝试合并节点以保持查询时间效率是一种不好的做法。如果我们根据我们想对数据提出的问题进行建模,那么将出现对该领域的准确表示。图形数据库即使在存储大量数据时也能保持快速的查询时间。在学习构建我们的图而不对其进行非规范化时,学会信任我们的图数据库非常重要。” --- 从第 64 页的“避免反模式”一章开始,在“图形数据库”一书中,由另一个非常流行的原生图形数据库 Neo4j 的创始人 Eifrem 合着。它是免费的,可在此处在线获取:https ://neo4j.com/graph-databases-book/

另请参阅这篇关于一些反模式(密集图与稀疏图)的文章,以补充威廉姆森的观点:https ://neo4j.com/blog/dark-side-neo4j-worst-practices/


为了完整起见,为那些想要更深入地研究这个问题的人提供了额外的部分:

回答威廉姆森自己的标准来决定某个东西是否应该是一个顶点/节点,而不是把它作为文档顶点的一个属性:

它会被自己访问吗?(即:显示没有文档的标签)

是的。浏览系统中可用的标签可能很有用。

您会对其进行图形测量(如 GRAPH_BETWEENNESS)吗?

不确定。可能不会。

会自己编辑吗?

很可能是。用户可以单独编辑它。也许管理员/版主想要清理标签名称(纠正拼写错误),或者清理它们的结构(如果你有子标签)。

标签是否/可以有它自己的关系?(假设你关心)

是的。他们可以。子标签或其他类型的内容,而不仅仅是文档。实际上,能够单击标签并立即查看带有该标签的所有文档非常有用。如果将标签存储为每个文档上的属性数组,这可能是次优的。而图形数据库从根本上针对查询与其他顶点(又名节点)相邻的顶点的情况进行了优化。

如果没有它的父顶点,这个属性会/应该存在吗?

是的。即使最后一个标记的文档被删除,标记也可能/应该存在。稍后有人可能想要使用该标签,它代表您可能想要保留的域信息。


于 2019-04-08T13:08:43.077 回答
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}
于 2016-03-08T08:43:33.247 回答
1

不幸的是,对于您关于连接的文档是否可以自动显示在您的文档中的明确问题的答案是否定的。我已经制作了一个带有单独标签文档的 ArangoDB 图,但我正在认真考虑将其转换为单个项目的属性,因为标签似乎遵循作为属性而不是相关项目的标准。

Mike Williamson 对此做了一篇不错的博客文章:https ://mikewilliamson.wordpress.com/2015/07/16/data-modeling-with-arangodb/

他认为,单个顶点有很多边是很慢的,流行的 Tag 顶点的边数就是这种情况。

于 2016-03-08T13:11:53.933 回答