Andrea Aloi
Andrea Aloi

Reputation: 991

Neo4j + nodejs: create node using javascript object literal

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: "[email protected]", ...}
    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: "[email protected]", ...}
    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

Upvotes: 4

Views: 1495

Answers (2)

cybersam
cybersam

Reputation: 66989

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.

Upvotes: 2

stdob--
stdob--

Reputation: 29172


For example:

app.post("/signup", function(req, res) {
    var params = {};
    //{userId: "johnsmith", email: "[email protected]", ...}
    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.

Upvotes: 2

Related Questions