MongoDB $lookup returns empty array [duplicate] - mongodb

This question already has answers here:
Moongoose aggregate $match does not match id's
(5 answers)
Closed 4 years ago.
When i am trying to JOIN in mongo db the $lookup returns the empty array.
I have two collection one is user_information and another one is add_to_cart.In that i want to get add_to_cart details of user form add_to_cart collection using user_id in user_information.
add_to_cart collection:
[
{
"_id": {
"$id": "592ec12b744a12d014000031"
},
"order_id": "592ec125744a12d014000030",
"table_id": 1,
"category_name": "veg",
"food_id": "5923c8bc744a12441e000031",
"user_id": "592ec125744a12d01400002f",
"food_name": "Cream Of Mushroom Soup",
"food_per_price": "100",
"food_total_price": 100,
"food_qty": 1,
"active_status": 0,
"created_at": {
"sec": 1496236331,
"usec": 0
},
"updated_at": {
"sec": 1496236331,
"usec": 0
}
},
{
"_id": {
"$id": "592ec12e744a12d014000032"
},
"order_id": "592ec125744a12d014000030",
"table_id": 1,
"category_name": "veg",
"food_id": "5923c8cb744a12441e000033",
"user_id": "592ec125744a12d01400002f",
"food_name": "Cream Of Mushroom Soup",
"food_per_price": "100",
"food_total_price": 100,
"food_qty": 1,
"active_status": 0,
"created_at": {
"sec": 1496236334,
"usec": 0
},
"updated_at": {
"sec": 1496236334,
"usec": 0
}
}
]
user_information collection:
[
{
"_id": {
"$id": "592ec125744a12d01400002f"
},
"branch_id": 1,
"brand_id": 1,
"business_id": 1,
"table_id": 1,
"uid": "116907438816775509716",
"user_name": "dhamo dharan",
"user_email": "dhamursv#gmail.com",
"user_provider": "google",
"user_image": "https://lh5.googleusercontent.com/-Masl6FTlG_g/AAAAAAAAAAI/AAAAAAAAAEo/UV3oTjMnqzQ/s96-c/photo.jpg",
"active_status": 0,
"created_at": {
"sec": 1496236325,
"usec": 0
},
"updated_at": {
"sec": 1496236325,
"usec": 0
}
}
]
my database query
db.add_to_cart.aggregate([
{ "$match": { "user_id": "592ec125744a12d01400002f" } },
{ "$sort": { "created_at": -1 } },
{ "$limit": 20 },
{ "$lookup": {
"from": "user_information",
"localField": "user_id",
"foreignField": "_id",
"as": "userinfo"
} },
{ "$unwind": "$userinfo" },
{ "$project": {
"food_name": 1,
"food_qty": 1,
"userinfo.user_name": 1,
"userinfo.user_email": 1
} }
])
It will return empty result i don't know what went wrong.Thanks in advance!

In Simple Words - your match query is wrong .
Because "user_id": "592ec125744a12d01400002f" is a "string" , matching works fine with normal find query with string ObjectId
but when we talk about aggregate , you can not give direct string .. you always give mongoose.Types.ObjectId(userId) , where userId is string
var userId="592ec125744a12d01400002f";
db.add_to_cart.aggregate([
{ "$match": { "user_id": mongoose.Types.ObjectId(userId) } },
{ "$sort": { "created_at": -1 } },
{ "$limit": 20 },
{ "$lookup": {
"from": "user_information",
"localField": "user_id",
"foreignField": "_id",
"as": "userinfo"
} },
{ "$unwind": "$userinfo" },
{ "$project": {
"food_name": 1,
"food_qty": 1,
"userinfo.user_name": 1,
"userinfo.user_email": 1
} }
])

Related

How to replace array of object containing ids with the data using MongoDB aggregation

