Search code examples
neo4jneo4jphp

neo4jphp: Cypher and Resultset differ


seems I am too tired to find the solution, maybe someone has a hint for me.

I have built a graph in Neo4J which I connect via neo4jphp (everyman). Using the java browser the graph looks ok, every user exists one time and might have several groups he belongs to.

While creating the user I use MERGE in order to avoid them to be doubled - like

MERGE (user:PERSON {
firstname: "Max",
name: "Muster", 
password:"e52ddddddd9afb7b373f9da437",
title:"something",
login:"Nick",   
status:"active"   
}) 
ON CREATE SET user.uuid = "'.uniqid().'" // PHP function for a UUID
return user;

This works well as I see the correct number of users even when I resend the query or reload the page.

The users are connected with a query towards groups like this

MATCH (user:PERSON), (team:GROUP)      
WHERE user.name= "Muster" AND user.firstname="Max" AND team.name="LOCAL_USER"
CREATE (user)-[:IS_MEMBER_OF {role:"user", status:"active"}]->(team);

Checking this in the GUI of Neo4J shows a correct graph (at least from what I can see). I have the right amount of users and their relations.

When I query the graph directly by Cypher in the browser GUI like this

MATCH (user:PERSON {status: "active"})-[relation:IS_MEMBER_OF{status:"active"}]->(team:GROUP {name:"LOCAL_USER"} )
RETURN user
ORDER BY user.name;

I get the correct number of users.

When I use the neo4jphp lib (everyman) I receive some users double - the resultset has several elements with the same user. I couldnt figure out why they behave differently but I assume that I might have messed up the relations somehow. But still I am wondering why the same cypher query returns different amount of records when you send it via GUI or via everyman lib and I would need a hint how to change maybe the queries to make sure that I only get one record per user as every user is only one time connected to the LOCAL_USER group.

Thanks for pushing me to the right direction.


Solution

  • I think you get doubles because you have multiple paths (e.g. multiple teams) for the user, use RETURN distinct user

    For your import statement, you do it the wrong way round, instead of your approach.

    MERGE by unique id (e.g login in your case) and set the other properties with ON CREATE SET ...

    Also use parameters not literal values in your query strings !!

    MERGE (user:PERSON {login:{login}})
    ON CREATE SET
      user.firstname = {firstname}, user.name= {name}, user.password = {password},
      user.title={title}, user.status = {status}, user.uuid = {uuid}
    RETURN user;