使用图遍历路径中具有未知位置的边和顶点的ArangoDB AQL过滤

时间:2016-09-19 19:41:01

标签: arangodb aql

我有一个通用的图形结构,我需要根据它们与图形中其他节点的连接在图形中找到非叶节点。我想要返回的节点的位置没有定义,并且可能有多个路径到我想要返回的节点。我想运行一个查询,将我在排序列表中显示的一堆项目返回给客户端。我不想在客户端运行多个异步查询和排序。

此列表基于将顶点连接在一起的边缘进行过滤,或者节点是否连接到另一个节点。过滤条件在客户端更新,这会导致重新构建查询并重新查询数据库。图中节点的位置需要返回,并不保证所有结果都相同,它们可能是叶节点,也可能是路径中的任何位置。我想要返回的顶点可以通过通向它们的边缘上的属性来识别,或者远离它们。每个边缘上还有一个用于排序的日期属性和一个用于过滤的类型属性。

图表中的图片' myGraph'比如我试图在下面说明。

------- 
| v:1 |\
------- \
   | \   \ -------
   |  |   \| v:4 |\
   |  \    ------- \
   |   |  /   ^     \ -------
   |    \/    |      \| v:7 |
   |    /|  return    -------   
   |   /  \             
   |  /   |              
-------   \
| v:2 |\   |
------- \   \
   |     \ -------
   |      \| v:5 |\
   |       ------- \
   |                \ -------
   |                 \| v:8 |\
   |                  ------- \ 
   |                     ^     \ -------
   |                     |      \| v:10|
-------                return    -------   
| v:3 |\   
------- \   
         \ -------
          \| v:6 |\
           ------- \
                    \ -------
                     \| v:9 |
                      -------
                         ^
                         | 
                       return

上图说明了在给定一组过滤条件的情况下我想要返回的内容,但是如果我更改过滤条件,返回的结果可能会有所不同。我想要返回的节点可以根据通向它们或远离它们的边缘上的属性轻松识别。

我的查询看起来类似于以下内容,但我很难找到一种方法来索引路径中具有通向或远离它们的符合特定过滤条件的边缘的节点。

FOR item in vertexCollection1
   FILTER .... // FILTER the vertices
   FOR v, e, p IN 1..4 OUTBOUND item._id GRAPH 'myGraph'
      // ?? Not sure how to efficiently return from here
      // ?? FILTER p.vertices[??].v == 7 OR p.vertices[??].v == 10
      // ?? FILTER p.edges[??].type == "type1" OR p.edges[??].type == "type2"... etc based on user selections
      // ?? LET date = p.edges[vertexPosition - 1].date 
      // ?? LET data = p.vertices[??]
      // SORT DATE_TIMESTAMP(date) DESC
      // RETURN {date: date, data: data}

我目前正在使用[**]操作来根据它所使用的集合来获取特定节点,使用如下内容:

LET data = p.vertices[ ** FILTER CONTAINS(CURRENT._id, "collectionName") OR ...]

但这很尴尬,需要将顶点放在特定的集合中以方便查询构造。这也没有解决如何索引连接到我想要返回的节点的相关边的问题。

如果这个问题在其他地方得到解答,我道歉,如果它是指向答案的指针,我将不胜感激。我不确定用正确的术语来简明地描述问题并进行相应的搜索。

谢谢!

1 个答案:

答案 0 :(得分:2)

我能够使用类似于以下内容的查询获得我需要的行为:

LET events = (
FOR v, e, p IN 1..3 OUTBOUND 'collection/document_id' GRAPH 'myGraph' OPTIONS {"uniqueEdges": "global"}
    FILTER .... // Filter the vertices
    LET children = (
        FOR v1, e1, p1 IN 1..1 OUTBOUND v._id GRAPH 'myGraph'
            FILTER e1.type == "myEventType" OR ... // Filter immediate neighbors I care about
            SORT(e1.date)  // I have date timestamps on everything
            RETURN { child: v1._id, ... /* other child attributes as needed */ }
    )

    // FILTER .... conditions on children if necessary in context of v

    RETURN DISTINCT (data: v, children: children, ... /* other attributes as needed */ )
)

FOR event IN events
    SORT(event.date) // I need chronological sorting and have date attribute on every node
    RETURN event

RETURN子句上的DISTINCT修饰符似乎删除了由同一节点的多个路径产生的重复项,并且我能够根据各个子节点和父节点上的属性添加我需要的自定义过滤器。

我不确定这是否是最佳或正确的方法,但它适用于我的用例。如果有更正或优化,请告诉我。

谢谢!

---性能更新

我目前正在使用大约700000个文档和2000000个边缘的图表进行测试。过滤条件会根据Web应用程序中的用户选择动态添加到查询中,查询的性能在很大程度上取决于添加的过滤条件。如果没有过滤器或非常广泛的过滤条件,查询可能需要一秒钟才能执行(在我们的测试硬件上)。如果过滤条件非常严格,则查询可以在几毫秒内执行。但是,默认情况下,最常见的用例是查询的较慢版本。我只使用一小部分数据,我们希望文档和边缘的数量增长到数百万的数量,因此我们扩展的性能非常令人担忧。我目前已将数据库分割为多个图形,以尝试减少任何单个查询可扫描的节点/边缘的范围和数量,但尚未确定我可以进行的其他优化,以允许查询随着数据集的缩放而缩放。我们目前正在努力改进我们的数据导入基础设施以扩展数据集,但还没有完成这项工作,所以我还没有在数据库上有任何更能代表我们预期配置的性能数据。