ArangoDB 批量创建边

qgzx9mmu  于 2022-12-09  发布在  Go
关注(0)|答案(1)|浏览(125)

我是ArangoDB的新手,但我一直在使用Arango-Net-Standard驱动程序,并成功地在C#中向图添加节点和边。
我可以使用此调用批量创建文档

await conn.Document.PostDocumentsAsync<Document>("my_document_collection", allDocuments, null)

但是我看不到一个明显的方法来批量创建边。一个复杂的因素是我不知道文档的id,所以必须在一个我知道的属性(uuid)上进行查找。
此AQL在Web前端工作。但我不确定如何使用ArangoDB-Net-Standard驱动程序来执行它。是否应先将其定义为数据库中的函数,然后使用“Cursor”端点调用它?
注意:我在真实的代码中动态构建了“数据”部分。

LET data = [
    {
        'parent': { 'from_uuid': '<parent-uuid>' },
        'child': { 'to_uuid': '<child1-uuid>' }     
    },
    {
        'parent': { 'from_uuid': '<parent-uuid>' },
        'child': { 'to_uuid': '<child2-uuid>' }     
    }   
]
    
FOR rel in data
    LET parentId = FIRST(
        FOR n IN nodes
            FILTER n.Properties.uuid == rel.parent.from_uuid
            LIMIT 1
            RETURN n._id
    )
    LET childId = FIRST(
        FOR n IN nodes
            FILTER n.Properties.uuid == rel.child.to_uuid
            LIMIT 1
            RETURN n._id
    )
    FILTER parentId != null AND childId != null
    INSERT { _from: childId, _to: parentId } INTO edges
    return NEW

谢谢

3phpmpom

3phpmpom1#

您可以使用Cursor API直接运行AQL查询,而无需创建单独的用户函数(除非您觉得它很有用)。
您概述的方法应该可以正常工作,文档在这里,但它对如何运行带参数的查询(“bindvar”)有点轻描淡写:https://github.com/Actify-Inc/arangodb-net-standard#run-an-aql-query
我创建并运行了一个单元测试来演示如何实现这一点。

var response = await _adb.Cursor.PostCursorAsync<dynamic>(aql, new Dictionary<string, object>
{
    ["edges"] = edges
});

下面是我创建的完整测试(_adbArangoDBClient的一个示例):

[Fact]
public async Task StackOverflow_Answer()
{
    await _adb.Collection.PostCollectionAsync(new ArangoDBNetStandard.CollectionApi.Models.PostCollectionBody
    {
        Name = "nodes"
    });
    await _adb.Collection.PostCollectionAsync(new ArangoDBNetStandard.CollectionApi.Models.PostCollectionBody
    {
        Name = "edges",
        Type = 3
    });

    var nodes = new[]
    {
        new
        {
            Properties = new 
            {
                uuid = 0
            }
        },
        new
        {
            Properties = new
            {
                uuid = 1
            }
        },
        new
        {
            Properties = new
            {
                uuid = 2
            }
        }
    };

    // Create all the documents first
    await _adb.Document.PostDocumentsAsync("nodes", nodes);

    var edges = new[] {
        new
        {
            parent = new
            {
                from_uuid = 0
            },
            child = new
            {
                to_uuid = 1
            }
        },
        new
        {
            parent = new
            {
                from_uuid = 1
            },
            child = new
            {
                to_uuid = 2
            }
        }
    };

    // Run your AQL query passing the "edges" as bind vars
    var aql = @"
        FOR rel in @edges
        LET parentId = FIRST(
            FOR n IN nodes
                FILTER n.Properties.uuid == rel.parent.from_uuid
                LIMIT 1
                RETURN n._id
        )
        LET childId = FIRST(
            FOR n IN nodes
                FILTER n.Properties.uuid == rel.child.to_uuid
                LIMIT 1
                RETURN n._id
        )
        FILTER parentId != null AND childId != null
        INSERT { _from: childId, _to: parentId } INTO edges
        return NEW
    ";

    var response = await _adb.Cursor.PostCursorAsync<dynamic>(aql, new Dictionary<string, object>
    {
        ["edges"] = edges
    });

    foreach (var item in response.Result)
    {
        _output.WriteLine($"Id {item._id}\nFrom: {item._from}\nTo: {item._to}\n");
    }
}

作为一种替代方案,您可以考虑编写一个AQL查询来基于UUID获取所需的文档,然后使用Document API单独发出一个批处理请求来添加Edge文档(没有什么可以阻止您通过Document API添加Edge文档,尽管它的名称是什么)。这种使用两个请求的方法最终可能比单一查询方法YMMV更快。
或者你可以使用Graph API,我不认为有一个使用Graph API的批处理方法,所以你需要为你想创建的每个边单独调用PostEdgeAsync
最佳方法还可能取决于一些因素,例如计划一次添加多少个文档/边,以及是否需要事务行为。

相关问题