使用Merge映射参数或通过客户端构建批处理操作?

时间:2014-02-18 20:53:00

标签: neo4jclient

有没有办法映射使用Merge传入的参数?

理想情况下,这就是我想要做的事情:

合并节点(如果不存在则创建,或更新整个节点属性 - 这是动态的)

MERGE(c:标签{Id:{map} .Id}) SET c = {map}

当地图是单个对象并且您只更新单个节点时,可以轻松完成此操作,但我希望能够以批量操作的方式执行此操作。
传入列表并拥有该自动地图。

当然,我认为目前使用Cypher Merge不会这样,但是可以使用REST API Batch方法完成,但是,如何使用Neo4jClient构建批处理并不清楚。

如果可能,如何构建一批合并操作? 我可以通过List枚举,并为每个对象添加一个合并操作到批处理。然后完整地执行批处理。

任何帮助都会很棒!


更新 所以,一个奇怪的副作用 - 当我运行这段代码时:

        createUniqueConstraint(label, PK_Field); 
        string propKey = label + "s" ;

        //string createstr = string.Format("(e:{0} { public void CreateNewRelationshipsFromMatrix<T>(IEnumerable<T> relationshipMatrix,   string IDFieldLeft, string IDFieldRight)
        where T : BaseModel
    {
        string entityName = GetTypeName(default(T)); //i.e. ContactAddress

        string merge1 = string.Format("(c:{0} {{{1}:row.{2}}})", IDFieldLeft.Replace("Id", ""), IDFieldLeft, IDFieldLeft);
        string merge2 = string.Format("(a:{0} {{{1}:row.{2}}})", IDFieldRight.Replace("Id", ""), IDFieldRight, IDFieldRight);
        string merge3 = string.Format("(c)-[r:{0}Link]->(a)", entityName);

        string uniqueRelationshipSetter = " ON CREATE SET r.weight=1 ON MATCH SET r.weight = r.weight + 1 ";

        foreach (var list in Neo4jDataRepository.Batch(relationshipMatrix, 1000))
        {
            var q1 = client.Cypher.Merge(merge1);
            var q2 = client.Cypher.Merge(merge2);
            var q3 = client.Cypher.Merge(merge3);

            var query = client
                        .Cypher
                        .WithParam("coll", list.ToList())
                        .ForEach("(row in {coll} | " +
                        q1.Query.QueryText + " " +
                        q2.Query.QueryText + " " +
                        q3.Query.QueryText + ")");
            query.ExecuteWithoutResults();
        }

    }
})", label, propKey);
        string strForEach = string.Format("(n in {{{0}}} |  MERGE (c:{1} {{{2} : n.{2}}}) SET c = n)",
            propKey, label, PK_Field);

        foreach (var entities in Neo4jDataRepository.Batch(list, 1000))
        {
            var query = client
                            .Cypher
                            .ForEach(strForEach)
                            .WithParam(propKey, entities.ToList());

            query.ExecuteWithoutResults();
            Debug.WriteLine("Batch passed for " + label + " ("+list.Count()+" items)");
            break;
        }

这很好(有点)。我有相关的节点,它们也包含一个与PK_Field同名的属性,我最终得到的节点只有一个属性而不是整个对象。

实施例: 联系{ContactId:1,名称:“David”}是一个对象的模型 ContactMembership {ContactMembershipId:1,ContactId:1,ContactMembershipTypeId:1} ContactMembershipType {ContactMembershipType:1,name:“User”}

运行此代码时,它首先遍历每个Models数组,然后使用上面的Merge语句添加/更新数据库中的那些。 在所有模型都在数据库中之后,它运行关系方法调用,它接受相关数据模型ContactMembership并使用此代码迭代它:

{{1}}

似乎是在第二次调用(已经存在的节点相关)期间,系统使用Label创建新节点:仅与ContactId属性联系而不与其他数据联系。 MATCH(n:联系方式) - [:ContactMembership] - (t)始终返回n的ContactId模型,而不是完整的联系模型。

MATCH(n) - [:ContactMembership] - (t)将返回t和n的完整模型。

不确定这里发生了什么......

1 个答案:

答案 0 :(得分:1)

FOREACH (n in {set} | MERGE (c:Label {Id : n.Id}) SET c = n)

http://docs.neo4j.org/chunked/stable/query-foreach.html

更新:即将推出的另一个选择是,您可以在Cypher中编写类似的内容:

LOAD CSV WITH HEADERS FROM 'file://c:/temp/input.csv' AS n
MERGE (c:Label { Id : n.Id })
SET c = n

https://github.com/davidegrohmann/neo4j/blob/2.1-fix-resource-failure-load-csv/community/cypher/cypher/src/test/scala/org/neo4j/cypher/LoadCsvAcceptanceTest.scala