Reputation: 369
Having trouble using the $[<identifier>]
operator in mongodb/mongoose when using $set
in a nested array. It seems it doesn't work for me when using it, the item.nModified is always 0 and nothing is updated in the database. Any idea what im doing wrong?
await Product.update(
{productName: product.productName},
{ "$set": {
"stores.$[index].trackingUrl": 'url',
} },
{ "arrayFilters": [
{ "index": 0 },
] },
).then((item) => {
console.log("Updated", item.nModified);
});
If i remove the arrayFilters object and using "stores.$[].trackingUrl": 'url'
, without the operator it will update the value correctly.
If i use "stores.$[].trackingUrl": 'url'
, and leave the arrayFilters i get this error
MongoError: The array filter for identifier 'index' was not used in the update { $set: { stores.$[].trackingUrl: "url" } }
If i change the 0
to 1
in {"index": 0}
get this error. I only have 1 object at the moment in the stores array so its no surprise it crashes here.
CastError: Cast to embedded failed for value "1" at path "stores"
Schema for Product
const ProductSchema = new Schema({
ean: String,
productName: String,
mainCategory: String,
subCategory: String,
group: String,
subSubCategory: String,
lowestPrice: Number,
isPopular: Boolean,
description: String,
keyword: String,
stores: [
{
name: String,
programId: Number,
productPrice: Number,
productUrl: String,
imageUrl: String,
sku: String,
currency: String,
manufacturerArticleNumber: String,
manufacturer: String,
oldPrice: Number,
shipping: Number,
inStock: Boolean,
market: String,
approvalStatus: Number,
trackingUrl: String,
productDescription: String,
timestamp: String,
},
],
});
One document
{ _id: 5f3bf084fa56743527344454,
ean: '000',
productName: 'name',
lowestPrice: 5,
mainCategory: 'Leksaker',
group: 'Leksaker',
subCategory: 'Djur',
subSubCategory: '',
stores:
[ { _id: 5f3cc819d28fc65d915016bc,
name: 'Stor & Liten',
programId: 0,
productPrice: 359,
productUrl: 'https://www.storochliten.se/papo-kaprosuchus',
imageUrl:
'https://media.storochliten.se/product-images/XL//papo-kaprosuchus-0.jpg',
sku: '317969',
currency: 'SEK',
manufacturerArticleNumber: 'P55056',
manufacturer: 'Papo',
oldPrice: 359,
shipping: 0,
inStock: true,
market: 'SE',
trackingUrl: '', //expect to insert "url" here
productDescription:'text',
timestamp: '2020-08-19T06:35:05.595Z' } ],
}
Upvotes: 1
Views: 481
Reputation: 49945
The identifier part of the filtered positional operator is used to specify a condition based on subdocument's field. Your example doesn't work because there's no index field for store.
If you want to update the first element you can simply use the dot notation:
{ $set: { 'stores.0.trackingUrl': 'url' }
If you need to identify store
by any field you can try with _id
(or any other existing field):
await Product.update(
{productName: product.productName},
{ "$set": {
"stores.$[store].trackingUrl": 'url',
} },
{ "arrayFilters": [
{ "store._id": 5f3cc819d28fc65d915016bc },
] },
).then((item) => {
console.log("Updated", item.nModified);
});
Upvotes: 2