I have 3 collections users, profiles and trustedcontacts. Profiles and trustedcontacts have ref to users
My db collections
I have collection users
{
"_id": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
},
"name": "User",
"email": "user#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
},
{
"_id": {
"$oid": "5c64968cae53a8202c963223"
},
"name": "User1",
"email": "user1#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
},
{
"_id": {
"$oid": "5c69968cae53a8202c963554"
},
"name": "User1",
"email": "user1#gmail.com",
"password": "$2a$10$BXxwpMTFK1a0aWclaqJYve4f3SZyi/emwHKv5rY2GNzrPSEsIJhzi",
}
collection profiles
{
"_id": {
"$oid": "5c5ecb17134fc342d4b1a9d6"
},
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
},
"handle": "handle",
"company": "test"
},
{
"_id": {
"$oid": "5c6496ebae53a8202c963224"
},
"user": {
"$oid": "5c64968cae53a8202c963223"
},
"handle": "handle1",
"company": ""
},
{
"_id": {
"$oid": "5c6496ebae53a8202c963224"
},
"user": {
"$oid": "5c69968cae53a8202c963554"
},
"handle": "handle2",
"company": ""
}
collection trustedcontacts
{
"_id": {
"$oid": "5d76008e4b98e63e58cb34cc"
},
"approvedTrustedContacts": [
{
"_id": {
"$oid": "5d764e411b7476462cf6b540"
},
"user": {
"$oid": "5c5ecaf6134fc342d4b1a9d5"
}
},
{
"_id": {
"$oid": "5d764e411b7476462cf6b541"
},
"user": {
"$oid": "5c64968cae53a8202c963223"
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": {
"$oid": "5d76008e4b98e63e58cb34cb"
}
}
//My Schemas
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
email: {
type: String,
}
});
export default mongoose.model('User', UserSchema);
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
handle: {
type: String,
},
company: {
type: String,
},
});
export default mongoose.model('Profile', ProfileSchema);
import mongoose from 'mongoose';
const TrustedContactsSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
approvedTrustedContacts: [
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
}
],
...
});
export default mongoose.model('TrustedContacts', TrustedContactsSchema);
I can populate trusted contact by user
const user = await TrustedContacts.findOne({ user: req.user.id }).populate('approvedTrustedContacts.user', ['name', 'email']);
and I got
"user": {
"date": "2019-09-09T07:32:20.174Z",
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764e411b7476462cf6b540",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
}
},
{
"_id": "5d764e411b7476462cf6b541",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
}
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
Expected Output
It is possible to get list of approvedTrustedContacts with profile data
"approvedTrustedContacts": [
{
"_id": "5d764e411b7476462cf6b540",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle",
"company": "test"
},
{
"_id": "5d764e411b7476462cf6b541",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1"
}
],
Also I have joined 2 collections like this
let result1 = await TrustedContacts.aggregate([
{ $lookup: { from: "profiles", localField: "user", foreignField: "user", as: "approvedTrustedContacts" } },
]);
And I got
{
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764f551b7476462cf6b542",
"user": "5d76008e4b98e63e58cb34cb",
"handle": "handle",
"company": "test",
},
{
"_id": "5c5ecb17134fc342d4b1a9d6",
"user": "5c5ecaf6134fc342d4b1a9d5",
"handle": "handle1",
"company": "test1",
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
],
Now I don't know how to polute user to have an output like this:
{
"_id": "5d76008e4b98e63e58cb34cc",
"approvedTrustedContacts": [
{
"_id": "5d764f551b7476462cf6b542",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle"
"company": "test",
},
{
"_id": "5c5ecb17134fc342d4b1a9d6",
"user": {
"_id": "5c64968cae53a8202c963223",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1",
}
],
"pendingApprovalContacts": [],
"waitingForApprovalContacts": [],
"user": "5d76008e4b98e63e58cb34cb",
}
],
My solution
let result = await TrustedContacts.aggregate([
{ $lookup: { from: "profiles", localField: "approvedTrustedContacts.user", foreignField: "user", as: "approvedTrustedContacts.profile" } },
{ $unwind: "$approvedTrustedContacts.profile" },
{ $lookup: { from: "users", localField: "approvedTrustedContacts.profile.user", foreignField: "_id", as: "approvedTrustedContacts.profile.user" } },
{ $unwind: "$approvedTrustedContacts.profile.user" },
{ $group :{
_id: "$_id",
"date": {"$first": "$date"},
"approvedTrustedContacts": {"$push": "$approvedTrustedContacts"},
}}
]);
As an output I have
{
"_id": "5d76008e4b98e63e58cb34cc",
"date": "2019-09-09T07:32:20.174Z",
"approvedTrustedContacts": [
{
"profile": {
"_id": "5c5ecb17134fc342d4b1a9d6",
"skills": [
"test"
],
"date": "2019-02-09T12:42:48.969Z",
"user": {
"_id": "5c5ecaf6134fc342d4b1a9d5",
"data": "2019-02-09T12:42:48.716Z",
"name": "User",
"email": "user#gmail.com",
},
"handle": "handle",
"company": "test",
}
},
{
"profile": {
"_id": "5c6496ebae53a8202c963224",
"skills": [
"qwqwqwqwqw"
],
"date": "2019-02-13T22:11:04.119Z",
"user": {
"_id": "5c64968cae53a8202c963223",
"data": "2019-02-13T22:11:03.807Z",
"name": "User1",
"email": "user1#gmail.com",
},
"handle": "handle1",
"company": "test1",
}
}
]
}
```
Related
I'm new to mongoose, I'm confuse while create the query. Can you help me?
I have a movie document like this :
"movies": [
{
"id": "635611395a71beb6c5bf0b4d",
"title": "Mission: Impossible - Fallout",
"createdAt": "2022-10-24T04:14:54.445Z",
"cast": [
{
"actor": "635350c581d5b60383f0c4be",
"roleAs": "Ethan Hunt",
"leadActor": true,
"_id": "635658c18b9e50facd7f1fd1"
},
{
"actor": "63560bf55a71beb6c5bf0b1f",
"roleAs": "Ilsa Faust",
"leadActor": false,
"_id": "635658c18b9e50facd7f1fd2"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"public_id": "vczxb7lgbonjn8ydsyep",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1666603204/vczxb7lgbonjn8ydsyep.jpg"
]
},
"reviews": {
"ratingAvg": "5.0",
"reviewCount": 2
}
},
{
"id": "635614855a71beb6c5bf0bdc",
"title": "Spider-Man: No Way Home",
"createdAt": "2022-10-24T04:28:58.286Z",
"cast": [
{
"actor": "635350a881d5b60383f0c4b8",
"roleAs": "Peter Parker",
"leadActor": true,
"_id": "636a2d6520cf4cf14a11ef95"
},
{
"actor": "635611eb5a71beb6c5bf0b99",
"roleAs": "MJ",
"leadActor": false,
"_id": "636a2d6520cf4cf14a11ef96"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"public_id": "tajzr9hpulvzqoytgpxu",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_470/v1667902823/tajzr9hpulvzqoytgpxu.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1667902823/tajzr9hpulvzqoytgpxu.jpg"
]
},
"reviews": {
"ratingAvg": "8.0",
"reviewCount": 2
}
},
This is my desired result:
{
"id": "635611395a71beb6c5bf0b4d",
"title": "Mission: Impossible - Fallout",
"createdAt": "2022-10-24T04:14:54.445Z",
"cast": [
{
"actor": "635350c581d5b60383f0c4be",
"roleAs": "Ethan Hunt",
"leadActor": true,
"_id": "635658c18b9e50facd7f1fd1"
},
{
"actor": "63560bf55a71beb6c5bf0b1f",
"roleAs": "Ilsa Faust",
"leadActor": false,
"_id": "635658c18b9e50facd7f1fd2"
}
],
"poster": {
"url": "https://res.cloudinary.com/debfn35m1/image/upload/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"public_id": "vczxb7lgbonjn8ydsyep",
"responsive": [
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_640/v1666603204/vczxb7lgbonjn8ydsyep.jpg",
"https://res.cloudinary.com/debfn35m1/image/upload/c_scale,w_50/v1666603204/vczxb7lgbonjn8ydsyep.jpg"
]
},
"reviews": {
"ratingAvg": "5.0",
"reviewCount": 2
}
},
Im trying to write a filter function to get all movie that has Tom Cruise with actorId as a parameter but cannot get the result.
Can someone please help me with this ?
Since your actor id is inside a cast array with key actor you must specify your key while match, check the updated code below
exports.actorAggregation = (actorId) => {
return [
{
$lookup: {
from: "Movie",
localField: "cast",
foreignField: "_id",
as: "actorFilter",
},
},
{ $unwind: "$cast" },
{
$match: {
"cast.actor._id": { $in: [actorId] }, // or "cast.actor": { $in: [actorId] },
status: { $eq: "public" },
},
},
{
$project: {
title: 1,
poster: "$poster.url",
responsivePosters: "$poster.responsive",
createdAt: "$createdAt",
},
},
];
};
I am trying to use the $lookup method to find users for this object. But when I use it, it replaces the other objects. The data that was outputed is this
"notifications": {
"author": [
{
"username": "UnusualAbsurd",
"status": "Michael Ohare",
"createdAt": "2022-03-08T14:02:53.728Z",
"id": "1",
"avatar": "https://avatars.dicebear.com/api/avataaars/UnusualAbsurd.png"
}
]
}
But what I expected was this
"notifications": [
"author": [
{
"username": "UnusualAbsurd",
"status": "Michael Ohare",
"createdAt": "2022-03-08T14:02:53.728Z",
"id": "1",
"avatar": "https://avatars.dicebear.com/api/avataaars/UnusualAbsurd.png"
}
],
"type": "REQUEST",
"value": "1"
]
How do I make it output the expected version?
This is my code right now
const data = await this.notificatioModel.aggregate([
{
$match: { author: id },
},
{
$project: { _id: 0, __v: 0 },
},
{
$lookup: {
from: 'users',
localField: 'notifications.author',
foreignField: 'id',
as: 'notifications.author',
pipeline: [
{
$project: { _id: 0, email: 0, password: 0 },
},
],
},
},
]);
This is my notification document
This is my user document
i have course model like
const courseSchema = new mongoose.Schema({
name:{
type: String,
required:[true,'course must have a name.'],
unique:true
},
duration :Number,
description :String,
imageCover :String,
images:Array,
price :Number,
curriculum:
[
{
week:Number,
description:String,
total:Number,
completed:Number,
progress:Number,
links:
[
{
name:String,
link:String,
img:String,
watched:{
type:Boolean,
default:false
}
}
]
}
],
tutors:[
{
type: mongoose.Schema.ObjectId,
ref:'user'
}
]
},
{
toJSON:{virtuals : true},
toObject:{virtuals : true}
});
i want to add new objects to links array in curriculum .client side will patch request with week object id , name and link ,inside update handler i am doing somthing like this.
const cour = await Course.findOneAndUpdate({"caricullum._id":req.params.w},
{$push:{name:req.body.name,link:req.body.link}},{
new : true,
});
w params contain curriculum week _id
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e2"
},
"images": [],
"tutors": [],
"name": "c/c++",
"duration": 8,
"price": 1299,
"imageCover": "cool_lion.jpg",
"description": "",
"curriculum": [
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e3"
},
"week": 1,
"description": "introduction to microcontroller and microprocesor",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e4"
},
"name": "introduction",
"link": "https://www.youtube.com/embed/d0e6ScoS3Sw"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e5"
},
"name": "difference between mc and mp",
"link": "https://www.youtube.com/embed/dcNk0urQsQM"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e6"
},
"name": "building with microcontroller vs boards(arduino uno)",
"link": "https://www.youtube.com/embed/IdEcm3GU7TM"
}
]
},
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3e7"
},
"week": 2,
"description": "introduction to arduino uno",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e8"
},
"name": "introduction to arduino uno",
"link": "https://www.youtube.com/embed/BiCSW6QR6HA"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3e9"
},
"name": "IO PINS",
"link": "https://www.youtube.com/embed/OZGMLOwHYf8"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ea"
},
"name": "setting up arduno uno for programming",
"link": "https://www.youtube.com/embed/ELUF8m24sZo"
}
]
},
{
"_id": {
"$oid": "6138abc106b3ad1d3477b3eb"
},
"week": 3,
"description": "interfacing with different sensors",
"links": [
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ec"
},
"name": "LED Blinking(OUTPUT)",
"link": "https://www.youtube.com/embed/dnPPoetX0uw"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ed"
},
"name": "interfacing with button(INPUT)",
"link": "https://www.youtube.com/embed/58Ynhqmvzoc"
},
{
"watched": false,
"_id": {
"$oid": "6138abc106b3ad1d3477b3ee"
},
"name": "16x2 LCD",
"link": "https://www.youtube.com/embed/Mr9FQKcrGpA"
}
]
}
],
"__v": 0
}
how to query for correct week document with req.params.w and push new document into links array
use arrayFilters
db.collection.update({},
{
$push: {
"curriculum.$[elem].links": {
link: "a",
name: "b",
whatched: "c"
}
}
},
{ new:true,
arrayFilters: [
{
"elem.week": 1
}
]
})
https://mongoplayground.net/p/nLV9UzbJlsc
I have 3 collections
const userSchema = new mongoose.Schema ({
username : {
type : String,
trim: true
},
name : {
type : String,
trim: true
},
avatar : {
type : String
}
last_seen: {
type: Date,
default: Date.now
},
status: {
type : Boolean,
default: true
}
})
const hsVideoSchema = new mongoose.Schema ({
name : {
type : String,
trim: true,
required : true
},
url : {
type : String,
trim: true,
required : true
},
uploadedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
status: {
type : Boolean,
default: true
}
})
const fsVideoSchema = new mongoose.Schema ({
name : {
type : String,
trim: true,
required : true
},
url : {
type : String,
trim: true,
required : true
},
uploadedBy: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
status: {
type : Boolean,
default: true
}
})
Now, to keep user's action history, i created History Model as below :
const historySchema = new mongoose.Schema ({
user_id : {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
hs_videoId : {
type: mongoose.Schema.Types.ObjectId,
ref: 'HsVideo',
default: null
},
fs_videoId : {
type: mongoose.Schema.Types.ObjectId,
ref: 'FsVideo',
default: null
},
action : {
type : String,
trim: true,
enum:['downloaded','viewed','liked','reported']
}
})
So, i will add new record in history collection when user will perform any action. At a time, out of 2 fields (hs_videId & fs_videoId) one field will be null and another will have id of ref document. In history collection, there can be same hs_videId/fs_videId with different action ('downloaded','viewed','liked','reported').
I am looking for query to get user's history by passing user_id and get all video history array with 2 sub arrays : HsVideos and FsVideos. Both sub array should have action's sub-array, which will have complete details of video (name, url,uploadedBy(UserArray),status).
What query i should write to get desire result ?
Query i tried already :
User.aggregate([
{ $match: {_id : ObjectId('5f3a90110132e115db700201')} },
{
$lookup: {
from: "histories",
as: "history",
pipeline: [
{
$match: {
user_id : ObjectId('5f3a90110132e115db700201')
}
}
]
},
},
]).exec(function(err, results){
if(err) console.log(err);
return res.status(200).json(results);
})
Please help ! Any help will be appreciated. Thanks.
EDIT : 1
I am expecting below result :
[
{
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "John",
"status": true,
"username": "jony"
"FsVideos": [
{
Viewed :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Downloaded :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Liked :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Reported :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
}
],
"HsVideos": [
{
Viewed :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Downloaded :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Liked :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
},
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
Reported :[
{
"_id": ObjectId("5a934e000102030405000001"),
"url": "http://example.com/video.mp4",
"uploadedBy": {
"_id": ObjectId("5f3a90110132e115db700201"),
"avatar": "default.png",
"last_seen": ISODate("1970-01-01T00:00:00Z"),
"name": "A",
"status": true,
"username": "A"
},
}
],
}
]
}
]
This is totally a bad structure of schema, you really need to update it, because this will cause memory usage and execution time of the query,
You need to use lookup with pipeline and nested lookup,
$match your conditions for user
$lookup with histories collection and result will be in HsVideos
$match get histories of user_id
$lookup for hsVideo collection and result will be in hs_videoId
$match get hsVideo details
$lookup with user collection for updatedBy and result will be in updatedBy
$unwind deconstruct result updatedBy and it will be object
$unwind deconstruct hs_videoId because its array and we need object
$group by action and push required fields in v array
$project to show and hide required fields
User.aggregate([
{ $match: { _id: ObjectId("5f3a90110132e115db700201") } },
{
$lookup: {
from: "histories",
let: { user_id: "$_id" },
as: "HsVideos",
pipeline: [
{ $match: { $expr: { $eq: ["$user_id", "$$user_id"] } } },
{
$lookup: {
from: "hsVideo",
let: { hs_videoId: "$hs_videoId" },
as: "hs_videoId",
pipeline: [
{ $match: { $expr: { $eq: ["$$hs_videoId", "$_id"] } } },
{
$lookup: {
from: "user",
localField: "uploadedBy",
foreignField: "_id",
as: "uploadedBy"
}
},
{ $unwind: "$uploadedBy" }
]
}
},
{ $unwind: "$hs_videoId" },
{
$group: {
_id: "$action",
v: {
$push: {
_id: "$_id",
url: "$hs_videoId.url",
name: "$hs_videoId.name",
uploadedBy: "$hs_videoId.uploadedBy"
}
}
}
},
{ $project: { _id: 0, k: "$_id", v: 1 } }
]
}
},
i am repeating the above lines of explanation, repeat the same flow of HsVideos in FsVideos
{
$lookup: {
from: "histories",
let: { user_id: "$_id" },
as: "FsVideos",
pipeline: [
{ $match: { $expr: { $eq: ["$user_id", "$$user_id"] } } },
{
$lookup: {
from: "fsVideo",
let: { fs_videoId: "$fs_videoId" },
as: "fs_videoId",
pipeline: [
{ $match: { $expr: { $eq: ["$$fs_videoId", "$_id"] } } },
{
$lookup: {
from: "user",
localField: "uploadedBy",
foreignField: "_id",
as: "uploadedBy"
}
},
{ $unwind: "$uploadedBy" }
]
}
},
{ $unwind: "$fs_videoId" },
{
$group: {
_id: "$action",
v: {
$push: {
_id: "$_id",
url: "$fs_videoId.url",
name: "$fs_videoId.name",
uploadedBy: "$fs_videoId.uploadedBy"
}
}
}
},
{ $project: { _id: 0, k: "$_id", v: 1 } }
]
}
},
$addFields to convert FsVideos and HsVideos array to object, action as key and vlaue
{
$addFields: {
FsVideos: { $arrayToObject: "$FsVideos" },
HsVideos: { $arrayToObject: "$HsVideos" }
}
}
])
.exec(function(err, results){
if(err) console.log(err);
return res.status(200).json(results);
})
Playground
{
"success": true,
"message": "Result",
"data": [
{
"Here": [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1",
}
]
},
{
"Here": [
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
],
}
What I am expecting is this
{
"success": true,
"message": "Result",
data: [
{
"_id": "5ee97ee7f25d1c1482717bdf",
"email": "test1#test.io",
"profileImages": [],
"username": "test1",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location",
"firstName": "test1",
"lastName": "test1"},
{
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
Query I am using is for this response is below using aggregation in mongodb, lookup and project which is leading me to the some undesired response
db.collections.aggregate( [
{
$lookup: {
from: 'users',
as: 'Here',
let: {
whoDid: '$whoDid'
},
pipeline: [
{
"$match": { "$expr": { "$eq": ["$_id", "$$whoDid"] } }
},
{
$project: {
_id: 1,
email: 1,
profileImages: 1,
username: 1,
birthday: 1,
phoneNumber: 1,
firstName: 1,
lastName: 1,
fullName: 1,
// age: {$year: "$birthday"}
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },
(31558464000)]
}
}
}
],
}
},
{
$project:{
Here:1,
_id:0
}
} ,
])
who did table is one of the collection I have where I have stored the user Id and later I am populating the data using lookup
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7b"),
"whoDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"toWhomDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"modified_at" : ISODate("2020-06-17T03:07:23.217Z"),
"created_at" : ISODate("2020-06-17T03:07:23.217Z"),
"__v" : 0
}
{
"_id" : ObjectId("5ee988eb1aac0022e15dbb7c"),
"whoDid" : ObjectId("5ee97ec0f25d1c1482717bdd"),
"toWhomDid" : ObjectId("5ee97ef2f25d1c1482717be1"),
"modified_at" : ISODate("2020-06-17T03:07:23.220Z"),
"created_at" : ISODate("2020-06-17T03:07:23.220Z"),
"__v" : 0
}
Can anyone suggest me any better option so that I can get a desired respose?
It is possible to use reduce method:
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
An example:
let obj = {
"success": true,
"message": "Result",
"data": [ {
"Here": [ {
"_id": "5ee97ee7f25d1c1482717bdf", "email": "test1#test.io",
"profileImages": [], "username": "test1",
"birthday": "2020-06-11T10:11:32.000Z", "phoneNumber": "+910000000000", "location": "Test Location",
"firstName": "test1", "lastName": "test1",
}
]
},
{
"Here": [ {
"_id": "5ee97ef2f25d1c1482717be1",
"email": "test2#test.io",
"profileImages": [],
"username": "test2",
"birthday": "2020-06-11T10:11:32.000Z",
"phoneNumber": "+910000000000",
"location": "Test Location"
}
]
}
]
};
obj.data = obj.data.reduce((a, c) => {
a.push(...c.Here);
return a;
}, [])
console.log(obj);
Add these extra steps into your aggregation pipeline:
{
$unwind: "$Here"
},
{
$replaceWith: "$Here"
}
MongoPlayground
Note: You can replace $project: { _id: 1, email: 1, ... to this:
{
$addFields:{
age: {
$divide: [{ $subtract: [new Date(), "$birthday"] },(31558464000)]
}
}
}