Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
08-17-2020 06:48 AM
I'm looking for strategies to handle parts of a tree where I need to maintain certain contstraints as you go two levels deep. Consider this GraphQL example:
{
text{
body
names{
name
startIndex
endIndex
people {
title
_id
}
}
}
}
A text includes strings which are a person's name. That person may have multiple names, so there is a separate node representing that unique individual. But, if the name
node in the above example is shared by more than one person, it will list multiple people. There are similar examples for other entity types.
What I want to do is make sure that the person returned is constrained by its relationship to the text node. We do have this relationship in our database, so it is possible to query all of the following:
(:Text)-[:MENTIONS]->(:Person)
(:Text)-[:MENTIONS]->(:Name)
(:Person)-[:NAMED]->(:Name)
How can we construct a GraphQL schema or query such that we can get the person mentioned in that particular text? Are we stuck with @cypher
directives handling very specific tree hierarchies, or is there a way to make it more flexible?
The best way I can think of to handle it is with GraphQL queries that are only one level deep, then relate the results on the client side. For example, we might do this:
{
text{
body
names{
_id
entities{
_id
}
}
entities {
_id
names {
_id
}
}
}
}
From there, we'd need JavaSCript functions to match or filter names and entities by _id
. That seems really ugly.
08-17-2020 08:02 AM
Soulliberty, welcome to the community. It seems like what you're after is going to be using the ability in your GraphQL schema to either create an individual Cypher query or add a @cyper directive query on your type. But off the top of my head it looks like you could have something like:
type text {
entities: [Person] @cypher (
statement: "MATCH (this)-[:MENTIONS || :NAMED]->(p) return p"
}
You can then filter the results on the front end whoever you like. Just a rough idea.
08-18-2020 02:10 PM
I think we can do cypher statements like this for specific cases, and maybe that's our only answer. Our [Name] nodes have a different type and properties than the [Person] nodes which is why this is more complicated.
08-18-2020 02:23 PM
The other thing to do is just write a fully custom Cypher query to handle it and feed your variables. When I've been faced with something that gets more complex in the past that's what I've ended up doing.
08-20-2020 06:38 AM
Another idea we've had is to ensure that certain nodes remain unique to certain relationship pairs. Let's say a chapter mentions "Mary." Instead of having one Name
Node for "Mary," we would create unique name nodes for every individual with that name. It may look like this:
names: [
{
name: "Mary",
id: 1,
person: {
title: "Mary Sue"
},
texts: [some_text_list]
},
{
name: "Mary",
id: 2,
person: {
title: "Mary Jo"
},
texts: [some_other_list]
},
]
This way, we maintain a one-to-one relationship that will always carry through the tree. It makes querying unique names a little tougher, but that's acceptable given our use case.
08-20-2020 04:54 PM
I attended a session today on https://neo4j.com/labs/neosemantics-rdf/ Neo semantics allows you to do quite a bit creating constraints on your graph that's not available out of the box with Neo4j alone. It might be worth you time to look at.
All the sessions of the conference are now available online