I have two models
// Product model
const ProductSchema = {
vendors: [{ type: Schema.Types.ObjectId, ref: 'Vendor' }],
mainVendor: { type: Schema.Types.ObjectId, ref: 'Vendor' },
}
// Vendor model
const VendorSchema = { ... }
When I delete a Vendor
, I want all Products
with mainVendor
field of deleted Vendor
's _id
to be replaced with the first vendor
of vendors
array. If vendors
array is empty, I want mainVendor
to be set to null
.
Say I have Product
const product = {
mainVendor: 'mainVendorObjectId'
vendors: ['secondVendorObjectid', 'thirdVendorObjectId']
}
When I delete Vendor
with mainVendorObjectId
_id
, I want my product
to be
const product = {
mainVendor: 'secondVendorObjectId',
vendors: ['thirdVendorObjectId']
}
If I have a product
with empty vendors
array
const product = {
mainVendor: 'mainVendorObjectId',
vendors: []
}
After deleting Vendor
with mainVendorObjectId
_id
I want my product to be like
const product = {
mainVendor: null,
vendors: []
}
I want to run it in post
hook.
What I have now
VendorSchema.post('findOneAndDelete', async function (res: TVendorModel) {
try {
const products = await ProductModel.updateMany(
{ mainVendor: res._id },
{ $expr: { $set: { mainVendor: '$vendors.0' } } }
);
} catch (error) {
console.error(error);
}
});
but it doesn't work and it won't set mainVendor
to null
if vendors
array is empty.
CodePudding user response:
A bit long query, but you can try with Update with aggregation pipeline.
With $cond
operator to check whether vendors
is an empty array, if yes set null
, else take the first value from the vendors
array to mainVendor
field.
For the vendors
field, it does the same concept as mainVendor
field, the outcome will be different in removing the first item from vendors
array.
db.collection.update({
mainVendor: "mainVendorObjectId"
},
[
{
$set: {
mainVendor: {
$cond: {
if: {
$eq: [
"$vendors",
[]
]
},
then: null,
else: {
$first: "$vendors"
}
}
},
vendors: {
$cond: {
if: {
$eq: [
"$vendors",
[]
]
},
then: [],
else: {
$slice: [
"$vendors",
1,
{
$size: "$vendors"
}
]
}
}
}
}
}
],
{
multi: true
})
CodePudding user response:
Too late but this is my solution
$first
extracts the first object of an array
$ifNull
checks if $first operation is null, if true, adds null
$slice
extracts a portion of the array
$sum
does a sum operation. In this case is just a trick to avoid errors when the length of the array is 0 (because $slice needs a value greater than 0)
db.collection.update({
"mainVendor": "mainVendorObjectId"
},
[
{
"$set": {
"mainVendor": {
$ifNull: [
{
"$first": "$vendors"
},
null
]
},
"vendors": {
"$slice": [
"$vendors",
1,
{
$sum: [
{
$size: "$vendors"
},
1
]
}
]
},
}
}
],
{
multi: true
})