0
votes

Trying to make a Cypher request which should create (or merge) files and create a relationship to a given root Folder (which may doesn't exists yet). There is a uniquness constraint on :FILE(fullpath) and :FOLDER(fullpath). The Code I have written looks like this:

     async public void createFiles(File[] files, Folder rootFolder)
     {
         var query = client.Cypher
             .Merge("(root:FOLDER {fullpath: {newRoot}.fullpath})")
             .Merge("(file:FILE {fullpath : {newFiles}.fullpath})")
             .Set("file = {newFiles}")
             .CreateUnique("root -[:CONTAINS]->(file)")
             .WithParam("newFiles", files)
             .WithParam("newRoot", rootFolder)
             .ReturnDistinct<int>("0");
         await query.ResultsAsync;
      }

But it throws an Neo4jClient.NeoException: ThisShouldNotHappenError: Developer: Andres claims that: Need something with properties exception. I think the Exception is thrown by the second .Merge. Isn't it possible to merge multiple nodes with an array as parameter? Is it a bug or is it my smelling code?

neo4j 2.1.3

1
Does files have a fullpath property? You use (file:FILE {fullpath : {newFiles}.fullpath}), but isn't newFiles an array of File? I don't know if that is part of the problem or not, just looks odd to me - Charlotte Skardon
that can be the issue. newFiles is a array with File Object (which have a fullpath property). I thought that the query tooks the .fullpath of each File in newFiles. But if this isn't the case, how to do it than? is there an other way, or is the only possible solution to foreach the c# way through the whole File[] and make a merge transaction for every node? - fadanner
There is a foreach clause in Cypher which might help you with this: docs.neo4j.org/chunked/stable/query-foreach.html Have you got your query working in the n4j user interface? - Charlotte Skardon

1 Answers

3
votes

fadanner,

Assuming all of the underlying parts are present in the parameters, you can do what you want by changing your query to this:

var query = client.Cypher
    .Merge("(root:FOLDER {fullpath : {newRoot}.fullpath})")
    .ForEach("(newFile IN {newFiles} | MERGE (file:FILE {fullpath : newFile.fullpath}) SET file = newFile CREATE UNIQUE (root)-[:CONTAINS]->(file))")
    .WithParam("newFiles", files)
    .WithParam("newRoot", rootFolder)
    .ReturnDistinct<int>("0");

I'm not a neo4jclient guy, so I may have some part of the syntax wrong, but this equivalent works with REST (at least I think its equivalent).

:POST /db/data/cypher
    {"query":"MERGE (n:Foo {name : {prop1}.name}) FOREACH(prop IN {prop2} | MERGE (m:Goo {name : prop.name}) SET m = prop CREATE UNIQUE (n)-[:HAS]->(m))", "params":{"prop1":{"name":"cat"},"prop2":[{"name":"boo","gleek":"math"},{"name":"oob","gleek":"spit"}]}}

Grace and peace,

Jim