Can I return the relationship as a field within a node?

I currently have this query:

    OPTIONAL MATCH (t)<-[r:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(post:Post)

and later on I have

    OPTIONAL MATCH (this)<-[:TAGGED]-(post:Post)

and because they all return together (as a list of posts), I don't know which posts were children of a thing or which ones just tagged "this" directly.

Is it possible to return when "r" which is the name of the "CHILD_OF" relationship variable here is present?

Full post looks something like this:

    OPTIONAL MATCH (this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(post:Post)
    WITH COLLECT(post) as rows, this
    OPTIONAL MATCH (this)<-[:TAGGED]-(p:Post)
    WITH rows + COLLECT(p) as allRows
    UNWIND allRows as post
    RETURN DISTINCT post
    ORDER BY post.date DESC

I don't want it as a map as neo4j-graphql-js doesn't support that, they exclusively support returning single nodes. So I also can't do return post, r

Hi @geronimo4j ,

Could you change the path to something like:

(p1:Post)-[:TAGGED]->(this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(p2:Post)

And like this you can differentiate in some way?

Hi Ljubica, With this will it return either post case? Like if it's (p1:Post)-[:TAGGED]->(this) OR if it's (this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(p2:Post)?

Just thinking there are a lot of cases that are not going to have that full relationship where this is Tagged and where this is a child of a thing? LIke when (this) is in the middle of those relationships, is that effectively an "OR" statement?

OPTIONAL MATCH (p1:Post)-[:TAGGED]->(this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(p2:Post)
RETURN p1 AS DIRECT,p2 AS CHILD_OF

Hi Gabrial, this would return two separate objects when I'm using it with neo4j-graphql-js which requires a single Node, I believe. Any way to have it return as a single Node?

Hi @geronimo4j

How about this?
I modified @tard_gabriel answer.

OPTIONAL MATCH (p1:Post)-[:TAGGED]->(this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(p2:Post)
RETURN DISTINCT (collect(p1) + collect(p2)) AS post

Hi Kohi, Thank you. Similar question as earlier to Ljubica, with this will it return either post case? Like if it's (p1:Post)-[:TAGGED]->(this) OR if it's (this)<-[:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(p2:Post)?

Just thinking there are a lot of cases that are not going to have that full relationship where this is Tagged and where this is a child of a thing? LIke when (this) is in the middle of those relationships, is that effectively an "OR" statement?

I don't need to combine the Match statements necessarily, I'm just trying to get the relationship included in the returned node, is that possible?

Is this not possible?

Again, I'm after getting the two queries to remain separate, but return the data plus relationship as one node.

Hi @geronimo4j

How about this two queries version?
I thought (this) did not include (:Thing), so I added WHERE.
Change RETURN to the value you want.

OPTIONAL MATCH (this)<-[r:CHILD_OF]-(:Thing)<-[:TAGGED]-(post:Post)
OPTIONAL MATCH (this)<-[:TAGGED]-(p:Post)
  WHERE NOT this:Thing
RETURN DISTINCT (collect(post) + collect(p)) as post;

How does that return the relationship?

Hi @geronimo4j

Simply add r to the last line.

OPTIONAL MATCH (this)<-[r:CHILD_OF]-(:Thing)<-[:TAGGED]-(post:Post)
OPTIONAL MATCH (this)<-[:TAGGED]-(p:Post)
  WHERE NOT this:Thing
RETURN DISTINCT (collect(post) + collect(p)) as post, r

Then it's no longer returning as a single node? Might be easiest to re-read the initial post, thanks anyway but it's just not in the direction of what I need to figure out

Hi @geronimo4j
Is there the CREATE statement for test data?

Hi Koji - Just in theory - without looking at any specifics, is there a way to return a single node that also includes the relationship?

Hi @geronimo4j
You mean like this?
This Cypher is part of it.

OPTIONAL MATCH p=(this)<-[r:CHILD_OF]-(:Thing)<-[:TAGGED]-(post:Post)
RETURN p

Unfortunately that returns a Path not a Node. Looking for something like:

Thing: {
 id,
 name,
 image, 
 relationship
}

where relationship is "r" of CHILD_OF

Does the relationship have a name property or something equally useful?

You could then return something like:

RETURN thing.id, thing.name, thing.image, r.name, id(r)

Doesn't that just return multiple disparate values, instead of a node? My biggest constraint is neo4j-graphql-js which currently expects a single node. That's unfortunately my biggest problem as I'm using that package and it appears to be poorly maintained/missing a number of basic neo4j support!

I guess the problem is then you need to create a new property in the Node that is a List of Relationships. Presumably you'd need to represent the relationships some how in the list (as a name?).

I'm not familiar with neo4j-graphql-js. I suspect you're trying to get it to do things it wasn't designed to but I don't know for sure.

Are you sure a map output isn't acceptable? When you need to return node properties, and have that include something additional which isn't actually a property on the node, you would typically use map projection for this.

Here's an example of how you might use it, if you only wanted to include the r on posts that were reached in a match using :CHILD_OF:

    OPTIONAL MATCH (this)<-[r:CHILD_OF]-(t1:Thing)<-[:TAGGED]-(post:Post)
    WITH COLLECT(post {.*, relationship:r}) as rows, this
    OPTIONAL MATCH (this)<-[:TAGGED]-(p:Post)
    WITH rows + COLLECT(p {.*}) as allRows
    UNWIND allRows as post
    RETURN DISTINCT post
    ORDER BY post.date DESC

Note that this returns maps, not nodes. The only alternative that returns nodes instead of maps is by using APOC virtual nodes, and you would supply the property map by map projection.