cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Query is not returning node

Hi, I'm running the following query using the neo4j driver for node js.

MATCH (u:User) 
WHERE u.id = $uuid
CREATE (m:Mood {title : $title, text:$text, emoji:$emojiCode, timestamp : $timestamp,createdBy : u.id, id : apoc.create.uuid() })
MERGE (u)-[r:IS_FEELING_ON_${date} {timestamp : $timestamp, feelingType : $feelingTypeClassification }]->(m)
WITH u,m
MATCH (u)-[:IS_FRIENDS_WITH]->(friends:User) 
UNWIND friends as friend 
MERGE (m)-[:VISIBLE_TO_${date}]->(friend)
RETURN m

The ${date} is kept dynamically using string literals in node js

I expect the node m to be returned but i get nothing. The node and all relationships are created.
I tried the Explain query approach by putting this query with all required params in the neo4j browser, in the end it says 4 estimated rows but in the result, there is nothing. Don't know where I'm wrong. Please help.

Edit : I was able to solve this by replacing the UNWIND friends as friend with WITH COLLECT(friends) as fr FOREACH(friend in fr | MERGE (m)-[:VISIBLE_TO_${date}]->(friend)).

But, I still do not understand why it was not giving me the expected result. I tried

UNWIND CASE COALESCE(SIZE(friends),0) WHEN 0 IS [NULL] ELSE friends END AS friend

but this gave me an error.

1 ACCEPTED SOLUTION

Hi @rhltumpala and welcome to the community!

I usually test my code in the Neo4j Browser first - as that would isolate any issues with your js code.

That being said, I feel you answered your own question. You need to collect data into a list if you want to unwind it later.
I also can't see if the substitutions are part of your js code or those are parameters.
My opinion is to create a query that uses parameters instead of creating a query string and passing that off to neo4j. For the dynamic Relationship type you will need to make a call to apoc.merge.relationship apoc.merge.relationship - APOC Documentation to create that dynamic relationship
Further you are RETURNing m which is the mood

Example of passing parameters

Blockquote

try {
   // To learn more about the Cypher syntax, see https://neo4j.com/docs/cypher-manual/current/
   // The Reference Card is also a good resource for keywords https://neo4j.com/docs/cypher-refcard/current/
   const writeQuery = `MERGE (p1:Person { name: $person1Name })
                       MERGE (p2:Person { name: $person2Name })
                       MERGE (p1)-[:KNOWS]->(p2)
                       RETURN p1, p2`

   // Write transactions allow the driver to handle retries and transient errors
   const writeResult = await session.writeTransaction(tx =>
     tx.run(writeQuery, { person1Name, person2Name })
   )
   writeResult.records.forEach(record => {
     const person1Node = record.get('p1')
     const person2Node = record.get('p2')
     console.log(
       `Created friendship between: ${person1Node.properties.name}, ${person2Node.properties.name}`
     )
   })

View solution in original post

6 REPLIES 6

Hi @rhltumpala and welcome to the community!

I usually test my code in the Neo4j Browser first - as that would isolate any issues with your js code.

That being said, I feel you answered your own question. You need to collect data into a list if you want to unwind it later.
I also can't see if the substitutions are part of your js code or those are parameters.
My opinion is to create a query that uses parameters instead of creating a query string and passing that off to neo4j. For the dynamic Relationship type you will need to make a call to apoc.merge.relationship apoc.merge.relationship - APOC Documentation to create that dynamic relationship
Further you are RETURNing m which is the mood

Example of passing parameters

Blockquote

try {
   // To learn more about the Cypher syntax, see https://neo4j.com/docs/cypher-manual/current/
   // The Reference Card is also a good resource for keywords https://neo4j.com/docs/cypher-refcard/current/
   const writeQuery = `MERGE (p1:Person { name: $person1Name })
                       MERGE (p2:Person { name: $person2Name })
                       MERGE (p1)-[:KNOWS]->(p2)
                       RETURN p1, p2`

   // Write transactions allow the driver to handle retries and transient errors
   const writeResult = await session.writeTransaction(tx =>
     tx.run(writeQuery, { person1Name, person2Name })
   )
   writeResult.records.forEach(record => {
     const person1Node = record.get('p1')
     const person2Node = record.get('p2')
     console.log(
       `Created friendship between: ${person1Node.properties.name}, ${person2Node.properties.name}`
     )
   })

Hi, David

In the query, only the ${date} is injected using Js code, the rest of the $x in the query represent the parameters given to neo4j using the parameter form. The reason being, I cannot create the name of a relationship dynamically during the execution of the query. So, I wrapped the query in a function, injected ${date} and returned the query in the parameter form. But now, It seems I can, with the apoc.merge.relationship resource you pointed.

Admittedly, this was a query written in haste. I shall step back and evaluate my knowledge again.

Thank you.
Rahul

If you did a PROFILE of the query, you would likely see that your rows drop to 0 on the expansion from: MATCH (u)-[:IS_FRIENDS_WITH]->(friends:User), so we can assume that either the user doesn't have any friends, or something is wrong with the pattern. Most likely, the relationship is in the other direction, if the presence of a relationship is meant to imply friendship regardless of the direction. If that is the case, drop the direction of the relationship from the MATCH pattern.

As David mentioned below, UNWIND is only useful for lists (otherwise it's a no-op), and friends is not a list, you already have a single friend per row due to the MATCH, you don't need the UNWIND at all. Lists are generated by collect(), or by functions that return lists. It helps to only use plural variable names when you know you're working with lists, and otherwise keep it singular: MATCH (u)-[:IS_FRIENDS_WITH]->(**friend**:User)

Hi, Andrew,

I did do a PROFILE and observe that the rows dropping to 0, but I couldn't understand why. I may need to brush up on the basics of neo4j again. Are you saying that I do not need UNWIND to create relationships to all the friends that were resulted by MATCH?

PS: If I were to query for all relationships that were set dynamically, and fall within a range say, :IS_FEELING_ON_2021_04_05 and :IS_FEELING_ON_2021_04_29, how would I go about doing thtat ? Instead of generating query strings using Js is there a possibility to do it in neo4j efficiently, at scale?

Thank you.

Yes, UNWIND is not needed when the thing you're unwinding is not a list (as in your case), so you can omit it completely. Your MATCH to friends already has a row per friend, so you can do your MERGE right after your MATCH.

For the rows dropping to 0, again this is either because the relationship type is wrong, or (more likely) the direction is wrong. Dropping the direction from the pattern will MATCH on the relationship in any direction, that is likely to let this work as expected.

For dynamic relationships, there are various APOC procedures you could use, such as the apoc.neighbors procedures. You would have to provide a string date list so you could generate the relationship type strings to use in those procs, that would be easiest from outside the Cypher query call in your client. There are ways to generate this within the Cypher itself, but that's some advanced stuff.

In either case, the creation of the list of relationship types, and usage of apoc.text.join() to assemble a "|" delimited string for usage in the procs would be fast. The efficiency of use would depend upon how many input rows there would be before you expand, and how many rows end up being expanded by the relationship types provided.

Thank you Andrew, I shall look into it