I'm working on product & category relation. Where category has parent-child relation.
i.e.
Category C1 has a child Category C2 and this can go to n-th layer
also,
a product has a category array and a reference to the last layer of category.
i.e. A product P1 belongs to the category C3
The problem arises, when the parent of Category C3 is changed to say Category 1 . As all the products assigned to Category C3 will have different category tree structure because of this change.
Here's my implementation so far:
GraphQl definition
type Product{
Id : ID
name : String
slug : String
category_direct : Category // Reference of the last layered category
category : [Category] // reference of the category parents or category structure depending on the last layered category
}
When the parent of category is changed:
await db.collection('categories').bulkWrite([
{
// Remove child from parent
updateOne: {
"filter": {Id: doc.parent},
"update": {
$pull: {child: {$in: [doc.Id]}},
$currentDate: {
"date_updated": {$type: "timestamp"}
}
}
}
}, {
// Add child ID to the new parent
// Add child details to parent category
updateOne: {
"filter": {Id: args.category.parent},
"update": {
$currentDate: {
"date_updated": {$type: "timestamp"}
},
$push: {"child": doc.Id}
}
}
}
]);
I'm stuck with the following where I need to restructure the category array in the products
// TODO Restructure product category depending on the products belonging to the category
// Find all products with direct_category as doc.Id and recursively get all parent categories
await db.runCommand({
update: "products",
updates: [{
q: { direct_category: doc.Id},
u: [
{
$set: {
category: {
// Can I add the below function here??
}
}
}
],
multi: true
}]
});
In order to append all category parents, I need to add the following inside of the update query :
// If category exists - get all the parents -- including self
args.product.category = await db.collection('categories').aggregate([{$match: {"Id": data.Id}},
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "Id",
"as": "ancestors"
}
},
{
"$addFields": {
"ancestors": {
"$reverseArray": {
"$map": {
"input": "$ancestors",
"as": "t",
"in": {"Id": "$$t.Id"}
}
}
}
}
}
]).toArray().then(data => {
if (data[0]) {
if (!_.isNull(data[0].ancestors)) {
data[0].ancestors.push({Id: data[0].Id})
return data[0].ancestors.map(value => value.Id)
} else return [{Id: data[0].Id}].map(value => value.Id)
} else return []
});