I need to update a field nested in my User document, that contains an array of part objects, to add new parts. One part object looks like this:
{
partId: 871838,
partNum: '87087',
partName: 'Brick Special 1 x 1 with Stud on 1 Side',
colorId: 0,
colorName: 'Black',
quantity: 10,
partImg: 'https:...'
}
I want to add the part to the array, but only if user doesn't already own it. I tried using $addToSet, like so:
await User.updateOne(
{ username: username },
{ $addToSet: { parts: { $each: req.body.parts } } }
);
but that won't work, since sometimes the part is the same, but the quantity varies, and that is enough to treat is as a different part, so it gets added. Is there a way to specify by which value to determine if the object already exists in an array?
EDIT: so, I found this in the docs :
you cannot specify that MongoDB compare only a subset of the fields in the document to determine whether the document is a duplicate of an existing array element
So that means that $addToSet is no good for my case... Now I have no idea what to do.
I'm posting an answer, since I managed to get the result that I wanted, and I'd like some feedback. It works fine, but feels brute force and kinda hacky:
const incomingParts = req.body.parts;
const _ownedParts = await User.findOne(
{ username: username },
{ parts: 1, _id: 0 }
);
let ownedParts: IPart[] = [];
const newParts: IPart[] = [];
//if statement for TS
if (_ownedParts) {
ownedParts = _ownedParts.parts;
}
let partsToAdd;
if (ownedParts.length === 0) {
//if the user owns no parts, just add the whole lot
partsToAdd = [...req.body.parts];
} else {
incomingParts.forEach((incoming: IPart) => {
const ownedIdx = ownedParts.findIndex((owned: IPart) => {
return incoming.partId === owned.partId;
});
if (ownedIdx !== -1) {
ownedParts[ownedIdx].quantity += incoming.quantity;
} else {
newParts.push(incoming);
}
});
partsToAdd = [...ownedParts, ...newParts];
}
await User.updateOne(
{ username: username },
{ $set: { parts: partsToAdd }, $push: { sets: setNum } }
);
If there is a way using mongodb operators or aggregate, I'd love to see that.
If I understand it correctly you want to change a specific field if the part exists. After you get the checks you may refer to this:
await User.updateOne(
{ username: username },
{ $set: { "parts.0.partNum": 234234 }
);
That assuming you know the index of the specific part. You can use this for reference: https://docs.mongodb.com/manual/reference/operator/update/set/