我有一个代表游戏中等级的图表。我所拥有的节点类型的一些示例是“Level”,“Room”,“Chair”。这些类型由VertexCollections表示,其中一个集合称为“级别”等。它们通过来自单独EdgeCollections的边连接,例如“Level”-roomEdge->“Room”-chairEdge->“Chair”。房间也可以包含房间等,所以深度不明。
我想从任意“Level”-vertex开始并遍历整个子树并找到属于该级别的所有椅子。
我试图看看ArangoDB对我来说是否比OrientDB更好,在OrientDB中我使用了查询:
SELECT FROM (TRAVERSE out() FROM startNode) WHERE @class = 'Chair'
我尝试过AQL查询:
FOR v IN 1..6 OUTBOUND @startVertex GRAPH 'testDb' FILTER IS_SAME_COLLECTION('Chair', v) == true RETURN v;
然而,与OrientDB查询相比,它似乎执行得慢得多(约1秒vs~0.1秒)。
我用于查询的代码如下:
String statement = "FOR v IN 1..6 OUTBOUND @startVertex GRAPH 'testDb' FILTER IS_SAME_COLLECTION('Chair', v) == true RETURN v";
timer.start();
ArangoCursor<BaseDocument> cursor = db.query(statement, new MapBuilder().put("startVertex", "Level/"+startNode.getKey()).get(), BaseDocument.class);
timer.saveTime();
两种解决方案都在相同的硬件上运行而没有进行任何优化,两个数据库都是“开箱即用”的。两种情况都使用相同的数据(约100万个顶点)并返回相同的结果。
所以我的问题是,如果我在AQL查询中正确地做事,或者有更好的方法吗?我是否误解了VertexCollections的概念以及如何使用它们?
您是否有理由为每种实体类型设置多个集合,例如一个集合用于房间,一个用于级别,一个用于椅子?
一种选择是拥有一个包含您的实体的集合,并使用文档中的type: "Chair"
或type: "Level"
键来标识它的实体类型。
然后你有一个单一的关系集合,它保持实体集合的_to
和_from
边缘。
然后,您可以从给定节点(例如Level)开始,并使用以下查询查找与其连接的所有Chair类型的实体:
FOR v, e, p IN 1..6 OUTBOUND Level_ID Relationship_Collection
FILTER p.vertices[-1].Type == 'Chair'
RETURN v
您可以返回v(最终顶点)或e(最终边缘)或p(所有路径)。
我不确定您是否需要使用图形对象,而是使用可以为实体集合添加关系的关系集合。
如果需要,图表很好,但对于遍历查询不是必需的。阅读ArangoDB上的文档,看看是否需要它们,通常我不使用它们,因为使用图表可能会降低性能。
请记住查看索引,并使用UI中的“Explain”功能查看索引的使用方式。也许在'Type'键中添加一个哈希索引。