MongoDB: Upsert fails on update with relation when `notablescan: 1`
See original GitHub issueBug description
Using MongoDB, the following error occurs when running an upsert and the document already exists:
PrismaClientUnknownRequestError:
Invalid `prisma.user.upsert()` invocation:
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: RawDatabaseError { code: "unknown", message: "Command failed (NoQueryExecutionPlans): error processing query: ns=ninja-diary.projectsTree: $expr {$and: [{$in: [\"$ownerId\", {$const: [\"qGdWa0VNzHfW8GRaDxz5nfjPDRt1\"]}]}, {$or: [{$ne: [{$ifNull: [\"$ownerId\", {$const: null}]}, {$const: null}]}, {$eq: [\"$ownerId\", {$const: null}]}]}]}Sort: {}\nProj: { _id: true, ownerId: true }\nCollation: { locale: \"simple\" }\n planner returned error :: caused by :: No indexed plans available, and running with 'notablescan')" } })
at Object.request (/usr/app/node_modules/@prisma/client/runtime/index.js:45582:15)
at async PrismaClient._request (/usr/app/node_modules/@prisma/client/runtime/index.js:46405:18)
at async setSyncTimeForUser (/usr/app/src/features/sync/utils.ts:29:18)
at async /usr/app/src/features/sync/push.ts:19:5
at async Proxy._transactionWithCallback (/usr/app/node_modules/@prisma/client/runtime/index.js:46366:18)
at async push (/usr/app/src/features/sync/push.ts:15:3)
at async /usr/app/src/app.ts:442:7 {
clientVersion: '3.12.0'
}
How to reproduce
model User {
id String @id @map("_id") @db.String
name String
lastSync DateTime @updatedAt
projects Project[]
@@map("users")
}
model Project {
id String @id @map("_id") @db.String
name String
owner User @relation(fields: [ownerId], references: [id])
ownerId String @db.String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isDeleted Boolean @default(false)
@@index([ownerId])
@@index([createdAt])
@@index([updatedAt])
@@index([isDeleted])
@@map("projects")
}
Run this once:
await prisma.user.upsert({
where: { id: userId },
create: { id: userId, name: "foo" },
update: { name: "foo2" },
});
This will create the document, which works. Then run it a second time, which will execute the “update” part since the document exists. It now fails with the error above.
If I remove the relation from the schema (and only have a “dum” ownerId
field) the opertation works again.
Expected behavior
It should not fail
Prisma information
Prisma v3.12.0
mongoDB 4.4
model User {
id String @id @map("_id") @db.String
name String
lastSync DateTime @updatedAt
projects Project[]
@@map("users")
}
model Project {
id String @id @map("_id") @db.String
name String
owner User @relation(fields: [ownerId], references: [id])
ownerId String @db.String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isDeleted Boolean @default(false)
@@index([ownerId])
@@index([createdAt])
@@index([updatedAt])
@@index([isDeleted])
@@map("projects")
}
Run this once:
await prisma.user.upsert({
where: { id: userId },
create: { id: userId, name: "foo" },
update: { name: "foo2" },
});
Environment & setup
- OS: debian
- Database: MongoDB Atlas v4.4
- Node.js version: 16.13
Prisma Version
prisma : 3.12.0
@prisma/client : 3.12.0
Current platform : debian-openssl-1.1.x
Query Engine (Node-API) : libquery-engine 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/libquery_engine-debian-openssl-1.1.x.so.node)
Migration Engine : migration-engine-cli 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/migration-engine-debian-openssl-1.1.x)
Introspection Engine : introspection-core 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/introspection-engine-debian-openssl-1.1.x)
Format Binary : prisma-fmt 22b822189f46ef0dc5c5b503368d1bee01213980 (at node_modules/@prisma/engines/prisma-fmt-debian-openssl-1.1.x)
Default Engines Hash : 22b822189f46ef0dc5c5b503368d1bee01213980
Studio : 0.459.0
Preview Features : interactiveTransactions, extendedIndexes
Issue Analytics
- State:
- Created a year ago
- Comments:24 (11 by maintainers)
Top Results From Across the Web
Mongodb update with upsert fails - Stack Overflow
It is actually a case of oversized document. db.collection_name.stats() confirmed it.
Read more >Does MongoDB still update or overwrite a document if the ...
I'm working with Mongoose and the phenomena happens for both update and updateMany. It seems, if the update object just happens to be...
Read more >Error returned after an update, but the update was successful
The document in the db does have a lot of other fields, but I'm only updating one of them. Thanks. isabelatkinson (Isabel Atkinson)...
Read more >db.collection.update() — MongoDB Manual
When you execute an update() with upsert: true and the query matches no ... update. document or pipeline. The modifications to apply. Can...
Read more >Use case for upsert with examples - M001: MongoDB Basics
I think just like anytime you have insert new doc of update existing one if already exists kind of situation, you can use...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Simplified schema for further reproduction:
and script with query logging:
I did some more investigating and the issue seems broader, as a lot of operations seem to cause a collection scan instead of using an index.
Specifically, I have found that using the
in
operator always causes an aggregation command that fails to use an index. For examplecauses a collection scan. I have confirmed this by running
explain
on theaggregate
command prisma ends up running (using query logging).I added a couple million objects to the collection, and running the
findMany
command takes over 300ms locally vs <5ms when using mongoDB driver