Moving from v2.0 cypher to current one

(Paolodipietro58) #1

I'm an old neo4j user. I started using neo4j around 2008 and suspend in 2014 due to health problems.

Now I'm returning, installed the latest (?) community version with docker, and start my first task: importing 4 large excel tables into the DB, restructuring them before the operation.

As I saw that the LOAD CSV import command was heavily changed, I tried to use it at first, but it wasn't the right approac, because I must reorganize the data and not only import them as they were.

So I decided to write a simpe excel macro, able to convert Excel data in a series of query, using the same approach I've used 6 years ago, creating the following query fragment, repeated for how many times as the number of persons.:

:PARAM name: "Di Pietro Chiara - Gynecologist"     

MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25"})

MERGE (_cal_445:`calendar` { :`X-WR-CALNAME` = $name })-[:`belongs_to a`]-(_per_445:`person`) 
WHERE $name = _per_445.firstname + " " + _per_445.lastname
   OR $name = (_per_445.lastname+ " " + _per_445.firstname)
RETURN _cal_445, _per_445

But I find the following several difficulties:

  1. I want to use parameters, but, following the cypher Refcard, and some discussion on the web, Neo4j (the browser) doesn't accept my parameters declaration.The simple statement on top of the query returns an error.
    </> ```
2. The query itself: I need to MERGE a person, creating it if not present, or just aligning some attribute if already present
</> ```
MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25"})
  1. the following step is to create a subgraph connecting the above person with a calendar (this is to be created if not existing! My (old approach) solution was as follow:
MERGE (_cal_445:`calendar` { :`X-WR-CALNAME` = $name })-[:`belongs_to a`]-(_per_445:`person`) 

but the user logisima suggest me to correct a first error transforming that line in this way:

MERGE (_cal_445:`calendar` { `:X-WR-CALNAME`:$name })

Then he noted that I was doing a MERGE with the value $name that was also on the WHERE clause. It's just not allowed ...

and suggest to rebuild the query as follow:

MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25"})
WITH _200
MATCH (_cal_445:`calendar` { `:X-VR-CALNAME`: $name })-[:`belongs_to a`]-(_per_445:`person`) 

WHERE $name = _per_445.firstname + " " + _per_445.lastname
   OR $name = (_per_445.nome + " " + _per_445.cognome)

RETURN _cal_445, _per_445;

But this query, though running, doesn't produce the desired result, because it creates only the first person but not the calendar and not the relationship with the above person.

Now, after these reasonings, I argue that I have to 'merge' also the creation of the calendar, maybe alone.

but at this point, if I have the person and the Calendar, I must create the relationship:

Please, note that the parameter doesn run!

/* :PARAM name: "Di Pietro Chiara - Gynecologist" */  

MERGE (_200:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara", `birthdate`: "1984/03/25", `name`: "Di Pietro Chiara"})
WHERE = _200.firstname + " " + _200.lastname
   OR = (_200.firstname + " " + _200.firstname)

MERGE (_cal_445:`calendar` { `:X-WR-CALNAME`: $name })

CREATE (_CAL_445)-[:`belongs_to a`]-(_200:`person`) 

/* WHERE ( $name = 200_firstname + " " + 200_.lastname)
   OR $name = (_per_445.nome + " " + _per_445.cognome)
RETURN _cal_445, _200;

In any case, none of these query run!

Well, these are only reasonings, but, looking at the Cypher manual, I cannot understand what is wrong, or what is too legacy to evoid he query running!

I hope someone will be able to unleash these nodes!

(12kunal34) #2

Hi ,

Please find my cypher for your task
please change it according to your need

MERGE (_cal_445:person{Firstname:'kunal',Lastname:'GOYAL'})
MATCH (n:person) with n
MERGE (_cal_446:calendar{ NAME :n.Firstname+ " " + n.Lastname })

here first i am creating person node with data like first name and last name
after that i am creating calendar node and using person node detail

hope it will help you :slight_smile:

(Andrew Bowman) #3

Keep in mind that when working with the browser, the :param command shouldn't be executed as part of the Cypher query, as the command isn't Cypher, and is interpreted by the browser itself so it will send the configured parameter(s) under the hood to subsequent Cypher queries.

So first set the parameter(s), and after they're set then (separately) execute the Cypher.

Next, you can't use MERGE in combination with WHERE. Is your intent to set the name property to the combination of the firstname and lastname (such as if your MERGE resulted in node creation)? Or if it matched to a person, is your intent to filter and only continue processing when the name property is already set accordingly? Or did you want to set the name property in any case?

(Paolodipietro58) #5

MERGE (_pers_445:person{Firstname:'kunal',Lastname:'GOYAL'})
MATCH (n:person) with n
MERGE (_cal_446:calendar{ NAME :n.Firstname+ " " + n.Lastname })

returns the following error:

WITH is required between MERGE and MATCH (line 2, column 1 (offset: 61))
"MATCH (n:person) with n"

But my goal is to have a relationship between the calendar and the person, while your approach looks more relational

(Paolodipietro58) #6

The core question is about matching more condition on the same parameters.

I need to

// create or retrieve a calendar with a given name 
MERGE (_cal_445:`calendar` { `:X-WR-CALNAME`:  "Di Pietro Chiara - Gynecologist" })

// find (if any) the matching person
MATCH (person) 
   to return 0 or 1 instance
   where the firstname and fullname parameters, 
       concatenated together in any order and separated by a space
   match the initial part of the calendario.X-WR-CALNAME

// and finally, if a person exists, create the relationship between the person and the calendar

MERGE (person)-[`:uses calendar`]->(calendar)

(Andrew Bowman) #7

Got it, thanks for the clarification.

As for the message, it is rather clear, when you have MERGE followed by a MATCH you need a WITH clause in between. We'd need that anyway for your filtering condition on the name property (a WITH followed by a WHERE acts as a filter, similar to a MATCH and a WHERE).

That said, your clarification makes it seem like you don't want to create the person if they don't exist, so using MATCH instead of MERGE for the person seems like the right way to go.

If your name pattern is always the same (only a single "-" character separating the name from the occupation, you can split it to get just the name to match on later.

Try out this query. Note that if there is no person fitting the predicate, you won't get anything returned back:

WITH trim(split($name, '-')[0]) as name, $name as calendarName
MERGE (_cal_445:`calendar` { `:X-WR-CALNAME`: calendarName })
WITH name, calendarName, _cal_445
MATCH (_200:`person` {`name`: name})
WHERE = _200.firstname + " " + _200.lastname
   OR = _200.firstname + " " + _200.firstname
CREATE (_CAL_445)-[:`belongs_to a`]->(_200) 
RETURN _cal_445, _200;

(Paolodipietro58) #8

I agree ..... but how can I set the parameter(s)?


(Andrew Bowman) #9

That's interesting, it works for me. What version of Neo4j are you using, and what version of the browser (you can get both from the neo4j button in the lower left corner).

For help, :help param should work.

There is an alternate syntax you can use:
:param name => "Di Pietro Chiara - Gynecologist"
Give that a try

(Paolodipietro58) #10


Please, give a look at the following two responses (I need to insert 4 images!)

(Paolodipietro58) #11

maybe the core of the problem is exactly here: the person doesn't have a name property, but only the firstname and lastname

And I shouldn't want to load all the persons for each query, but this is secondary!

I tried with this query, where the first line is only to ensure that the right person is already present.

merge (x:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara"})

WITH "Di Pietro Chiara - Gynecologist" as calendarName
WITH trim(split(calendarName, '-')[0]) as fullname, calendarName
MERGE (_cal_445:`calendar` { `X-WR-CALNAME`: calendarName })
WITH fullname, calendarName, _cal_445
MATCH (_200:`person`)
WHERE fullname = _200.firstname + " " + _200.lastname
        OR fullname = _200.lastname + " " + _200.firstname

CREATE (_CAL_445)-[_rel:`belongs_to a`]->(_200) 

RETURN _cal_445, _rel,_200;

but it always produce 3 nodes and 1 relationship and the relationship is wrong!

This is the calendar, (correct!):

(Paolodipietro58) #12

... follow from the previous

this is the person (correct!)

but this is a ghost node (wrong, as the relationship, which should connect person and calendar)

(Paolodipietro58) #13

I use Neo4j 3.0.12 with the Neo4j Browser version 1.1.9, installed with docker on an Ubuntu 18.10 workstation with 16GB of RAM, running on a VMware workstation v12.5.9

The final correct solution is this one:

merge (x:`person` {`lastname`: "Di Pietro", `firstname`: "Chiara"})

WITH "Di Pietro Chiara - Gynecologist" as calendarName
WITH trim(split(calendarName, '-')[0]) as fullname, calendarName
MERGE (_cal_445:`calendar` { `X-WR-CALNAME`: calendarName })
WITH fullname, calendarName, _cal_445
MATCH (_200:`person`)
WHERE fullname = _200.firstname + " " + _200.lastname
        OR fullname = _200.lastname + " " + _200.firstname

MERGE (_cal_445)-[_rel:`belongs_to a`]->(_200) 

RETURN _cal_445, _rel,_200;

with responseTime: 811

(Paolodipietro58) #14

returns exatly the same error as the previous one.

Please, note that :help param also returns no such help topic.

and the link to the documentation are broken, because they points to the 3.0.12 version and returns a 404.

I'm using the current

(Andrew Bowman) #15

Okay, that makes sense now. You're using a very old version of Neo4j (3.0.x is 4 minor versions behind the current 3.4.x, with 3.5.x just about to be released within a month or so). Parameter support wasn't added to the browser until 3.1.x.

If possible please upgrade to the most recent version of Neo4j 3.4.10.