Neo4j Cypher WITH is required between CREATE and MATCH - neo4j

I want to execute several queries at the same time on the browser console, here are my requests :
CREATE (newNode1:NEW_NODE)
CREATE (newNode2:NEW_NODE)
MATCH (n1:LABEL_1 {id: "node1"}) CREATE (newNode1)-[:LINKED_TO]->(n1)
MATCH (n2:LABEL_2 {id: "node2"}) CREATE (newNode2)-[:LINKED_TO]->(n2)
When I execute them one by one there is no problem, but when I execute them at the same time, I get the following error :
WITH is required between CREATE and MATCH
Is there any way to correct this?

Add a couple of WITHs?
CREATE (newNode1:NEW_NODE)
CREATE (newNode2:NEW_NODE)
WITH newNode1, newNode2
MATCH (n1:LABEL_1 {id: "node1"})
CREATE (newNode1)-[:LINKED_TO]->(n1)
WITH newNode1, newNode2
MATCH (n2:LABEL_2 {id: "node2"})
CREATE (newNode2)-[:LINKED_TO]->(n2)
Alternatively, you could do it in a different order and avoid the WITHs, the difference being that it won't create anything if n1/n2 don't MATCH.
MATCH (n1:LABEL_1 { id: "node1" })
MATCH (n2:LABEL_2 { id: "node2" })
CREATE (newNode1:NEW_NODE)-[:LINKED_TO]->(n1)
CREATE (newNode2:NEW_NODE)-[:LINKED_TO]->(n2)

Related

How to verify if a node exist and if not exist then a created during an import of .csv to neo4j

I am importing some .cvs files for my database in neo4j, but I have the data of people in three different files, so when I import the data of the person from another file that has more data, I get an error when trying to import people nodes, because I already have other nodes with those dni (constraint) in my database.
So I want to create the new node or, if it exists, retrieve its pointer to create relationships with other nodes that I keep creating while I import.
I have tried several things on the internet but I still can't find the solution
Here my code:
LOAD CSV WITH HEADERS FROM 'file:/D:/ACCOUNT.csv' AS line FIELDTERMINATOR ';'
MERGE (persona :Persona { dni: line.DNI,
nombre: line.NOMBRE,
sexo: line.SEXO,
fechaNacimiento: line.FNACIMIENTO,
direccion: line.DIRECCION
})
I have tried with apoc and "with" but I still can't find the solution.
when this code finds another node with a person label and ID equal to the one entered, it gives me an error
To get this working, you'll have to understand how MERGE works. The statement
MERGE (persona :Persona { dni: line.DNI, nombre: line.NOMBRE, sexo: line.SEXO,
fechaNacimiento: line.FNACIMIENTO,direccion: line.DIRECCION
})
will create a new Persona node for every distinct combination of the above properties. So, for a node with the same dni, but with other values of other properties, this will fail. To fix this, you should try merging the nodes on the basis of their dni, and then set the properties like this:
MERGE (persona :Persona { dni: line.DNI })
ON CREATE
SET persona.nombre = line.NOMBRE,
persona.sexo = line.SEXO,
persona.fechaNacimiento = line.FNACIMIENTO,
persona.direccion = line.DIRECCION
The above query will ignore setting properties if a matching node is found. To set some properties when a match is found, use ON MATCH, like this:
MERGE (persona :Persona { dni: line.DNI })
ON CREATE
SET persona.nombre = line.NOMBRE,
persona.sexo = line.SEXO,
persona.fechaNacimiento = line.FNACIMIENTO,
persona.direccion = line.DIRECCION
ON MATCH
// Matching logic here

GraphDB - get paths among different types of nodes

