4

can't find whether this has been asked before or not, so bear with me.
I'm just starting to use Neo4j with a nodejs backend and the neo4j-driver driver. I wonder if it's possible to create a node with several properties without enumerating each one in the second argument to the session.run method.

app.post("/signup", function(req, res) {
    var user = req.body; //{userId: "johnsmith", email: "john@smith.com", ...}
    session.run("CREATE (u:User {u}) RETURN u", user).then(function(response) {
        /*do stuff with newly created user*/
    }, function() {
        //handle error
    });
});

Currently, this yields the following error: {code: 'Neo.ClientError.Statement.ParameterMissing', message: 'Expected a parameter named u' }, and if I change the above to:

app.post("/signup", function(req, res) {
    var user = req.body; //{userId: "johnsmith", email: "john@smith.com", ...}
    session.run("CREATE (u:User {u}) RETURN u", {u: user}).then(function(response) {
        /*do stuff with newly created user*/
    }, function() {
        //handle error
    });
});

then the error reads: { code: 'Neo.ClientError.Statement.TypeError', message: 'Property values can only be of primitive types or arrays thereof' }.

This doesn't make much sense to me, given that the refcard clearly states you can create a node using a map, like so: CREATE (n {map}); so I must obviously be getting something wrong. I hope I don't have to enumerate all a user's properties like so:

session.run("CREATE (u:User {userId: {u.userId}, email: {u.email}, ...}) RETURN u", {u: user}).then(/*...*/)

Thanks in advance

4

2 回答 2

2

For example:

app.post("/signup", function(req, res) {
    var params = {};
    //{userId: "johnsmith", email: "john@smith.com", ...}
    Object.keys(req.body).forEach( function(k) {
        var value = req.body[k];
        if (!isPrimitive(val)) value = JSON.stringify(value);
        params[k] = value;
    });

    session.run("CREATE (u:User) SET u = {user} RETURN u", {user: params})
        .then(function(response) {
            // do stuff with newly created user
        }, function() {
            // handle error
        });
});

Where isPrimitive an abstract function that checks whether a variable is a primitive.

于 2017-02-13T22:27:06.713 回答
2

Neo4j only supports storing specific kinds of data structures to a property. To quote from the Cypher Refcard:

Neo4j properties can be strings, numbers, booleans or arrays thereof.

And, to be more exact, in order for an array (or "collection") to be stored as a property value, all its elements must be of the same primitive type.

The answer from @stdob-- provides one possible simple workaround to this (but it stringifies all arrays, even ones that can be stored without conversion).

NOTE: The refacrd needs to be a bit more clear. Nested maps are supported, in general. For instance, you can freely pass in JSON data as Cypher query parameters. However, maps containing nested maps are NOT supported for storing as property values.

于 2017-02-13T23:06:56.613 回答