I am having a collection which contains the data like the following and want to have the desirable output which I have mentioned below.
db={
collectionA: [
{
"id": ObjectId("63b7c24c06ebe7a8fd11777b"),
"uniqueRefId": "UUID-2023-0001",
"products": [
{
"productIndex": 1,
"productCategory": ObjectId("63b7c24c06ebe7a8fd11777b"),
"productOwners": [
ObjectId("63b7c2fd06ebe7a8fd117781")
]
},
{
"productIndex": 2,
"productCategory": ObjectId("63b7c24c06ebe7a8fd11777b"),
"productOwners": [
ObjectId("63b7c2fd06ebe7a8fd117781"),
ObjectId("63b7c12706ebe7a8fd117778")
]
},
{
"productIndex": 3,
"productCategory": "",
"productOwners": ""
}
]
}
],
collectionB: [
{
"_id": ObjectId("63b7c2fd06ebe7a8fd117781"),
"fullname": "Jim Corbett",
"email": "jim.corbett#pp.com"
},
{
"_id": ObjectId("63b7c12706ebe7a8fd117778"),
"fullname": "Carry Minatti",
"email": "carry.minatty#pp.com"
},
]
}
Desirable Output = [
{
"id": ObjectId("507f1f77bcf86cd799439011"),
"uniqueRefId": "UUID-2023-0001",
"products": [
{
"productIndex": 1,
"productCategory": ObjectId('614g2f77bff86cd755439021'),
"productOwners": [
{
"_id": ObjectId("63ac1e59c0afb8b6f2d41acd"),
"fullname": "Jim Corbett",
"email": "jim.corbett#pp.com"
}
]
},
{
"productIndex": 2,
"productCategory": ObjectId('614g2f77bff86cd755439021'),
"productOwners": [
{
"_id": ObjectId("63ac1e59c0afb8b6f2d41acd"),
"fullname": "Jim Corbett",
"email": "jim.corbett#pp.com"
},
{
"_id": ObjectId("63ac1e59c0afb8b6f2d41ace"),
"fullname": "Carry Minatti",
"email": "carry.minatty#pp.com"
}
]
},
{
"productIndex": 3,
"productCategory": "",
"productOwners": ""
}
]
}
]
In the collectionA we are having other documents as well, its not just one document.
Similarly for collectionB we are having other documents too.
How we can get this desirable output?
I am expecting the mongodb query for getting this solution.
I have implemented the lookup like the following
db.collectionA.aggregate([
{
"$lookup": {
"from": "collectionB",
"localField": "products.productOwners",
"foreignField": "_id",
"as": "inventory_docs"
}
}
])
You can try this:
db.collectionA.aggregate([
{
"$unwind": "$products"
},
{
"$lookup": {
"from": "collectionB",
"localField": "products.productOwners",
"foreignField": "_id",
"as": "products.productOwners"
}
},
{
"$group": {
"_id": {
id: "$id",
uniqueRefId: "$uniqueRefId"
},
"products": {
"$push": "$products"
}
}
},
{
"$project": {
id: "$_id.id",
uniqueRefId: "$_id.uniqueRefId",
products: 1,
_id: 0
}
}
])
Playground link.
In this query, we do the following:
First we unwind the products array, using $unwind.
Then we calculate productOwners, using $lookup.
Then we group the unwinded elements, using $group.
Finally we, project the desired output using $project.

$lookup ObjectId in an array of ObjectId mongoose

