my database
{
"_id": {
"$oid": "ddfsfs"
},
"id": 3,
"parent_id": 6,
"translation":
[
{
"language": "en",
"desc": "prod detail",
"name": "example1"
},
{
"language": "tr",
"desc": "detaylar",
"name": "ornek1"
}
]
}
I want to make this : For example, only the English field is selected. Is it okay if it has only the name and description in the English field in its final form? and How?
{
"_id": {
"$oid": "ddfsfs"
},
"id": 3,
"parent_id": 6,
"desc": "prod detail",
"name": "example1"
}
or the database can be like this. again only the english field will remain
{
"_id": {
"$oid": "62189ffd81f6b6bb05d8d409"
},
"id": 7,
"parent_id": 8,
"en": {
"desc": "hii",
"name": "serial ethernet"
},
"tr": {
"desc": "merhaba",
"name": "seri ethernet"
}
}
please share me mongodb aggregations code for use in nestjs. thank you!:)
CodePudding user response:
For the first database schema, you need a pipeline that will first filter the translation
array using the $filter
operator. This will return an array with just the document that satisfies the filtering condition. So the expression:
{ $filter: {
input: '$translation',
cond: { '$eq': ['$$this.language', 'en'] }
} }
yields the result
[
{
"language" : "en",
"desc" : "prod detail",
"name" : "example1
}
]
The second step will be to merge the above document with the top-level fields you need, in this case you want the _id, id and parent_id fields to combine with the above. Use $mergeObjects
for this.
Since $mergeObjects
requires documents as input, you need to use $arrayElemAt
or $first
operator to get the document from the array in the previous $filter
expression, i.e.
{ $arrayElemAt: [
{ $filter: {
input: '$translation',
cond: { '$eq': ['$$this.language', 'en'] }
} },
0
] }
or $first
{ $first: {
$filter: {
input: '$translation',
cond: { '$eq': ['$$this.language', 'en'] }
}
} }
will return
{
"language" : "en",
"desc" : "prod detail",
"name" : "example1
}
Now you can use the expression
{
$mergeObjects: [
{ _id: "$_id", id: '$id', parent_id: "$parent_id" },
{ $arrayElemAt: [
{ $filter: {
input: '$translation',
cond: { '$eq': ['$$this.language', 'en'] }
} },
0
] }
]
}
to get
{
"_id" : ObjectId("6218abb521d9a0dfecd02e4b"),
"parent_id" : 6.0,
"language" : "en",
"desc" : "prod detail",
"name" : "example1"
}
Final step will be to replace the root with the operator $replaceRoot
and your final aggregate pipeline Try the following aggregate pipeline (MongoDb Playground) should look like this
{ $replaceRoot: {
newRoot: {
$mergeObjects: [
{ _id: "$_id", id: '$id', parent_id: "$parent_id" },
{ $arrayElemAt: [
{ $filter: {
input: '$translation',
cond: { '$eq': ['$$this.language', 'en'] }
} },
0
] }
]
}
} }
For the alternative schema run this aggregation pipeline where it's only a matter of merging the document with the en key i.e.
{ $replaceRoot: {
newRoot: {
$mergeObjects: [
{ _id: "$_id", id: '$id', parent_id: "$parent_id" },
'$en'
]
}
} }