I am trying to create a call that combines all images between 'images' and 'posts.images' and sorts by createdAt. So far I have:
output = [Array(1), Array(3), {…}, {…}, {…}, {…}, {…}, {…}]
So it appears to be combining the arrays into a parent array instead of merging into a single array.
What I want:
output = [{…},{…},{…},{…},{…},{…},{…},{…},{…},{…},{…},{…}]
Here is my schema:
const deviceSchema = new Schema({
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
images: [{
url: {
type: String,
},
createdAt: {
type: Date,
}
}],
posts: [{
description: {
type: String,
},
images: [{
url: {
type: String,
},
createdAt: {
type: Date,
}
}],
createdAt: {
type: Date,
}
}],
});
Here is my aggregate call:
const images = await Device.aggregate([
{ $project: {
combinedImages: { $concatArrays: ["$images", "$posts.images"] }
}},
{ $match: { _id: id }},
{ $unwind: '$combinedImages' },
{ $sort: { 'combinedImages.createdAt': -1 }},
{ $skip: (page-1)*limit },
{ $limit: limit },
{ $group: { _id: '$_id', images: { $push: '$combinedImages'}}}
])
You can use a combination of $concatArrays
and $reduce
to combine all images into a single array, e.g.:
db.collection.aggregate([
{
$set: {
combinedImages: {
"$concatArrays": [
"$images",
{
$reduce: {
input: "$posts",
initialValue: [],
in: {
"$concatArrays": [
"$$value",
"$$this.images"
]
}
}
}
]
}
}
}
])
This leads to the following output:
{
// ...
"combinedImages": [
{
"url": "img1"
},
{
"url": "img2"
},
{
"url": "post_img11"
},
{
"url": "post_img12"
},
{
"url": "post_img21"
},
{
"url": "post_img22"
}
],
// ...
}
See this mongoplayground to test.