So basically I have a Patient schema, in which there are 2 fields:
patientSchema = {
//other_fields
current_facility: {
type: mongoose.Schema.Types.ObjectId,
ref: "Facility",
},
close_contact_list: {
type: [mongoose.Schema.Types.ObjectId],
ref: "Patient",
}
}
If i populate like this
Patient.find().populate({
path: "close_contact_list",
populate: {
path: "current_facility",
model: "Facility",
},
select: "id_number name dob status current_facility",
})
The result of 1 document would be:
{
//other_fields
"close_contact_list": [
{
"_id": "62e7e80bcdde7f149602775e",
"id_number": "201260388",
"name": "Tom",
"dob": "2003-01-01T00:00:00.000Z",
"status": "F1",
"current_facility": {
"location": {
"formattedAddress": "Phuong Phường 2, Quan Quận 2, TP Hồ Chí Minh",
"province": "Hồ Chí Minh",
"district": "Quận 2",
"ward": "Phường 2"
},
"_id": "62e7d60596997310f14e4bdb",
"name": "Thu Duc",
"capacity": 3000,
"current_count": 2,
"__v": 0
}
},
{
//similar_to_above
},
...
]
}
My question is how can i do the same thing but by using aggregate. I appreciate your help.
Try this:
Patient.aggregate([
{
"$lookup": {
"from": "Facility",
"localField": "_id",
"foreignField": "current_facility",
"as": "current_facility"
}
},
{
"$project": {
"id_number": 1,
"name": 1,
"dob": 1,
"status": 1,
"current_facility": 1
}
}
])

I want to aggregate data array inside another array in mongodb

I want to aggregate MongoDB documents which is having arrays inside of an array. my document was like the below.
{
"_id": "6257e31d11a9d5231c05c084",
"name": "Test Name 1",
"phone": "1234567891",
"visits": [
{
"_id": "6257e31d11a9d5231c05c069",
"date": "2-7-2021",
"samples": [
"6257f8855197613b641d494e",
....
],
"products_detailed": [
"5d725cd2c4ded7bcb480eab2",
.....
]
},
...........
]
}
and I want to get the output line below
{
"_id": "6257e31d11a9d5231c05c084",
"name": "Test Name 1",
"phone": "1234567891",
"visits": [
{
"_id": "6257e31d11a9d5231c05c069",
"date": "2-7-2021",
"samples": [
{
"_id": "6257f8855197613b641d494e",
"product_name": "Samor",
"price": 250
},
........
],
"products_detailed": [
{
"_id": "5d725cd2c4ded7bcb480eab2",
"product_name": "Pahad",
"price": 100
},
............
]
},
.........................
]
}
how can I get like this? I tried to use $lookup & group to get the output, but I am not getting the output as required me.
Since you have a list of visits on each document, one way to go is to $unwind and then $group at the end, like this:
db.Main.aggregate([
{
$unwind: "$visits"
},
{
"$lookup": {
"from": "Samples",
"localField": "visits.samples",
"foreignField": "_id",
"as": "samples"
}
},
{
"$lookup": {
"from": "Product Detailed",
"localField": "visits.products_detailed",
"foreignField": "_id",
"as": "products_detailed"
}
},
{
$project: {
name: 1,
phone: 1,
"visits._id": 1,
"visits.date": 1,
"visits.products_detailed": "$products_detailed",
"visits.samples": "$samples"
}
},
{
$group: {
_id: 0,
name: {$first: "$name"},
visits: {$push: "$visits"}
}
}
])
As you can see on the playground, on your data sample it will return:
[
{
"_id": 0,
"name": "Test Name 1",
"visits": [
{
"_id": "6257e31d11a9d5231c05c069",
"date": "2-7-2021",
"products_detailed": [
{
"_id": "5d725cd2c4ded7bcb480eab2",
"price": 100,
"product_name": "Pahad"
}
],
"samples": [
{
"_id": "6257f8855197613b641d494e",
"price": 250,
"product_name": "Samor"
}
]
}
]
}
]

Get the count of total submissions and the number of submissions with "AC" using $lookup operator

