John_Page
(John Page)
6
Hi Emmanuel,
You can’t do this with something as simple as a push nor can you efficient query for duplicates so it’s not worth trying that. You need to use an Expressive update to define what markets looks like relative to it’s current value.
Also - as an aisde you shoudl never $unwind then $group by _id, this is a pathological worst case for performance and a common huge anti-pattern.
I’ve made two assumptions here
(1) You want this to work for not just the first market or first sale period but all of them
(2) This may be wrong but I assum we can just convert storeSegmentations array to a set.
If (2) isn’t true then you would need to figure out logic for which object to keep if you have a duplicate segmentationType in an array and apply that using $reduce.
Anyway - here is the example code, I’ve broken it down to define each clause seperately - if you really want ot look at the whole thing then print out the value of expressiveUpdate.
db.a.drop()
var record = {
_id : "205734",
productId: "205734",
markets : [
{
salePeriods : [
{
panel: {
storeSegmentations :[
{ segmentationType: "C.WEB"},
{ segmentationType: "SUPPLY_SIZES"},
{ segmentationType: "SUPPLY_SIZES"},
]
}
},
{
panel: {
storeSegmentations :[
{ segmentationType: "C.WEB"},
{ segmentationType: "SUPPLY_SIZES"},
{ segmentationType: "SUPPLY_SIZES"},
]
}
}
]
},
{
salePeriods : [
{
panel: {
storeSegmentations :[
{ segmentationType: "C.WEB"},
{ segmentationType: "SUPPLY_SIZES"},
{ segmentationType: "SUPPLY_SIZES"},
]
}
}
]
}
]
}
db.a.insertOne(record);
var setOfSegmentationTypes = { $setUnion : [ "$$salePeriod.panel.storeSegmentations" ]}
var newSalesPeriod = {panel : { storeSegmentations : setOfSegmentationTypes }}
var allSalePeriods = { $map : { input : "$$market.salePeriods", as: "salePeriod", in : newSalesPeriod }}
var allMarkets = { $map : { input :"$markets", as: "market" , in: allSalePeriods }}
var expressiveUpdate = [ { $set : { markets : allMarkets }} ]
db.a.updateMany({},expressiveUpdate)
db.a.find();