Tinkerpop蓝图顶点查询

3
我已经研究了Tinkerpop技术栈很长一段时间。我认为我对它的功能以及它适用的数据库有很好的了解。我目前考虑了几个不同的数据库,但还没有决定使用哪一个。因此,我决定纯粹地按接口编写代码,暂时不考虑任何具体实现。在我所看的数据库中,它们都实现了TransactionalGraphKeyIndexableGraph。我认为这已经足够满足我的需求了,但我有一个问题。
我有不同的顶点类。使用Blueprints,我认为最好的方式是在每个顶点中添加一个包含类名的字段来表示。这样,我就可以像graph.getVertices("classname", "User")这样做,并获取所有用户顶点。由于getVertices函数指定一个实现应该利用索引,所以我可以保证快速查找(如果我对该字段进行索引)。
但是,假设我想基于两个属性检索一个顶点。该顶点必须具有className=Usersusername=admin。最好的方法是什么?是否可能对这两个属性都建立索引,即使并非所有顶点都有username字段呢?
FYI- 我目前正在考虑的数据库是OrientDB、Neo4j和Titan,但我还没有最终决定。我目前也计划使用Gremlin,如果这有所帮助。
2个回答

4
使用“类”或“类型”对顶点进行分段是一种很好的方法。例如:
graph.createKeyIndex("classname",Vertex.class);
graph.getVertices("classname", "User");

这是一种相当常见的模式,通常应该可以快速查找,不过如果你打算将特定的classname增长到非常大的规模,那么迭代数千万用户的索引可能并不好。我认为这会导致你第二个问题的提出,即关于进行两个属性查找的问题。

就你举的例子而言,进行两个元素的查找可能是这样的(使用 Gremlin):

g.V('classname',"User").has('username','admin')

所以,您可以将顶点缩小到只有具有关键索引的“用户”顶点,然后筛选其中的“管理员”。但是,我会以不同的方式对其进行建模。更便宜的方法是只需执行以下操作:

graph.createKeyIndex("username",Vertex.class);
graph.getVertices("username", "admin");

或者在Gremlin中:

g.V('username','admin')

如果您知道所需的用户名,那么建模是没有更好/更快的方法。如果您仅想查找一个(或一组具有该用户名的顶点),则在该属性上进行关键索引是更好的方式,真正需要classname只是为了迭代所有“User”顶点。
即使我没有在其上创建关键索引,我仍然在所有顶点上包含一个typeclassname属性。我发现这在全局操作中非常有用,可能并不关心速度,但只需要一个答案。

问题在于我无法保证User类将是唯一具有用户名字段的顶点类。我们的数据模型是灵活的,并且可以由用户间接编辑。不保证不同类别的顶点不会共享属性名称。 - GJK
1
完全没有问题。索引不需要唯一标识特定的用户(尽管它可以这样做很好)。使用索引让你接近目标,然后按类别进行过滤。考虑以下两种方式的区别:g.V('classname','user').has('username','admin')g.V('username','admin').has('classname','user')。第一个必须获取所有用户(可能有成千上万个),然后循环查找“admin”。第二个更好,即使在图中存在多个'username',它也不太可能返回数千个结果,因此您只需扫描少量内容即可找到'user'类别。 - stephen mallette
1
或者,在您的模式中确保唯一性。如果您不介意在属性名称中使用冗长的前缀,那么您完全可以在其前面加上类型名称。因此,也许您觉得需要将用户名存储在“用户”类和“博客”类(以表示谁写了一篇文章)中。只需将“用户”类顶点属性命名为“username”,将“博客”类属性命名为“blogUsername”。这样,您就可以确保索引始终从一个类返回一个内容。 - stephen mallette

3
  1. graph.getVertices()将遍历所有顶点,并查找具有该属性的顶点,如果您的图实现未启用自动索引。如果您已经拥有数据,无法仅打开自动索引器,则应使用index = indexableGraph.getIndex(),然后index.get('classname', 'User')

  2. 可以在多个对象上执行query,但没有具体细节很难说。对于Neo4j,它们使用Lucene,这意味着query()将采用Lucene查询,例如className:Users AND username:admin,但我不能代表其他人发表意见。

是的,这些数据库都适合玩耍,我个人发现neo4j最容易使用,只要您理解他们的许可结构,就不应该有任何使用问题。


好的,正如你所说,这些查询有点特定于实现(不幸的是)。我想随时切换数据库,所以我自己编写了查询包装器。感谢你的帮助。 - GJK
是的,这很不幸,但大多数系统都是这样构建的,有些系统可能没有执行某些类型查询的能力,因此它们留给实现特定的部分。 - Nicholas
graph.getVertices() 做了线性扫描并不完全正确。如果图实现了 KeyIndexableGraph(三个提到的图都是),并且指定的键是作为索引创建的键,则使用该索引可以避免进行线性扫描。https://github.com/tinkerpop/blueprints/wiki/Graph-Indices#keyindexablegraph-and-fast-lookup-of-elements-by-keyvalue-pairs - stephen mallette
抱歉,我忘了自动索引器。我以为他在说如果没有启用它。我已更新我的答案,谢谢。 - Nicholas

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