How to select collection with id in array embed from other collection mongodb - mongodb

I have two collection: photos and users. I want select list user with user_id in likes array embed from photos collection.
photos:
{
"_id" : ObjectId(""),
"title": "Title",
"likes" : [
{
"user_id" : ObjectId("")
},
{
"user_id" : ObjectId("")
}
],
}
users:
{
{
"_id" : ObjectId(""),
"name": "Name1",
"avatar": "Path1",
},
{
"_id" : ObjectId(""),
"name": "Name2",
"avatar": "Path2",
},
}
Output with paging:
{
{
"_id" : ObjectId(""),
"name": "Name1",
"avatar": "Path1",
},
{
"_id" : ObjectId(""),
"name": "Name2",
"avatar": "Path2",
},
}

I think this will help you...
db.getCollection('photos').aggregate([{ $lookup:
{
from: "users",
localField: "likes.user_id",
foreignField: "_id",
as: "likes"
}
}
])
The output is:
{
"_id" : ObjectId(""),
"title" : "Title",
"likes" : [
{
"_id" : ObjectId(""),
"name" : "Name1",
"avatar" : "Path1"
},
{
"_id" : ObjectId(""),
"name" : "Name2",
"avatar" : "Path2"
}
]
}

Related

How to join two table in mongodb with aggregate and lookup I have as array in second table?

I have two collections:
clients
{
"_id" : ObjectId("60d203145b7b6c19b00ba576"),
"isDeleted" : false,
"createdAt" : ISODate("2021-06-22T15:06:21.564Z"),
"status" : "live",
"customerGUID" : "C8B910A3F74E",
"apps" : [
{
"url" : "https://test.com",
"loginGUID" : "12324654",
"loginAPIAccessKey" : "B072-266C369743CA",
}
],
"avatar" : "",
"description" : "",
"firstName" : "firstname",
"lastName" : "lastname",
"email" : "company#test.com",
"companyName" : "Company name",
}
visitors
{
"_id" : ObjectId("60aed4e0d6e30865f060be3c"),
"lastName" : "CAIN",
"firstName" : "DAVID",
"loginAPIAccessKey" : "B072-266C369743CA",
"email" : "cainins#att.net",
"createdAt" : ISODate("2021-05-26T23:08:16.505Z"),
"activity" : []
}
I want all visitors which have active clients with isDeleted: false status. and the relationship between visitors and clients is visitors.loginAPIAccessKey and clients.apps.loginAPIAccessKey which is in an array of objects.
Can someone help me?
You have to make use of the $lookup stage with the pipeline option.
db.visitors.aggregate([
{
"$lookup": {
"from": "clients",
"let": {
"loginAPIAccessKey": "$loginAPIAccessKey"
},
"pipeline": [
{
"$unwind": "$apps"
},
{
"$match": {
"$expr": {
"$eq": [
"$apps.loginAPIAccessKey",
"$$loginAPIAccessKey"
],
},
"isDeleted": false,
},
},
],
"as": "matchedClients"
}
},
{
"$match": {
"matchedClients": {
"$ne": []
}
},
},
])

How to write following queries in MongoDB using aggregate?

Retrieve films with an actor living in "Spain",
Retrieve films with actor details.
Collections are:
db.actor.insert([{ "actorId" : "5", "firstName" : "Ritik", "lastName" : "Roshan", "address" : { "street" : "GM Road", "city" : "Guwahati", "state" : "Aasam", "country" : "India", "pincode" : "145145" }, "contactDetails" : { "email" : "Ritik.roshan#gmail.com", "phoneno" : "9874584" }, "age" : "52" }])
db.film.insert([{ "filmId" : "10","title" : "Doshti Ka Karishma", "releaseOfYear" : "2001", "category" : ["advanture","Romantic"],
"actor" : [{ "firstName" : "Ritik", "lastName" : "Roshan" },{ "firstName" : "Karishma", "lastName" : "Kapoor" }],
"director" : [{ "firstName" : "Satish", "lastName" : "Ambike" }],
"releaseDetails" : { "place" : "Rajasthan", "date" : ISODate("2001-05-18T15:14:08.023Z"), "rating" : "C"}}])
You can use $lookup to join two collection
db.film.aggregate([
{ $match: { "releaseDetails.place": "Rajasthan" } },
{
"$lookup": {
"from": "actor",
"let": {
actor: "$actor"
},
"pipeline": [
{
$match: {
$expr: {
$and: [
{ $in: [ "$firstName", "$$actor.firstName" ] },
{ $in: [ "$lastName", "$$actor.lastName" ] }
]
}
}
}
],
"as": "joinActors"
}
}
])
Working Mongo playground
Note : You are saving firstname and lastname as reference in film collection. But combination of firstname and lastname are not always unique, Better you save _id of actor into the film collection's actor section.
something like this Save ref id