I have the following MongoDB collection:
db={
"problems": [
{
"problemId": 1,
"title": "dummy 1",
},
{
"problemId": 2,
"title": "dummy 2",
}
],
"submissions": [
{
"submissionId": 1,
"status": "AC",
"problemId": 1,
},
{
"submissionId": 2,
"status": "AC",
"problemId": 1,
},
{
"submissionId": 3,
"status": "WA",
"problemId": 2,
},
{
"submissionId": 4,
"status": "WA",
"problemId": 1,
},
{
"_id": 5,
"status": "AC",
"problemId": 2,
},
{
"_id": 6,
"status": "WA",
"problemId": 2,
}
]
}
I want to show the total submission count and the number of solutions with status = 'AC'. I want the result to look like this:
[
{
"problemId": 1,
"title": "dummy 1",
"total_submissions": 3,
"accepted_submissions": 2
},
]
So far I have used the $lookup operator and did something like this:
db.problems.aggregate([
{
"$lookup": {
"from": "submissions",
"localField": "problemId",
"foreignField": "problemId",
"as": "submission_docs"
}
}
])
But the result I get is: (I'm just showing 1 item in the list)
[
{
"_id": ObjectId("5a934e000102030405000000"),
"problemId": 1,
"submission_docs": [
{
"_id": ObjectId("5a934e000102030405000003"),
"problemId": 1,
"status": "AC",
"submissionId": 1
},
{
"_id": ObjectId("5a934e000102030405000004"),
"problemId": 1,
"status": "AC",
"submissionId": 2
},
{
"_id": ObjectId("5a934e000102030405000006"),
"problemId": 1,
"status": "WA",
"submissionId": 4
}
],
"title": "dummy 1"
}
]
The MongoDB playground can be found here: https://mongoplayground.net/p/YRdpyQN5f00
Use $size to count the submission_docs array length for total_submissions.
Filter the submission with status "AC" in submission_docs via $filter and next count the array length.
db.problems.aggregate([
{
"$lookup": {
"from": "submissions",
"localField": "problemId",
"foreignField": "problemId",
"as": "submission_docs"
}
},
{
$project: {
_id: 0,
problemId: 1,
title: 1,
total_submissions: {
$size: "$submission_docs"
},
accepted_submissions: {
$size: {
$filter: {
input: "$submission_docs",
cond: {
$eq: [
"$$this.status",
"AC"
]
}
}
}
}
}
}
])
Sample Mongo Playground

How to use mongoose lookup child match? [duplicate]

This question already has an answer here:
Aggregation filter after $lookup
(1 answer)
Closed 5 years ago.
Sorry my English is bad...
How to use mongoose lookup child match?
My query is
categorys.aggregate([{
"$sort": {
"order": 1,
"id": 1
}
},
{
"$lookup": {
"localField": "id",
"from": "categorys",
"foreignField": "parentId",
"as": "child"
}
},
{
"$match": {
see: true,
depth: 1
}
}
]).exec(function(err, Categorys)
is result
{
"_id": "596e237c414f2137b0c4e9c2",
"id": 3,
"name": "DB",
"address": "DB",
"parentId": 0,
"depth": 1,
"see": true,
"__v": 0,
"child": [{
"_id": "596e24701e1bd30dc415b894",
"id": 5,
"name": "Mongodb",
"address": "Mongodb",
"parentId": 3,
"depth": 2,
"see": true,
"__v": 0
},
{
"_id": "596e24821e1bd30dc415b895",
"id": 6,
"name": "mssql",
"address": "mssql",
"parentId": 3,
"depth": 2,
"see": false,
"__v": 0
}
]
}]
I don't look result in mssql (see:false) how about match?
Help me!
You can use $filter in $project stage if you want to match in child array. like bellow.
categorys.aggregate([
{
"$sort": {
"order": 1,
"id": 1
}
},
{
"$lookup": {
"localField": "id",
"from": "categorys",
"foreignField": "parentId",
"as": "child"
}
},
{
$project: {
name: 1,
address: 1,
// ... as you need
child: {
$filter: {
input: "$child",
as: "item",
cond: {
$and: [
{$eq: ["$$item.see", true]},
{$eq: ["$$item.depth", 2]}
]
}
}
}
}
}
])
N.B: If you want to use match condition for parent field like "depth":1,"see":true, then you should use that $match stage before $lookup
categorys.aggregate([
{$match:{//parent field match condition first}},
{$sort:{}},
{$lookup:{}},
{$project:{//for child}}
]);