【问题标题】:Tinkerpop Blueprints Vertex QueryTinkerpop 蓝图顶点查询
【发布时间】:2013-04-21 18:57:04
【问题描述】:

我研究 Tinkerpop 堆栈已有一段时间了。我想我很清楚它可以做什么以及它适用于哪些数据库。我现在正在考虑几个不同的数据库,但还没有确定。所以我决定把我的代码纯粹写到接口上,现在不考虑 any 实现。在我正在查看的数据库中,它们实现了TransactionalGraphKeyIndexableGraph。我认为这足以满足我的需要,但我只有一个问题。

我有不同的“类”顶点。使用蓝图,我相信通过在每个顶点中包含类名的字段来最好地表示这一点。这样做,我可以做类似graph.getVertices("classname", "User") 的事情,它会给我所有的用户顶点。而且由于getVertices 函数指定实现应该使用索引,因此我可以保证快速查找(如果我索引该字段)。

但是假设我想根据两个属性检索一个顶点。顶点必须有className=Usersusername=admin。找到该单个顶点的最佳方法是什么?即使不是所有顶点都有username 字段,是否可以对这两个属性进行索引?

仅供参考 - 我目前考虑的数据库是 OrientDB、Neo4j 和 Titan,但我还没有确定。如果有帮助的话,我目前也计划使用 Gremlin。

【问题讨论】:

    标签: neo4j orientdb titan tinkerpop


    【解决方案1】:

    对顶点使用“类”或“类型”是分割它们的好方法。正在做:

    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。如果您只想找到一个(或一组具有该username 的顶点),那么对该属性进行键索引是更好的方法。

    即使我没有在其上创建键索引,我仍然在所有顶点上包含 typeclassname 属性。我发现它在我可能关心也可能不关心速度但只需要答案的全球运营中很有帮助。

    【讨论】:

    • 这个问题是我不能保证 User 类将是唯一具有用户名字段的顶点类。我们的数据模型灵活且可由用户间接编辑。不能保证不同类的顶点不会共享属性名称。
    • 完全没有问题。索引不需要唯一地标识特定用户(尽管它可以时很好)。使用索引让您关闭,然后过滤类。考虑以下区别:g.V('classname','user').has('username','admin')g.V('username','admin').has('classname','user')。首先必须获得所有用户(可能是数千或更多),然后循环它们以找到“管理员”。第二个要好得多,因为即使“用户名”在图中多次存在,它也可能不会返回数千个,因此您只需扫描一小部分即可找到“用户”类。
    • 或者,确保架构的唯一性。如果您不介意属性名称的冗长,则没有理由不能在其前面加上类型名称。因此,也许您觉得需要将用户名存储在“用户”类和“博客”类中(以表示谁写了一篇文章)。只需调用“user”类顶点属性“username”并调用“blog”类属性“blogUsername”。这样你就可以确保你的索引总是从一个类中返回一件事。
    【解决方案2】:
    1. graph.getVertices() 将遍历所有顶点并查找具有该属性的顶点,如果您没有在图形实现中打开自动索引。如果你已经有数据并且不能只打开自动索引器,你应该使用index = indexableGraph.getIndex()然后index.get('classname', 'User')

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

    是的,这些数据库很适合玩,我个人认为neo4j 是最简单的,只要您了解它们的许可结构,使用它们应该没有任何问题。

    【讨论】:

    • 好吧,正如您所说,查询在某种程度上是特定于实现的(不幸的是)。我想要随时切换数据库的能力,所以我只是编写了自己的查询包装器。感谢您的帮助。
    • 是的,很不幸,但大多数系统都是这样构建的,有些系统可能无法执行某些类型的查询,所以他们将其留给特定的实现。
    • graph.getVertices() 进行线性扫描并不完全正确。如果图实现了 KeyIndexableGraph(并且所有提到的三个图都实现了)并且指定的键是作为键索引创建的,则使用索引并避免线性扫描。 github.com/tinkerpop/blueprints/wiki/…
    • 抱歉,我忘记了自动索引器。我假设他在谈论如果他没有启用该功能。我已经更新了我的答案,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多