Redplane
Redplane

Reputation: 3151

Merge non-existing node and return the source node in Neo4j

I'm using neo4j as my database in my little application. My application is about managing candidates' CV (Resume').

This is my diagram :

CV Management

For now, what I'm doing is to add a project with a list of skills that the project uses.

This is my neo4j query:

MATCH (user: User)
WHERE (user.Id = "74994fd8-40bb-48e8-adf1-bc11eeb6c035")
WITH user
MERGE (project: Project {Id: '02d5ad72-036c-47e9-a366-d5ca4a3e66e2'})
ON CREATE
SET project = {
  Id: "02d5ad72-036c-47e9-a366-d5ca4a3e66e2",
  Name: "VINCI GTR",
  Description: "Description of VINCI GTR",
  StartedTime: 0.0
}
MERGE (user)-[:DID_PROJECT]->(project)
WITH project, user
MATCH (user)-[:HAS_SKILL]->(skill: Skill)
WHERE skill.Id IN []
MERGE (project)-[:USED_SKILL]->(skill)
RETURN project

In my query, I use: WHERE skill.Id IN [] to make sure my skills list is empty, because I want to simulate a situation that there is no skill available.

When I run the command, I cannot receive the newly created project, even it has been created in database. I have this result instead:

Neo4j result

How can I:

Thanks

Upvotes: 0

Views: 186

Answers (1)

cybersam
cybersam

Reputation: 66967

A MATCH clause that fails to match aborts the rest of the query (and the query will return nothing).

The following snippet will never match anything, since it is trying to match user nodes that have a related skill node whose Id value matches a nonexistent value (which makes no sense):

MATCH (user)-[:HAS_SKILL]->(skill: Skill)
WHERE skill.Id IN []

To only create the USED_SKILL relationship if user does not have a skill, do this:

MATCH (user: User)
WHERE user.Id = "74994fd8-40bb-48e8-adf1-bc11eeb6c035"
MERGE (project: Project {Id: '02d5ad72-036c-47e9-a366-d5ca4a3e66e2'})
ON CREATE
  SET project += {
    Name: "VINCI GTR",
    Description: "Description of VINCI GTR",
    StartedTime: 0.0
  }
MERGE (user)-[:DID_PROJECT]->(project)
WITH project, user
WHERE SIZE((user)-[:HAS_SKILL]->()) = 0
MERGE (project)-[:USED_SKILL]->(skill)
RETURN project

This query does a degree-ness check on each user node to find the ones that have no HAS_SKILL relationships (we deliberately omit the :Skill label from the opposite node in the pattern, which is a kind of hack to cause the Cypher planner to generate a more efficient operation). Also, we use SET += instead of SET = so that we don't replace all the node properties, allowing us to avoid having to overwrite the Id value with the same value.

By the way:

The HAS_SKILL_CATEGORY relationship seems to be redundant. If a user's skills can all be reached via HAS_SKILL relationships, then you can already get that user's categories via something like this:

MATCH (user: User)-[:HAS_SKILL]->()-[:BE_IN_SKILL_CATEGORY]->(c)
WHERE user.Id = "74994fd8-40bb-48e8-adf1-bc11eeb6c035"
RETURN c;

Upvotes: 1

Related Questions