I have a graph DB (using Neo4J) consisting of 5 types of nodes, e.g. filename, type1, type2, type3 and type4.
CREATE (:type1{name:type1_A})
CREATE (:type1{name:type1_B})
CREATE (:type2{name:type2_A})
CREATE (:type2{name:type2_B})
CREATE (:type3{name:type3_A})
CREATE (:type3{name:type3_B})
CREATE (:type4{name:type4_A})
CREATE (:type4{name:type4_B})
CREATE (:filename{name:1A_2A_3A_4A})
CREATE (:filename{name:1A_2A_3A_4A_another})
CREATE (:filename{name:1A_2B_3A_4A})
CREATE (:filename{name:1A_2A_3B_4A})
CREATE (:filename{name:1A_2A_3A_4B})
For each filename, I created 4 links (with same relationship name) as follows:
MATCH(n:type1 {name:'type1_A'}) MATCH(f:filename {name:'1A_2A_3A_4A}) CREATE (n)-[:linked_to]->(f)"
MATCH(n:type2 {name:'type2_A'}) MATCH(f:filename {name:'1A_2A_3A_4A}) CREATE (n)-[:linked_to]->(f)"
MATCH(n:type3 {name:'type3_A'}) MATCH(f:filename {name:'1A_2A_3A_4A}) CREATE (n)-[:linked_to]->(f)"
MATCH(n:type4 {name:'type4_A'}) MATCH(f:filename {name:'1A_2A_3A_4A}) CREATE (n)-[:linked_to]->(f)"
and so on for the other filenames.
Now, for instance, I'd like to get all paths involving filename nodes linked to type1_A AND type2_A AND type3_A AND type4_A. In this case, I except '1A_2A_3A_4A' and '1A_2A_3A_4A_another' nodes and corresponding paths to type1_A, type2_A and type3_A nodes.
Can anyone suggest me the corresponding Cypher query?
Thanks
Try the below and see if gets you what you're looking for.
MATCH
(f:filename),
(t1:type1 {name: "type1_A")-[t1lt:linked_to]->(f),
(:type2 {name: "type2_A")-[:linked_to]->(f),
(:type3 {name: "type3_A")-[:linked_to]->(f),
(:type4 {name: "type4_A")-[:linked_to]->(f)
RETURN f, t1, t1lt

Neo4j cypher query fails with unknown syntax error

I have the following paramObj and dbQuery
paramObj = {
email: newUser.email,
mobilenumber: newUser.telephone,
password: newUser.password,
category: newUser.category,
name: newUser.name,
confirmuid: verificationHash,
confirmexpire: expiryDate.valueOf(),
rewardPoints: 0,
emailconfirmed: 'false',
paramVehicles: makeVehicleArray,
paramVehicleProps: vehiclePropsArray
}
dbQuery = `CREATE (user:Person:Owner {email:$email})
SET user += apoc.map.clean(paramObj,
['email','paramVehicles','paramVehiclesProps'],[])
WITH user, $paramVehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
CREATE UNIQUE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v`;
Then I tried to execute
commons.session
.run(dbQuery, paramObj)
.then(newUser => {
commons.session.close();
if (!newUser.records[0]) {........
I am getting
Error: {"code":"Neo.ClientError.Statement.SyntaxError","name":"Neo4jError"}
which doesn't direct me anywhere. Can anyone tell me what am I doing wrong here?
This is actually the first time I am using the query format .run(dbQuery, paramObj) but this format is critical to my use case. I am using Neo4j 3.4.5 community with apoc plugin installed.
Ok...so I followed #inversFalcon suggestion to test in browser and came up with following parameters and query that closely match the ones above:
:params paramObj:[{ email:"xyz123#abc.com", mobilenumber:"8711231234",password:"password1", category:"Owner",name:"Michaell",vehicles:["Toyota","BMW","Nissan"],vehicleProps: [] }]
and query
PROFILE
CREATE (user:Person:Owner {email:$email})
SET user += apoc.map.clean($paramObj, ["email","vehicles","vehicleProps"],[])
WITH user, $vehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
MERGE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v;
Now I get
Neo.ClientError.Statement.TypeError: Can't coerce `List{Map{name -> String("Michaell"), vehicles -> List{String("Toyota"), String("BMW"), String("Nissan")},.......
I also reverted to neo4j 3.2 (re: an earlier post by Mark Needham) and got the same error.
You should try doing an EXPLAIN of the query using the browser to troubleshoot it.
A few of the things I'm seeing here:
You're referring to paramObj, but it's not a parameter (rather, it's the map of parameters you're passing in, but it itself is not a parameter you can reference in the query). If you need to reference the entire set of parameters being passed in, then you need to use nested maps, and have paramObj be a key in the map that you pass as the parameter map (and when you do use it in the query, you'll need to use $paramObj)
CREATE UNIQUE is deprecated, you should use MERGE instead, though be aware that it does behave in a different manner (see the MERGE documentation as well as our knowledge base article explaining some of the easy-to-miss details of how MERGE works).
I am not sure what caused the coercion error to disappear but it did with the same query and I got a "expected parameter error" this was fixed by using $paramObj.email, etc. so the final query looks like this:
CREATE (user:Person:Owner {email: $paramObj.email})
SET user += apoc.map.clean($queryObj, ["email","vehicles","vehicleProps"],[])
WITH user, $paramObj.vehicles AS vehicles
UNWIND vehicles AS vehicle
MATCH(v:Vehicles {name:vehicle})
MERGE (user)-[r:OWNS {since: timestamp()}]->(v)
RETURN user,r,v;
which fixed my original problem of how to remove properties from a map when using SET += map.

Neo4j Relationships not showing connecting lines in the graph

I created the following nodes and relationship in neo4j
CREATE (United_States:Citizenship { type : “Naturalized”})
CREATE (United_States:Citizenship { type : “Native_Born”})
CREATE (uid:Person { unique_id: 'A23AF39D-BEED-4FFC-B080-1362920FA7A8', id_type: '128bit_UUID' })
MATCH (uid:Person),(Native_Born:Citizenship) WHERE uid:Person="A23AF39D-BEED-4FFC-B080-1362920FA7A8" CREATE (uid) <- [ r:PersonUniqueIdentifier ] -> (Native_Born)
CREATE (fn:Person { first_name:'Willie', id_type:'128bit_UUID'})
CREATE (ln:Person { last_name:'Armstrong', id_type:'128bit_UUID'}))
CREATE CONSTRAINT ON (uid:Person) ASSERT Person.unique_id IS UNIQUE
CREATE INDEX ON :Person(unique_id)
I do not see the 'PersonUniqueIdentifier' Relation between the Citizenship node and id:Person node on the graph.
Screen shot of graph
Firstly, I would make a habit of doing the indexes/constraints first. There's not a lot of data here, but if you add an index after adding the data, it will need to go through all your nodes first. Also, creating a constraint also adds an index for you, so no need for that line. It seems like you're mixing up variables here, so refactoring a bit:
CREATE CONSTRAINT ON (person:Person) ASSERT person.unique_id IS UNIQUE
Also your Citizenship CREATEs are using the same variable name. I don't know if that would necessarily cause a problem, but it's simpler to do this anyway:
CREATE (:Citizenship { type : “Naturalized”}), (:Citizenship { type : “Native_Born”})
This statement looks fine to me (though, again, you could lose the variable if you wanted to):
CREATE (person:Person { unique_id: 'A23AF39D-BEED-4FFC-B080-1362920FA7A8', id_type: '128bit_UUID' })
Here there are a few problems. Here's how I would refactor it:
MATCH (person:Person),(citizenship:Citizenship)
WHERE
person.unique_id="A23AF39D-BEED-4FFC-B080-1362920FA7A8",
citizenship.type = 'Native_Born'
CREATE (person)-[:HAS_CITIZENSHIP]->(citizenship)
I'm not really sure what you want to do here. It seems like you want to create one person, so I would do this:
CREATE (:Person { first_name:'Willie', id_type: '128bit_UUID', last_name:'Armstrong'})

How can I check if a node already exist, before linking it to a new node in Neo4j with cypher

I'm novice in Neo4j and cypher and would like some help solving an issue. All help would be appreciated.
This is my problem:
I have created two nodes, one as a user and one as a city, linked to the user.
Graph setup
CREATE (n:User{firstName : "John", lastName : "Doe"});
MATCH (user:User{firstName : "John", lastName : "Doe"})
Return user;
Query:
MATCH (user:User)
WHERE user.firstName = "John"
CREATE (city:City { cityName:"Liverpool", areaCode:"34343" })
CREATE (user)-[:STUDY_IN]->(city);
Now I want to create a new node(user) and link that user to the existing node (city:Liverpool).
I've done that i this way:
MATCH (city:City)
WHERE city.cityName = "Liverpool"
CREATE (user:User { firstName : "Kent", lastName : "Clark" })
CREATE (user)-[:STUDY_IN]->(city);
In real life, I would need to check if the city exist, before creating the relationship and if it doesn't exist, then I would like to create a new node for that city.
You can see my code here:
http://console.neo4j.org/?id=utor92
Use the MERGE command which will match a pattern if it exists or create it if it doesn't.
CREATE (user:User{firstName: "Kent", lastName: "Clark"})
MERGE (city:City{cityName: "Liverpool"})
CREATE (user)-[:STUDY_IN]->(city)
RETURN user, city
You can also use ON CREATE and ON MATCH with MERGE. For example:
MERGE (city:City{cityName: "Manchester"})
ON CREATE SET city.foo = "bar"
ON MATCH SET city.baz = "qux"
In this example if city does not exist it will be created and the property foo is set to "bar". If it exists already the property baz gets set to "qux".
For a more in depth look at MERGE check out the docs.

Resources