return deleted node after DETACH DELETE - neo4j

I have a problem to get node record in result after I deleted the node.
My query is:
MATCH (user:User)-[:CREATED]->(comment:Comment)-[:BELONGS_TO]->(post:Post)
WHERE comment.uuid = {commentUUID} AND post.uuid = {postUUID} AND user.uuid = {userUUID} AND NOT EXISTS(user.deleted)
DETACH DELETE comment
RETURN comment
Here I am deleting comment which belongs to some post (BELONGS_TO). I also check if user who wants to delete the comment is also author of this comment (CREATED).
Query works, the deletion of node and relationship happen successfully, but I am not satisfied with returned value.
It shows me this result instead:
{ metadata: { deleted: true, id: 89 },
paged_traverse: 'http://myDatabaseURI/db/data/node/89/paged/traverse/{returnType}{?pageSize,leaseTime}',
outgoing_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/out',
outgoing_typed_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/out/{-list|&|types}',
labels: 'http://myDatabaseURI/db/data/node/89/labels',
create_relationship: 'http://myDatabaseURI/db/data/node/89/relationships',
traverse: 'http://myDatabaseURI/db/data/node/89/traverse/{returnType}',
all_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/all',
all_typed_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/all/{-list|&|types}',
property: 'http://myDatabaseURI/db/data/node/89/properties/{key}',
self: 'http://myDatabaseURI/db/data/node/89',
incoming_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/in',
properties: 'http://myDatabaseURI/db/data/node/89/properties',
incoming_typed_relationships: 'http://myDatabaseURI/db/data/node/89/relationships/in/{-list|&|types}' }
Thanks for help!
Edit:
I hide my db URI in result and replaced it with myDatabaseURI

As far as I can tell, when you delete a node, you cannot return its properties by returning the node itself.
However, you can get the properties of the node before the deletion, and return that after deleting the node itself:
MATCH (user:User)-[:CREATED]->(comment:Comment)-[:BELONGS_TO]->(post:Post)
WHERE comment.uuid = {commentUUID} AND post.uuid = {postUUID} AND user.uuid = {userUUID} AND NOT EXISTS(user.deleted)
WITH comment, properties(comment) as props
DETACH DELETE comment
RETURN props
This won't get you the node id, though, so if you need to return that, you can use map projection to get all properties plus the node id instead.

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

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.

Conditional data insertion in neo4j

I have an empty LIST, where I want to insert some CONTACT data. I have write the following query:
MERGE (u:CONTACT { id: 'random-id-01', email: 'some01#email.com', name: 'some-name-01', info: 'some-info-01 } )
WITH u as u
MATCH (pl:LIST { id: {listId} } )
MERGE (pl)-[plcn:LIST_CONTACTS]->(u)
RETURN u
But I also have to check duplicate email. So I have write the following query:
MATCH (pl:LIST)-[plcn:LIST_CONTACTS]->(ux:CONTACT)
WHERE ux.email <> 'some01#email.com'
MERGE (u:CONTACT { id: 'random-id-01', email: 'some01#email.com', name: 'some-name-01', info: 'some-info-01 } )
WITH u as u
MATCH (pl:LIST { id: {listId} } )
MERGE (pl)-[plcn:LIST_CONTACTS]->(u)
RETURN u
This query only works when some CONTACT data are already exist. But when an empty LIST is created and then want to insert CONTACT data into that newly created LIST, then it is not working.
How can I solve this problem?
Thanks in advance.
If you want email to be unique among :CONTACT nodes, then create a unique constraint on :CONTACT(email), that will ensure an error is thrown when an insert attempt violates the uniqueness constraint.
I'm not quite understanding your intent with the MATCH of all contacts with a different email than the one you want to insert. Can you clarify what you're attempting?

Create a relationship only if a similar one exist - neo4j

I have a linked list such that every node has a 'next' relation pointed to the next node, the first node has another relation : 'first' which pointed to it from some category. I'm trying to write a delete function that uses cypher to do so but I keep getting this error :
Received an unexpected HTTP status when executing the request.
The query was: MATCH (c:Cat {id:{id}})-[:Post]->(p:Post{id:{pid}})
My try :
gclient.Cypher
.Match("(c:Cat {id:{id}})-[:Post]->(p:Post{id:{pid}})")
.Match("(p)-[nn:next]->(np:Post)")
.OptionalMatch("(c)-[old:first]->(p)")
.OptionalMatch("(ppost:Post)-[pn:next]->(p)")
.WithParams((new
{
id = catId,
pid = postId
}))
.Create("(ppost)-[:next]->(np)")
.With("old, p, c, np")
.Where("old IS NOT NULL")
.Create("(c)-[:first]->(np)")
.With("p, old")
.Delete("old")
.Delete("p")
.ExecuteWithoutResults();

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