Open astigsen opened 6 years ago
Nice! Should we also expose the object ID in Realm as a property on all objects so that it is then easy to reference the ID. This is the PK when there is one but perhaps would simplify thinking about what is the ID in the GraphQL syntax?
I'd be very surprised if this were supported GraphQL syntax. As far as I remember, GraphQL objects can only define fields and not what seems like a method. While we can definitely extend the syntax and parse it (and it does look much nicer than what I am going to propose), I imagine it would take a serious amount of effort.
An alternative approach that seems like it will be easier to implement would be something like:
const mutation = gql`
mutation {
result: setRelationship(input: {
objectType: "Car"
objectId: 1 // alternatively this could be PK
propertyName: "Driver"
relatedObjectId: 2 // This could be optional and if set to null, remove the link
}) {
brand
driver {
name
}
}
}`;
Similarly for lists:
const append = gql`
mutation {
result: insertInList(input: {
objectType: "Person"
objectId: 1 // alternatively this could be PK
propertyName: "Cats"
relatedObjectId: 2
index: 3 // Optional
}) {
...
}
}`;
and so on. This looks uglier and will likely require batching of mutations but seems feasible with the current architecture.
Should we also expose the object ID in Realm as a property on all objects
That should be the end goal. But the current API's for working with the internal object id's is a bit clunky (and private), so we probably need a bit of design work first.
As far as I remember, GraphQL objects can only define fields and not what seems like a method.
According to http://graphql.org/learn/queries/#arguments it is possible to define arguments on individual properties.
My understanding was that this was only possible for return types (hence it's in the queries section), not for input types (GraphQL makes a difference between those). For example here it says:
Input types can't have fields that are other objects, only basic scalar types, list types, and other input types.
You might be right. If that is the case I guess we will have to go with the more heavy approach of defining individual mutations ☹️
Do you prefer that to the dynamic API I proposed? I guess my main motivation for suggesting them is that right now we don't do any preprocessing of the inputs - we just proxy them to realm-js. If we included the fields as part of the input schema, e.g.:
const mutation = gql`
mutation {
result: addCompany(input: {
companyId: "some-unique-id"
ownerId: "personId" // Equivalent to owner(byId: true) from your example
}) {
companyId
owner
}
}`;
we would:
ownerId
in their schema?).The main benefit I can see is that we get "strong" typing and validation (e.g. users can't put any random value).
If we have to go in that direction, I think that the first API you proposed is preferable. Overloading the property names seems a bit inflexible and brittle.
So is it possible to add relation on mutation ?
EG: I would like to create a product with an existing supplier
mutation addProduct($input: ProductInput) {
addProduct(input: $input) {
name,
id
}
}
variable:
{
"input": {
"id": "f988da1d-65ee-4c4e-97a1-63bad5f1ef22",
"name": "new product cedric",
"supplier": { "id":"f480da1d-65ee-4c4e-97a1-63bad5f1ef22" },
}
This throws the error Attempting to create an object of type 'Supplier' with an existing primary key value ''f480da1d-65ee-4c4e-97a1-63bad5f1ef22''
.
If your objects have primary keys, you should be able to use updateProduct
rather than addProduct
. This is the only supported approach currently.
When updating objects, you often need to set individual relations, but that is currently quite complex as the API only allows you to create new objects. This is especially problematic with lists, as you might want to do specific operations (adding, removing or moving entries), and you currently can only do that by re-creating the entire list.
There are two subproblems here:
For the first problem, I propose adding an argument to the property fields during that specifies that it should interpret the value as an object reference (primary key):
For the second problem of supporting granular updates of lists, I propose a second set of arguments that you can apply to list properties:
Note that the last two (
remove
andmove
) uses the position in the list as value. If applicable it could also usebyId
, which would select the first entry matching that id (since it is possible for a list to contain duplicates).