0

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:

  • Create the relationships between user and skill when skill is available and -
  • Skip this operation if no skill is not available.
  • Return newly created Project instance ?

Thanks

1
  • I think your first bullet should be "Create the relationships between project and skill when skill is available ...", correct? Commented Feb 23, 2019 at 2:02

1 Answer 1

1

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;
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your solution. Before your answer, I have to turn on the lenient match operation for neo4j by setting it in the configuration file. It worked, however, I don't like touching the configuration file much.
If you are talking about the "lenient" configuration setting in OGM, see this closed issue. There is some agreement that the default behavior should be "more lenient", but for possibly overall practical reasons, it has been decided to make it not that way. But most people will probably have no problems using the "lenient" setting.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.