I have a nested array, I have to remove the one object , based upon the condition using aggregation
here is the JSON I get from mongodb
{
"_id": "633d275ceb34a28755974032",
"name": "free",
"products": [
{
"title": "Product 1",
"phone": [
{
"title": "Best Phone 1 ",
"video": {
"Location": "https://video.mp4"
},
"freePreview": true
}
]
},
{
"title": "Product 2",
"phone": [
{
"title": "Best Phone 2",
"video": {
"Location": "https://video.mp4"
},
"freePreview": false
}
]
}
]
}
But I need the data like
{
"_id": "633d275ceb34a28755974032",
"name": "free",
"products": [
{
"title": "Product 1",
"phone": [
{
"title": "Best Phone 1 ",
"video": {
"Location": "https://video.mp4"
},
"freePreview": true
}
]
},
{
"title": "Product 2",
"phone": [
{
"title": "Best Phone 2",
"freePreview": false
}
]
}
]
}
In this data "video object" is removed inside the phone array , because of freePreview is false,
Based upon the freePreview condition , help me to remove the video object
CodePudding user response:
You need to use double $map operator to iterate through your array of arrays and use $cond along with $$REMOVE
to remove value conditionally:
db.collection.aggregate([
{
$addFields: {
products: {
$map: {
input: "$products",
as: "p",
in: {
title: "$$p.title",
phone: {
$map: {
input: "$$p.phone",
in: {
title: "$$this.title",
freePreview: "$$this.freePreview",
video: {
$cond: {
if: {
$eq: [
false,
"$$this.freePreview"
]
},
then: "$$REMOVE",
else: "$$this.video"
}
}
}
}
}
}
}
}
}
}
])
Here's a similar example.
CodePudding user response:
@mickl's answer works great. If you want to allow for possible document/schema changes, then rather than specifying the fields to keep explicitly, you could use "$mergeObjects"
to keep everything and then only modify what you need.
Borrowing heavily from @mickl, here's how you could do that.
db.collection.aggregate([
{
$addFields: {
products: {
$map: {
input: "$products",
as: "p",
in: {
"$mergeObjects": [
"$$p",
{
phone: {
$map: {
input: "$$p.phone",
in: {
"$mergeObjects": [
{
"$arrayToObject": {
"$filter": {
"input": {"$objectToArray": "$$this"},
"as": "kv",
"cond": {"$ne": ["$$kv.k", "video"]}
}
}
},
{
video: {
$cond: {
if: {
$eq: [
false,
"$$this.freePreview"
]
},
then: "$$REMOVE",
else: "$$this.video"
}
}
}
]
}
}
}
}
]
}
}
}
}
}
])
Try it on mongoplayground.net.