I need to convert string to objectId in mongoDB, in mongodb 4 it can be achieved through $toObjectId": "$bar_id
But the problem is my mongodb version is 3.4
Is there any way to achieve that in version 3.4?
Upgrading isn't an option since it's used in production env
The use case is I need to do lookup from one collection to another, the collection looks like
Collection F:
{
"_id" : ObjectId("a"),
"field" : "some-field",
"cityId" : "cityId",
"regionId" : "regionId",
"countryId" : "countryId",
}
and collection country looks like (region and city is similar)
{
"_id" : ObjectId("countryId"),
"name": "someName"
}
I tried using query:
db.F.aggregate([
{
$lookup:
{
from: "country",
localField: "countryId",
foreignField: "_id",
as: "country"
}
}
])
but the result looks like:
{
"_id" : ObjectId("a"),
"field" : "some-field",
"cityId" : "cityId",
"regionId" : "regionId",
"countryId" : "countryId",
"country" : [
]
}
Any advice?
Thank you
Related
Here I have two collections :
conso
{
"_id" : ObjectId("5684f3c454b1fd6926c322fd"),
"client" : "1",
"conso" : "4"
}
{
"_id" : ObjectId("56d82612b63f1f31cf906003"),
"client" : "1",
"conso" : "2"
}
{
"_id" : ObjectId("56d82612b63f1c31cf906004"),
"client" : "2",
"conso" : "10"
}
{
"_id" : ObjectId("59301c39028afaf3450e2890"),
"client" : "2",
"conso" : "20"
}
{
"_id" : ObjectId("59301c39029afaf4450e2885"),
"client" : "3",
"conso" : "18"
}
{
"_id" : ObjectId("59301c39030afaf4450e2885"),
"client" : "3",
"conso" : "12"
}
class
{
"_id" : ObjectId("5f6d219d345f0066299c1fd6"),
"CLIENT" : "1",
"class" : "A"
}
{
"_id" : ObjectId("5e6d219c345f0066299c1fd6"),
"CLIENT" : "2",
"class" : "A"
}
{
"_id" : ObjectId("5e6d02c97d9426227fa00401"),
"CLIENT" : "3",
"class" : "B"
}
I would like to have :
{"class" : "A", avg : 9}
{"class" : "B", avg : 15}
My code :
db.conso.aggregate([
{$group: {_id : {class: "$class"}, avg: { $avg: "$conso" }}},
{$lookup: {from: "class", localField: "client", foreignField: "CLIENT", as: "class_info"}}
]);
and I obtain :
{ "_id" : { "class" : null }, "avg" : 11, "class_info" : [ ] }
After having the below changes to your conso collection and your query, we can get the desired result.
Modification in conso collection
The attribute conso in the conso collection takes a string value which we need to change it into number, so the modified collection will look like
{"_id":"5684f3c454b1fd6926c322fd","client":"1","conso":4},
{"_id":"56d82612b63f1f31cf906003","client":"1","conso":2},
{"_id":"56d82612b63f1c31cf906004","client":"2","conso":10},
{"_id":"59301c39028afaf3450e2890","client":"2","conso":20},
{"_id":"59301c39029afaf4450e2885","client":"3","conso":18},
{"_id":"59301c39030afaf4450e2885","client":"3","conso":12}
If you are not willing to modify your collection then you can use $toInt to convert the conso string into number, this step will add another pipeline stage( $project ) to our existing query between $lookup and $group. Please note that $toInt will be giving error if the value cannot be converted to int.
Modification to the query
Do the $lookup first and then perform $group and in the group stage _id part need to changed from class: "$class" to class: "$class_info.class"
Modified query will be
db.conso.aggregate([
{ $lookup: {
from: "class",
localField: "client",
foreignField: "CLIENT",
as: "class_info"}
},
{ $group: {_id : {class: "$class_info.class"}, avg: { $avg: "$conso" }}},
]);
Hope it Helps!
I was trying to join multiple collections in MongoDB using the aggregate $lookup.The issue I am facing right now $lookup localField attribute does not accept $ character.
I have following three collections.
student
{
"_id" : ObjectId("5db12e6dfc368dff1cfc30e5"),
"studentId" : "S97YAREA51",
"name" : "Has Maara duwa",
"age" : 22
}
course
{
"_id" : ObjectId("5db12e6dfc368dff1cfc20e5"),
"courseId" : "C04865690",
"courseName" : "Love and Empathy"
}
studentCourse
{
"_id" : ObjectId("5db12e6dfc368dff1cfc10e5"),
"student" : {
"$ref" : "student",
"$id" : ObjectId("5db12e6dfc368dff1cfc30e5")
},
"course" : {
"$ref" : "course",
"$id" : ObjectId("5db12e6dfc368dff1cfc20e5")
}
}
I need to update studentCourse collection records to something like below.
{
"_id" : ObjectId("5db12e6dfc368dff1cfc10e5"),
"student" : {
"$ref" : "student",
"$id" : ObjectId("5db12e6dfc368dff1cfc30e5")
},
"course" : {
"$ref" : "course",
"$id" : ObjectId("5db12e6dfc368dff1cfc20e5")
},
"studentId" : "S97YAREA51",
"courseId" : "C04865690"
}
I tried to create the following aggregation query, but it was failing due to localField does not accept $ character. I would be much appreciated if somebody provides me a simple solution for this matter.
db.studentCourse.aggregate([
{
$lookup:{
from: "student",
localField: "student.$id",
foreignField: "_id",
as: "student"
}
},
{ $unwind:"$student" }, // $unwind used for getting data in object or for one record only
{
$lookup:{
from: "course",
localField: "course.$id",
foreignField: "_id",
as: "course"
}
},
{ $unwind:"$course" },
// define which fields are you want to fetch
{
$project:{
"_id" : 1,
"student" : 1,
"course" : 1,
"studentId" : "$student.studentId",
"courseId" : "$course.courseId",
}
}
]);
collection A document 1
{
"_id" : ObjectId("5c2ee03224acf45a663d8f09"),
"_class" : "document.domain.DDD",
"generated" : false,
"linkIds" : [],
"types" : [],
"metadata" : {
"templateId" : "ABDC",
"userId" : "Master"
}
"versions" : [
{
"revision" : "fb4fb8ec-edfe-4a3e-a1a9-c8c4b2bce678",
"fileId" : "5c2ee03224acf45a663d8f08"
}
]
}
collection B document 1
{
"_id" : ObjectId("5c2ee03224acf45a663d8f08"),
"_class" : "document.domain.RDF",
"extension" : ".pdf",
"rootPath" : "D"
"size" : 152754
}
the field id in collection A , document 1 appears as String in objectid of collection B doc 1.
how to lookup for the string in collection B which appears as objecid?
you have to use mongodb aggregation there
you have view this more on
https://docs.mongodb.com/manual/core/aggregation-pipeline/
and you have to use $lookup operator more you learn this on
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
you can achived your task doing this
collectionA.aggregate.([
{
$match:{},// To match and get all doc
},
{
$lookup:
{
from: collection B//<collection to join>,
localField: versions.fileId//<field from the input documents>,
foreignField: _id//<field from the documents of the "from" collection>,
as: versions.file//<output array field>
}
}])
I have two collections one is user and other is address.
User document has list which contains the publicId of addresses.
I am writing an API to fetch users. How can I return the merged result of user and addresses documents?
User :
{
"_id" : ObjectId("5684f3c454b1fd6926c324fd"),
"email" : "user#example.com",
"userId" : "userId",
"addresses" : ["A1234","A5678"]
}
Address :
{
"_id" : ObjectId("56d82612b63f1c31cf906004"),
"publicId" : "A1234"
"addressLine1" : "AD1",
"addressLine2" : "AD1",
"pin" : "001"
}
{
"_id" : ObjectId("56d82612b63f1c31cf906005"),
"publicId" : "A5678"
"addressLine1" : "AD2",
"addressLine2" : "AD2",
"pin" : "002"
}
What I am trying to achieve is following
{
"_id" : ObjectId("5684f3c454b1fd6926c324fd"),
"email" : "user#example.com",
"userId" : "userId",
"addresses" : [
{
"publicId" : "A1234"
"addressLine1" : "AD1",
"addressLine2" : "AD1",
"pin" : "001"
},
{
"publicId" : "A5678"
"addressLine1" : "AD2",
"addressLine2" : "AD2",
"pin" : "002"
}
]
}
how can I achieve this using aggregate query?
for that you can use $lookup stage from aggregation framework:
db.user.aggregate([
{$lookup:
{
from : 'addresses',
localField: 'Addresses',
foreignField: 'publicId',
as: 'Addresses'
}
},
{$project: {'Addresses._id': 0} }
]).pretty()
for using $lookup (similar to left outer join) you need to use MongoDB version 3.2 or above.
I got it working. Following is the aggregate query I used.
db.user.aggregate([
{
$unwind: "$addresses"
},
{
$lookup:
{
from: "address",
localField: "addresses",
foreignField: "publicId",
as: "addresses"
}
},
{
$match: {
"userId":"userId",
"addresses": { $ne: [] }
}
}
])
So I have collections projects which has field contacts.envCon.$id:
{
"contacts" : {
...
"envCon" : {
"$ref" : "contacts",
"$id" : ObjectId("5807966090c01f4174cb1714") <---- NOTICE!!!
}
...
}
}
On contacts collection Object with id Example12345 looks like this:
{
"_id" : ObjectId("5807966090c01f4174cb1714"),
"name" : "Terracon"
}
So I tried the following $lookup from aggregation framework:
db.getCollection('projects').aggregate([
{
$lookup:{
from: "contacts",
localField: "contacts.envCon.id",
foreignField: "id",
as: "example"
}
}
]);
But it is not doing the JOIN what am I missing? how to do lookups between 2 collections using contacts.envCon.id from projects and _id from contacts.
I'm using meteor just in case.
I'm not sure what is going on with your ObjectId values; I'm not even able to insert a field value of ObjectId("Example12345"). The difference in ObjectID values between the two collections is likely what is causing the $lookup to fail.
The aggregation query you provided works in my environment when I let MongoDB generate the _id ObjectID value in "contacts" and store the same value in the "projects" collection.
$ db.projects.find().pretty()
{
"_id" : ObjectId("580832011b3c40dba2ae6e32"),
"contacts" : {
"envCon" : DBRef("contacts", ObjectId("580831d61b3c40dba2ae6e31"))
}
}
$ db.contacts.find().pretty()
{ "_id" : ObjectId("580831d61b3c40dba2ae6e31"), "name" : "Terracon" }
$ db.getCollection("projects").aggregate([ { "$lookup" : { "from" : "contacts", "localField" : "contacts.envCon.id", "foreignField" : "id", "as" : "example" } } ]).pretty()
{
"_id" : ObjectId("580832011b3c40dba2ae6e32"),
"contacts" : {
"envCon" : DBRef("contacts", ObjectId("580831d61b3c40dba2ae6e31"))
},
"example" : [
{
"_id" : ObjectId("580831d61b3c40dba2ae6e31"),
"name" : "Terracon"
}
]
}