I've a problem, actually I'm trying to join different collections for some operation, but I'm not able to get the result as both "BatchInfo" and "UserInfo" is coming as null.
The reason I'm doing "project" first is because I want to take out "Batch Id" and "User Id" from respective objects and then apply in respective "lookup" "foreignField". Also, I'm using mongo 3.2.
db.getCollection('coursecompletedfeedbacks').aggregate([
{
$project: {
"BATCH" : 1,
"FEEDBACK" : 1,
"USER" : 1,
"batchId" : "$BATCH._id",
"userId" : "$USER._id"
}
},
{
$lookup:{
from: "batches",
localField: "batchId",
foreignField: "_id",
as: "BatchInfo"
}
},
{
$lookup:{
from: "users",
localField: "userId",
foreignField: "_id",
as: "UserInfo"
}
}
])
Try as below:
db.getCollection('coursecompletedfeedbacks').aggregate([
{
$lookup:{
from: "batches",
let: { bId: "$BATCH._id" },
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", "$$bId"]
}
}
},
],
as: "BatchInfo"
}
},
{
$lookup:{
from: "users",
let: { uId: "$USER._id" },
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", "$$uId"]
}
}
},
],
as: "UserInfo"
}
},
{
$project: {
"BatchInfo" : 1,
"UserInfo" : 1,
""FEEDBACK" : 1,
}
},
])
Related
Trying to do mongodb aggregate $lookup query for following collections :
Shop collection :
{
"_id" : ObjectId("5b618a57759612021aaa2ed"),
"no" : "23456",
"date" : ISODate("2012-01-04T16:00:00.000+0000"),
"clientId" : "5b55cc5c05546200217ae0f3"
}
Client collection :
{
"_id" : ObjectId("5b55cc5c05546200217ae0f3"),
"title" : "Ms",
"name" : "Jane Marie"
}
the query :
db.getCollection("shop").aggregate([
{ $lookup:
{
from: "client",
localField: "clientId",
foreignField: "_id",
as: "client"
}
}
])
above query ends up giving an empty patient array :
{
"_id" : ObjectId("5b618a57759672021aaa2ed"),
"no" : "20190000024274",
"date" : ISODate("2012-01-04T16:00:00.000+0000"),
"clientId" : "5b55cc5c05546200217ae0f3",
"client" : []
}
Edit :
and when trying to lookup using an array of ids as local Field :
transaconsIds: ["5b61d4320550de077143b763", "5b61d4324450de002143b777"]
by using :
{
$lookup:
{
from: "transcation",
let: { vid: "transaconsIds" },
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", { $toObjectId: "$$vid" }]
}
}
}
],
as: "transactions"
}
}
this leads to an Mongo Server error.
Edit 02 :
when trying to lookup for localField which is a nested as follows :
"transactions" : [
{
"bill" : {
"soldItemIds" : [
"5b55aabf0550770021097ed2"
]
}
}
]
by using :
{ $unwind : "$transactions"},
{
$lookup:
{
from: "bill",
let: { did: "$transactions.bill.soldItemIds" },
pipeline: [
{
$match: {
$expr: {
$in: ["$_id", {
$map: {
input: "$$did",
in: { $toObjectId: "$$this" }
}
}
]
}
}
}
],
as: "bills"
}
}
this leads to an Mongo Server error too.
this should do it:
db.shop.aggregate([
{
$lookup:
{
from: "client",
let: { pid: "$clientId" },
pipeline: [
{
$match: {
$expr: {
$eq: ["$_id", { $toObjectId: "$$pid" }]
}
}
}
],
as: "client"
}
},
{
$set: {
client: {
$arrayElemAt: ["$client", 0]
}
}
}
])
update: array of id strings
db.collection.aggregate(
[
{
$lookup:
{
from: "transactions",
let: { vid: "$transactionIds" },
pipeline: [
{
$match: {
$expr: {
$in: ["$_id", {
$map: {
input: "$$vid",
in: { $toObjectId: "$$this" }
}
}
]
}
}
}
],
as: "transactions"
}
}
])
db.collection("shop").aggregate([
{ $match: { _id: shopId } },
{ $addFields: {
convertedId: {$toObjectId: "$clientId"}
}},
{ $lookup: {
from: "users",
localField: "convertedId",
foreignField: "_id",
as: "result"
}}
]);
I got 3 collections that's look like this:
Type :
{
uuid : "uuid_type_1",
info: "info sur le type 1"
}
Piece :
{
uuid : "uuid_piece_1",
type_uuid : "uuid_type_1",
info: "info sur la piece 1"
}
Photo :
{
uuid : "uuid_photo_1",
piece_uuid : "uuid_piece_1",
info: "info photo 1"
}
And I want to join all this 3 collections.
For 2, I succeed with lookup, for 3 I know I have to use pipeline and I try this but without successful.
db("Essais").collection("TYPE").aggregate([
{
$match:recherche
},
{
$lookup:{
from: "PIECE",
localField: "uuid",
foreignField : "type_uuid",
pipeline:[{
$lookup:{
from: "PHOTO",
localField: "uuid",
foreignField : "piece_uuid",
as: "PHOTOSPIECE"
}
}],
as: "PIECES"
}
}
)];
The following solution is working :
$lookup:
{
from: "PIECE",
let: { "uuidtype" : "$uuid" },
pipeline:[
{ $match: { "$expr": { "$eq": [ "$type_uuid", "$$type_uuid" ] } } },
{$lookup:
{
from: "PHOTO",
as: "PHOTOSPIECE",
let: { "uuidpiece" : "$uuid" },
pipeline:[
{ $match: { "$expr": { "$eq": [ "$piece_uuid", "$$uuidpiece" ] } }},
]
}
}
],
as: "PIECES"
}
I know that in logTable the "mailID" is "1234" (String)
and in mailTable the "_id" is 1234 (NumberInt)
But is there any way at all to do this $lookup?
log table
{
"_id" : "mailStuff0234",
"mailID" : "1234",
"typeState" : "NEW",
"changeByType" : "ADMIN"
}
mail table
{
"_id" : NumberInt(1234),
"user" : "torben#sunnythailand.com",
"subject" : "Visit to Atlantis Condo Resort"
}
and here is the aggregate
db.log.aggregate([
{ '$match': { typeState: 'NEW'} },
{ '$lookup': {
from: 'mail',
localField: 'mailID',
foreignField: '_id',
as: 'mail'
} },
{ '$unwind': '$mail' }
], {})
MongoDB 4.0 introduced $toInt operator so you can convert mailID value before applying $lookup.
db.log.aggregate([
{
$addFields: { mailID: { $toInt: "$mailID" } }
},
{
$lookup: {
from: "mail",
localField: "mailID",
foreignField: "_id",
as: "mail"
}
}
])
You can also use $lookup with custom pipeline:
db.log.aggregate([
{
$lookup: {
from: "mail",
let: { mailID: { $toInt: "$mailID" } },
pipeline: [ { $match: { $expr: { $eq: [ "$_id", "$$mailID" ] } } } ],
as: "mail"
}
}
])
I have the following mongo aggregate query:
return db.collection('projects').aggregate([
{
$match: {
agents: ObjectId(agent)
}
},
{
$lookup: {
from: "agents",
localField: "agents",
foreignField: "_id",
as: "agents"
}
},
{
$lookup: {
from: "roles",
localField: "roles",
foreignField: "_id",
as: "roles"
}
},
{
$lookup: {
from: "agencies",
localField: "agency",
foreignField: "_id",
as: "agency"
}
},
{
$lookup: {
from: "resources",
localField: "roles.applicants",
foreignField: "_id",
as: "roles.applicants"
}
}
])
It works as it should, embedding the proper documents. However, the "password_hash" field is showing for each applicant. I want to remove that field. If I try to project and set roles.applicants.password_hash: 0 I actually end up getting the entire applicant without the password hash, but the rest of the roles fields are no longer there. So I get something that looks like:
roles: {
applicants: {
name: "Josh"
}
}
That should be
roles: {
title: "Super Hero",
applicants: {
name: "Josh"
}
}
I figured it out. Here is how I did it. First, the projection wasn't the issue with why the roles document was missing fields. It was the lookup.
What I did was changed the roles lookup to use the pipeline method on the nested documents and then did another pipeline on applicants, which first matched the applicants from the resource collection and then handled the projection. It looks like this.
{
$lookup: {
from: "roles",
let: { "roles": "$roles" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$roles" ] } } },
{
$lookup: {
from: "resources",
let: { "applicants": "$applicants" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$applicants" ] } } },
{
$project: {
first_name: 1
}
}
],
as: "applicants"
}
}
],
as: "roles"
}
}
The entire aggregate looks like this
return db.collection('projects').aggregate([
{
$match: {
agents: ObjectId(agent)
}
},
{
$lookup: {
from: "agents",
localField: "agents",
foreignField: "_id",
as: "agents"
}
},
{
$lookup: {
from: "agencies",
localField: "agency",
foreignField: "_id",
as: "agency"
}
},
{
$lookup: {
from: "roles",
let: { "roles": "$roles" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$roles" ] } } },
{
$lookup: {
from: "resources",
let: { "applicants": "$applicants" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$applicants" ] } } },
{
$project: {
first_name: 1
}
}
],
as: "applicants"
}
}
],
as: "roles"
}
}
])
I have two collections points collection and users collection here i want to do aggregation based on userid
points collection
{
"userpoint": "2",
"purchaseid":"dj04944",
"store":"001",
"date":ISODate("2017-11-10T08:15:39.736Z")
"userid"[
objectID("5a7565ug8945rt67"),
objectID("8a35553d3446rt78")
]
},
{
"userpoint": "4",
"purchaseid":"5678sd",
"store":"004",
"date":ISODate("2017-11-11T08:15:39.736Z")
"userid"[
objectID("9a85653d3890rt09")
]
}
users collection
{
objectID("5a7565ug8945rt67"),
"name":"asdf",
"mobinumber":"12345",
},
{
objectID("8a35553d3446rt78"),
"name":"qwr",
"mobinumber":"11111",
},
{
objectID("9a85653d3890rt09"),
"name":"juir",
"mobinumber":"9611",
}
how can i do aggregation
db.points.aggregate([
{
$lookup:
{
from: "users",
localField: "",
foreignField: "",
as: "inventory_docs"
}
}
])
i want to combine both collections
help me out to move forward
If your expected output like bellow
{
"_id" : ObjectId("5a164fa5400096bfa0b3422c"),
"date" : ISODate("2017-11-10T08:15:39.736Z"),
"name" : "asdf",
"mobile" : "12345"
}
The can try this query
db.points.aggregate([
{
$match: {
store: "001",
date: {$lte: ISODate("2017-11-10T08:15:39.736Z"), $gte: ISODate("2017-11-10T08:15:39.736Z")}
}
},
{$unwind: "$userid"},
{
$lookup: {
from: "users",
localField: "userid",
foreignField: "_id",
as: "user"
}
},
{
$project: {
userpoint: 1,
purchaseid: 1,
date: 1,
user: {$arrayElemAt: ["$user", 0]}
}
},
{$match: {"user.name": "asdf"}},
{
$project: {
date: 1,
name: "$user.name",
mobile: "$user.mobinumber"
}
}
])