Problem:
I need to only update one document in a nested array of subdocuments. My previous query was updating all matching documents which is no good Example Below. So I decided to use aggregation so that I could add a limit stage so that I could only update one item, but I cannot get the update to happen through node and I am not even getting errors.
Old Query/Update:
This query updates all documents that match the shape of userId: "empty"
const query = await db.collection('events').updateOne({
_id: new ObjectId(eventId),
createdBy: new ObjectId(createdBy),
"weights.weight": weight
},
{
$set: {
"weights.$.spotsAvailable.$[el2]": {
"name": applicantName,
"userId": new ObjectId(applicantId)
}
}
},
{
arrayFilters: [
{
"el2.userId": "empty"
}
]
})
I have tested the aggregation in the MongoDB compass aggregation builder and it works fine.
But in the actual node code no luck
I have tried:
- Pluging in variables without the
new ObjectId
syntax - Plugin in variables with the
new ObjectId
syntax - Using the exact same hardcoded values that I got from copying the aggregation code from compass for the node driver
Code:
const acceptOrRemoveApplicant = async (eventId: ObjectId, createdBy: ObjectId, applicantId: ObjectId, applicantName: string, boolean: boolean, weight: number): Promise<boolean | undefined> => {
console.log({ eventId, createdBy, applicantId, applicantName, boolean, weight })
if (boolean == true) {
try {
/*
* Requires the MongoDB Node.js Driver
* https://mongodb.github.io/node-mongodb-native
*/
const agg = [
{
'$match': {
'_id': new ObjectId('6398c34ca67dbe3286452f23'),
'createdBy': new ObjectId('636c1778f1d09191074f9690')
}
}, {
'$unwind': {
'path': '$weights'
}
}, {
'$unwind': {
'path': '$weights.spotsAvailable'
}
}, {
'$match': {
'weights.spotsAvailable.name': 'empty',
'weights.weight': 15
}
}, {
'$limit': 1
}, {
'$set': {
'weights.spotsAvailable.name': 'Wayen',
'weights.spotsAvailable.userId': '123456'
}
}
]
const client = await clientPromise;
const db = client.db();
const query = db.collection('events').aggregate(agg);
// const query = await db.collection('events').updateOne({
// _id: new ObjectId(eventId),
// createdBy: new ObjectId(createdBy),
// "weights.weight": weight
// },
// {
// $set: {
// "weights.$.spotsAvailable.$[el2]": {
// "name": applicantName,
// "userId": new ObjectId(applicantId)
// }
// }
// },
// {
// arrayFilters: [
// {
// "el2.userId": "empty"
// }
// ]
// })
if (query) {
console.log("we queried")
console.log({ query })
return true
} else {
throw new Error("User not added to event")
}
} catch (e) {
console.error(e);
}