Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
07-10-2020 03:36 AM
Hello,
I want to test auto-generated CRUD operations created by calling makeAugmentedSchema. There is no problem with creating nodes but creating relationship does not work for me. Please advise on what I am doing wrong here.
Schema:
type Bio{
id: ID!
description: String
}
type Person{
id: ID!
name: String
dob: Date
gender: String
bioRelation: [Bio] @relation(name: "HAS_BIO", direction: "OUT")
}
Mutation:
mutation {
p: CreatePerson(
name: "Anton",
gender: "Male") {
name
gender
id
}
b: CreateBio(
description: "I am a developer") {
description
id
}
r: AddPersonBioRelation(
from: {id: "p"},
to:{id: "b"}
){
from{
name
}
to{
description
}
}
}
I am following the Interface Mutations guidance https://grandstack.io/docs/graphql-interface-union-types.
I get Person and Bio nodes created but no relationship gets created between the two:
{
"data": {
"p": {
"name": "Anton",
"gender": "Male",
"id": "586b63fd-f9a5-4274-890f-26ba567c065c"
},
"b": {
"description": "I am a developer",
"id": "a46b4c22-d23b-4630-ac84-9d6248bdda89"
},
"r": null
}
}
Thank you
07-10-2020 03:43 AM
This is how AddPersonBioRelation looks like:
07-12-2020 06:02 AM
You're not able to do the addRelationship mutation in conjunction with node creation mutations. You have to do is separately or create a custom cypher mutation that performs the operation in one go.
07-13-2020 01:55 AM
Thank you for helping, @MuddyBootsCode!
As I see, neo4j-graphql.js developers claim that it is possible to do the addRelationship mutation in conjunction with node creation mutations: https://grandstack.io/docs/graphql-interface-union-types.
I do want to reference newly created nodes by their id when creating relationship within one mutation. Could you please provide with example of such a custom cypher mutation that performs the operation in one go.
Many thanks,
Anton
07-14-2020 08:49 AM
Hmm that might be an updated part of the docs but to do a cyper mutation you'd just write a cyper statement that did what you're trying to do:
CREATE (a:node)
CREATE (b:node)
SET (a)-[:RELATIONSHIP]->(b)
return Whatever
07-14-2020 09:04 AM
@MuddyBootsCode, your answer looks like some sort of trolling, mate. The question is about how to reference newly created nodes along with creating the relationship in one go.
07-14-2020 09:20 AM
As I see there is an option to assign id at the stage of node creation and pass them to a relationship definition, but it raises the problem of managing the uniqueness of nodes as UUID gets overwritten.
07-15-2020 10:41 AM
In the example in the docs you referenced the id
values are provided to the create node mutations, which can then be used to reference the nodes in the add relationship mutation.
If no id
value is provided to the node creation mutation then a UUID is generated, and this value must be provided to the add relationship mutation. However, you won't know what those values are, thus necessitating a second operation.
If however, you specify values for the id
fields then this can be done in a single operation. So your example becomes:
mutation {
p: CreatePerson(
name: "Anton",
gender: "Male",
id: "p1") {
name
gender
id
}
b: CreateBio(
description: "I am a developer",
id: "b1") {
description
id
}
r: AddPersonBioRelation(
from: {id: "p1"},
to:{id: "b1"}
){
from{
name
}
to{
description
}
}
}
07-16-2020 02:08 AM
Thank you, @William_Lyon. Now, I see that there is no way to pass generated UUID to add relationship mutation in the same operation where nodes get created.
I have come up with an idea of introducing a personId property to both Person and Bio nodes that I can use to connect the two and remove once relationship is created. This allows to perform the operation in one go.
type Bio{
id: ID!
personId: Int
description: String
}
type Person{
id: ID!
personId: Int
name: String
gender: String
bioRelation: [Bio] @neo4j_ignore
}
type Mutation{
AddPersonBioRelation(personId: Int): Person
@cypher(statement:
"""
MERGE (p:Person {personId: $personId})
MERGE (b:Bio {personId: $personId})
CREATE (p)-[r:HAS_BIO]->(b)
REMOVE p.personId, b.personId
RETURN p
"""
)
}
The operation looks like this:
Which creates nodes along with a relationship keeping nodes' UUIDs:
I am not sure if this is considered as a good practice, though. From one side, such implementation defines a property for Person and Bio nodes just to facilitate a creation operation, but not for describing an entity. From the other side, api gets more user friendly for clients to use.
07-14-2020 10:01 AM
I’m not sure if your level of experience with either Neo4j or the grand stack but you can write custom mutations using cypher. I’ve given you a template on how to do that. Not an exact answer. No trolling involved. https://grandstack.io/docs/graphql-schema-directives You’ll see with the @cypher directive you can do what you’re after.
07-15-2020 02:02 AM
@MuddyBootsCode, you gave an example of creating two generic nodes with a relationship, which is pretty obvious. What would be helpful is the example of a resolver that overwrites autogenerated mutation that connects two newly created nodes keeping their uuid's.
I reckon mutation should looks like this in schema definition:
type Mutation {
AddPersonBio(fromPersonID: ID!, toBioID: ID!): Person @cypher(
statement:"""
MATCH (from:Person {id: $fromPersonID})
MATCH (to:Bio {id: $toBioID})
MERGE (from)-[:HAS_BIO]->(to)
RETURN from.id, to.id
""")
But how do I implement a resolver to be able to reference uuids of newly created objects?
Could you please provide with a relevant example addressing this question?
Thanks.
07-15-2020 04:29 AM
Ok. I think the issue is that you're missing a reciprocal piece of your relationship on your bio type. You also need to add it's relation to a person in your case it could look like:
type Bio {
id: ID!
description: String
person: Person @relation(name: "HAS_BIO", direction: "IN")
}
When you're using relationships you have to specify both types and ensure the in and out directions are correct. Give that a try and let me know.
Sorry the other stuff before but in some of the larger GRANDstack projects I've built I've found it much easier to go the custom Cypher mutation route for most things, rather than trying to coerce the auto-generated mutations into what I was trying to do.
07-15-2020 05:51 AM
I have defined relation on Person node already (please see my first message). Building symmetric relations is considered as not the best solution as to Neo4j official guidance which I am agreed with:
07-15-2020 06:06 AM
@William_Lyon, could you please comment on the best solution for this problem?
Thank you.
07-17-2020 06:30 AM
Super-interesting comment! And something I’ve been wondering about. Makes me wonder if there’s a highly-opinionated article online about using GRANDstack that shared (empirical) perspectives like this.
My concern about custom mutations is that they need to be manually updated as the schema definition changes. Do you run tests to compare your custom mutation to a group of more granular (autogenerated) mutations?
07-17-2020 08:01 AM
The two approaches I tend to use are either chaining operations together in the application with hooks i.e. useQuery or use Mutation until I hit a point where I feel the operation is just cleaner or easier to perform using Cypher. That’s mostly a personal opinion on when that happens. I think it just hits a point where Cypher is easier.
That being said I make a lot of use of input types to ensure that things don’t break or are caught by tests when they do.
07-15-2020 08:03 AM
You’re first post shows an error on your schema. I pointed it out to you. You’re missing the reciprocal relationship from Bio to Person.
07-15-2020 08:22 AM
@MuddyBootsCode, do I get it right, that you do not consider Person->Bio and Bio->Person relationships as symmetrical for this example?
There is no error in a schema re type definitinos in my first post, the confusion comes from mutation definition.
07-15-2020 08:26 AM
@MuddyBootsCode, it looks like you do not follow the point. I do not mind if you stop posting misleading messages.
07-15-2020 09:02 AM
In your first post you’ve posted your schema. In it you show to have no relationship from Bio to person. In order for makeAugmentedSchema to know how to create the correct relationship you need to include the relationship on both the person and bio type. With a correct in and out direction for the relationship. This does not create a separate relationship just ensures that it’s mapped correctly.
Try that and see if it fixes your mutation. If it doesn’t then holpefully someone else feels like helping you.
All the sessions of the conference are now available online