$lookup nested external id after $group

I want to replace the external user ids with the real user properties after $lookup, my data:
"comments" : [
{
"user_Id" : ObjectId("aaa"),
"content" : "aaaa",
"rep" : [
{
"user_Id" : ObjectId("bbb"),
"comment" : "bbbb",
},
{
"user_Id" : ObjectId("ccc"),
"comment" : "cccc",
}
]
},
{
"user_Id" : ObjectId("ddd"),
"content" : "ddd",
"rep" : [ ]
}
]
User collection:
"users" : [
{
"_id" : ObjectId("aaa"),
"name" : "user1",
"email" : "test1#test.com",
},
{
"_id" : ObjectId("bbb"),
"username" : "user2",
"email" : "test2#test.com",
}
]
What i want to archieve:
"comments" : [
{
"user" : {
"_id" : ObjectId("aaa"),
"name" : "user1",
"email" : "test1#test.com",
}
"content" : "aaaa",
"rep" : [
{
"userId" : {
"_id" : ObjectId("bbb"),
"username" : "user2",
"email" : "test2#test.com",
},
"comment" : "bbbb",
},
{
"user" : {
"_id" : ObjectId("aaa"),
"name" : "user1",
"email" : "test1#test.com",
},
"comment" : "cccc",
}
]
},
{
"user" : {
"_id" : ObjectId("bbb"),
"username" : "user2",
"email" : "test2#test.com",
},
"content" : "ddd",
"rep" : [ ]
}
]
Right now i managed to get my user info from the external id but i'm going crazy trying to get the user object inside the replies too, i tried to group after grouping but nothing to do, this is what i did:
db.pages.aggregate([
{
$match: { _id: ObjectId('5db599f3fffdee1c822269e0b3') }
},
{
$project: {
comments: 1,
}
},
{ $unwind: '$comments' },
{
$lookup:
{
from: 'users',
localField: 'comments.user_Id',
foreignField: '_id',
as: 'us'
}
},
{ $unwind: '$us' },
{
$group: {
_id: {
user: {
id: '$us._id',
name: '$us.username',
email: '$us.email',
},
comments: {
comment: '$comments.comment',
rep: '$comments.rep'
},
}
}
}
]).pretty()

Querying, projecting and sorting multiple fields of documents inside a mongoDB collection

I have a simple mongoDB collection, named usersCollection, whose generale structure is this:
[
{
"username" : "john",
"sex" : "m",
"email" : "john#gmail.com",
"courses" : [
{
"title" : "medicine",
"grade": 25,
},
{
"title" : "art",
"grade": 29,
},
{
"title" : "history",
"grade": 21,
}
]
},
{
"username" : "jane",
"sex" : "f",
"email" : "jane#gmail.com",
"courses" : [
{
"title" : "math",
"grade": 20,
},
{
"title" : "medicine",
"grade": 30,
}
]
},
{
"username" : "sarah",
"sex" : "f",
"email" : "sarah#gmail.com",
"courses" : [ ]
},
{
"username" : "josh",
"sex" : "f",
"email" : "josh#gmail.com",
"courses" : [
{
"title" : "english",
"grade": 28,
}
]
},
{
"username" : "mark",
"sex" : "m",
"email" : "mark#gmail.com",
"courses" : [
{
"title" : "history",
"grade": 30,
},
{
"title" : "medicine",
"grade": 19,
},
{
"title" : "math",
"grade": 22,
}
]
}
]
Every user is a member of usersCollection and has some general informations and a list of courses that he/she has already completed with the relative grades.
Can anyone tell me how I can query usersCollection to get a descending sorted array that contains an object for all users that have already completed a specific course? Every object of this array should contains the "name", the "email" and the "grade" of the relative user.
For example, launching a query on usersCollection around the course with name "medicine", I would obtain this array:
[
{
"username": "jane",
"email": "jane#gmail.com",
"grade": 30
},
{
"username": "john",
"email": "john#gmail.com",
"grade": 25
},
{
"username": "mark",
"email": "mark#gmail.com",
"grade": 19
}
]
You can manage to do it using sort and group pipeline of mongoDB.
if you want to get any specific courses you can apply match pipeline before sort pipeline.
db.users.aggregate([
{
$unwind: "$courses"
},
{
$match: {
'courses.title': 'medicine'
}
},
{
$sort: {
'courses.title': -1,
'courses.grade': -1,
}
},
{
$group: {
_id: "$courses.title",
records: {
$push: {
"_id" : "$_id",
"username" : "$username",
"sex" : "$sex",
"email" : "$email",
"grade":"$courses.grade"
}
}
}
}
])

