Steps to reproduce:
Create such schema:
type User {
id: ID! @unique
email: String! @unique
location: Location!
}
type Location {
# note there is no @unique field here
lat: Int!
lng: Int!
}
Create a new user with some location:
mutation {
createUser(data: {
email: "[email protected]"
location: {
create: {
lat: 20
lng: 20
}
}
}) {
id
}
}
Get user id and update this user location few times:
mutation {
updateUser(data: {
location: {
create: {
lat: 21 # whatever actually, can even be the same value all the time
lng: 20
}
}
}, where: {
id: "<ID OF THE USER>"
}) {
id
}
}
Now let's try to get all locations
{
locations {
lat
lng
}
}
Expected: Should return single row as there is only one user having some location
Actual: Every updateUser created a new row that is now impossible to safely delete.
Side note: for rows that are not meant to have unique field, I think it's not needed to have create field. Having:
mutation {
updateUser(data: {
location: { # note lack of `create` sub-field
lat: 21
lng: 20
}
}, where: {
id: "<ID OF THE USER>"
}) {
id
}
}
Should be enough. Also, the same applies to one-to-many etc relations of types without id or other unique field. In such case, the whole concept of create, connect and upsert could actually be abstracted away and hidden from the user. It would also feel more natural as nested subfield instead of "another persisted db model entity".
Another side note: As (in this case) location has no field like parentUser etc, there is actualy no point of query like locations at all. Without context, such rows are hanging in the air.
Query result like:
{
"data": {
"locations": [
{
"lat": 32,
"lng": 234
},
{
"lat": 11,
"lng": 22
}
]
}
}
has no meaning at all without context available (also many of them would be totally the same with no way to distinguish). While I can imagine some use-cases for such queries, those could easily be replaced with context-aware queries going from users.
I'd consider good idea not allowing to query anything that has no context available (in this case you'd have to query users > location to get them together with their context)
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
it's happening in latest version of prisma too :(
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Its not stale
This is not a bug to me. The example shows the following mutation. This instructs Prisma to update a user and create a new location that then gets connected to the user. As a consequence the previous location gets disconnected. This behaviour looks correct to me.
mutation {
updateUser(data: {
location: {
create: {
lat: 21 # whatever actually, can even be the same value all the time
lng: 20
}
}
}, where: {
id: "<ID OF THE USER>"
}) {
id
}
}
If the intention is indeed to just update the location the nested update mutation should be used:
mutation {
updateUser(data: {
location: {
update: {
lat: 21 # whatever actually, can even be the same value all the time
lng: 20
}
}
}, where: {
id: "<ID OF THE USER>"
}) {
id
}
}
I am closing this therefore right now. Happy to reopen if needed.
How do I know if I need to update or create without making more requests before?
Also, if item gets disconnected, it's becoming zombie object as it has no id and can be the same as many other, yet it pollutes queries like allLocation or even makes them unreliable
What's the point of keeping such location object that has no purpose without being connected to anything (as it is child of something else by definition)
@pie6k : Then you should use a nested upsert instead.
The point of keeping those objects is that your desired behaviour won't make sense for every Prisma user. This specific behaviour is business logic that is custom to you and you should try to express it through existing features.
Most helpful comment
it's happening in latest version of prisma too :(