【问题标题】:Sort direct neighbor nodes (books) by attribute of 2nd degree neighbors (authors) for user book list?按用户书籍列表的二级邻居(作者)的属性对直接邻居节点(书籍)进行排序?
【发布时间】:2017-09-01 12:41:35
【问题描述】:

来自 Slack 的 agheranimesh:

这是我的图表,名为 LibraryGraph

我的图表查询:

FOR v, e, p IN 1..2 OUTBOUND "User/001" GRAPH "LibraryGraph"
   SORT p.vertices[2].Name
   RETURN  p.vertices[1]

它没有给我想要的结果。我想要一个按作者姓名排序的书单,没有作者的书应该排在最后(B2、B3、B1、B4、B5)。

重新创建数据的脚本 (arangosh --javascript.execute <file>):

db._createDatabase('Library')
db._useDatabase('Library')

const User = db._create('User')
const Book = db._create('Book')
const Author = db._create('Author')

const User_Book = db._createEdgeCollection('User_Book')
const Book_Author = db._createEdgeCollection('Book_Author')

User.save({ '_key': '001', 'UserName': 'U1' })

Book.save({ '_key': 'B1', 'Name': 'B1' })
Book.save({ '_key': 'B2', 'Name': 'B2' })
Book.save({ '_key': 'B3', 'Name': 'B3' })
Book.save({ '_key': 'B4', 'Name': 'B4' })
Book.save({ '_key': 'B5', 'Name': 'B5' })

Author.save({ '_key': 'A', 'Name': 'A' })
Author.save({ '_key': 'B', 'Name': 'B' })
Author.save({ '_key': 'X', 'Name': 'X' })
Author.save({ '_key': 'Y', 'Name': 'Y' })
Author.save({ '_key': 'Z', 'Name': 'Z' })

User_Book.save({ '_from': 'User/001', '_to': 'Book/B1' })
User_Book.save({ '_from': 'User/001', '_to': 'Book/B2' })
User_Book.save({ '_from': 'User/001', '_to': 'Book/B3' })
User_Book.save({ '_from': 'User/001', '_to': 'Book/B4' })
User_Book.save({ '_from': 'User/001', '_to': 'Book/B5' })

Book_Author.save({ '_from': 'Book/B2', '_to': 'Author/A' })
Book_Author.save({ '_from': 'Book/B3', '_to': 'Author/B' })
Book_Author.save({ '_from': 'Book/B1', '_to': 'Author/X' })
Book_Author.save({ '_from': 'Book/B1', '_to': 'Author/Y' })
Book_Author.save({ '_from': 'Book/B1', '_to': 'Author/Z' })

const graph_module =  require('org/arangodb/general-graph')
const graph = graph_module._create('LibraryGraph')

graph._addVertexCollection('User')
graph._addVertexCollection('Book')
graph._addVertexCollection('Author')

graph._extendEdgeDefinitions(graph_module._relation('User_Book', ['User'], ['Book']))
graph._extendEdgeDefinitions(graph_module._relation('Book_Author', ['Book'], ['Author']))

【问题讨论】:

    标签: sorting graph arangodb graph-traversal aql


    【解决方案1】:

    我建议使用两次遍历,而不是使用具有可变深度 (1..2) 的单个遍历来涵盖两种情况,无论有作者还是没有作者的书籍:

    FOR book IN OUTBOUND "User/001" GRAPH "LibraryGraph"
        LET author = FIRST(
            FOR author IN OUTBOUND book._id GRAPH "LibraryGraph"
                SORT author.Name
                LIMIT 1
                RETURN author.Name
        ) OR "\uFFFF"
        SORT author
        RETURN book
    

    首先我们从User/001 遍历到链接的书籍。然后我们从每本书到链接的作者进行第二次遍历。这可能会返回 0、1 或多个作者。子查询将结果限制为按字母顺序排列的第一作者(例如 X、Y、Z 中的 X)并返回名称。

    在主查询的范围内,我们将作者姓名或回退到一个在排序后最后结束的值(null 将首先结束,这在此处是不需要的)。然后我们按作者姓名对书籍进行排序并返回:

    实现此结果的另一种方法,但更难理解:

    FOR v, e, p IN 1..2 OUTBOUND "User/001" GRAPH "LibraryGraph"
        LET name = p.vertices[2].Name OR "\uFFFF"
        COLLECT book = p.vertices[1] AGGREGATE author = MIN(name)
        SORT author
        RETURN book
    

    遍历返回具有 2 或 3 个顶点的路径...

       [0]         [1]         [2]
    User/001 --> Book/B2
    User/001 --> Book/B2 --> Author/A
    User/001 --> Book/B3
    User/001 --> Book/B3 --> Author/B
    User/001 --> Book/B4
    User/001 --> Book/B5
    User/001 --> Book/B1
    User/001 --> Book/B1 --> Author/Y
    User/001 --> Book/B1 --> Author/X
    User/001 --> Book/B1 --> Author/Z
    

    索引 2 (p.vertices[2]) 或备用值的作者临时存储在变量 name 中。然后将书本顶点组合在一起以消除重复(由变量遍历深度引起,返回例如001-->B2,但也返回更长的路径001-->B2-->A)。

    聚合用于选择具有最低值的作者姓名 (MIN),这通常意味着按字母顺序排列 - 但是对于某些语言和字符集,它可能无法正常工作,而 SORT 确实可以正确排序基于设置语言的规则(每个 DBMS 实例只能有一个)。

    分组结果 - 不同的书籍文档 - 按作者姓名排序并返回。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 2021-04-30
      • 2017-07-19
      • 2016-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多