MongoDB nested lookup with 3 child levels

I need to retrieve the entire single object hierarchy from the database as a JSON.
I'm trying aggregate for hours and can't solve how to do it with my data. So I have three collections:
form
{ "_id" : "1", "name" : "My first form" }
{ "_id" : "2", "name" : "Second one" }
{ "_id" : "3", "name" : "Another" }
question
{ "_id" : "q1", "form" : "1", "title": "What's your country?"}
{ "_id" : "q2", "form" : "1", "title": "What your favorite color?"}
{ "_id" : "q3", "form" : "1", "title": "Where do you live?"}
{ "_id" : "q4", "form" : "2", "title": "Where to go?"}
option
{ "_id" : "o1", "question" : "q1", "text" : "Brazil" }
{ "_id" : "o2", "question" : "q1", "text" : "EUA" }
{ "_id" : "o3", "question" : "q1", "text" : "China" }
{ "_id" : "o4", "question" : "q2", "text" : "Red" }
{ "_id" : "o5", "question" : "q2", "text" : "Blue" }
{ "_id" : "o6", "question" : "q2", "text" : "Green" }
I need to retrieve each form with all corresponding questions, and in each question the options for it. Like this:
[
{
_id:"q1",
name: "My first form",
questions: [
{ "_id" : "q1",
"form" : "1",
"title": "What's your country?",
"options": [
{ "_id" : "o1", "question" : "q1", "text" : "Brazil" }
{ "_id" : "o2", "question" : "q1", "text" : "EUA" },
{ "_id" : "o3", "question" : "q1", "text" : "China" }
]
},
{ "_id" : "q2",
"form" : "1",
"title": "What your favorite color",
"options": [
{ "_id" : "o4", "question" : "q2", "text" : "Red" }
{ "_id" : "o5", "question" : "q2", "text" : "Blue" },
{ "_id" : "o6", "question" : "q2", "text" : "Green" }
]
},
{ "_id" : "q3",
"form" : "1",
"title": "Where do you live?",
"options": []
}
]
},
...
]
I've tried a lot of $lookup, $unwind, another $lookup and $project, but nothing give-me that result (forms with questions inside, questions with options inside).
Please, help me! :)
I think the around is querying the question collection, looking up their questions and grouping by form, and finally lookup form and project, in that order.
This should do it. Keep in mind that _id in the output of this aggregate is the form _id.
db.question.aggregate([
{$match: {}},
{$lookup: {
from: 'option',
localField: '_id',
foreignField: 'question',
as: 'options'
}},
{$group: {
_id: "$form",
questions: {$push: {
title: "$title",
options: "$options",
form: "$form"
}}
}},
{$lookup: {
from: 'form',
localField: "_id",
foreignField: "_id",
as: 'form'
}},
{$project: {
name: {$arrayElemAt: ["$form.name", 0]},
questions: true
}}
]);
Actually.. this seems like a better alternative. It will return forms with no questions too.
db.form.aggregate([
{$match: {}},
{$lookup: {
from: 'question',
localField: '_id',
foreignField: 'form',
as: 'questions'
}},
{$unwind: {
path: "$questions",
preserveNullAndEmptyArrays: true
}},
{$lookup: {
from: 'option',
localField: 'questions._id',
foreignField: 'question',
as: 'options'
}},
{$group: {
_id: "$_id",
name: {$first: "$name"},
question: {$push: {
title: "$questions.title",
form: "$questions.form",
options: "$options"
}}
}}
])