$lookup aggregation failed to display array value - mongodb

I'm working with MongoDB and I've 2 collections.
data collection ["user-profile"]
{
"_id" : ObjectId("60650e6fc4b4603e1e78bb23"),
"firstName" : "Luthfan",
"lastName" : "Difiesa",
"mobile" : "86742633497",
"gender" : "male",
"createdOn" : ISODate("2021-04-22T05:26:07.428+0000"),
"updatedOn" : ISODate("2021-04-22T05:26:55.218+0000")
}
data collection ["user-wishlist"]
{
"_id" : ObjectId("60650e7a1a4a817a1dd0a29c"),
"userId" : "86742633497",
"contents" : [
{
"_id" : ObjectId("5ef9d2da228f840bbd41649c"),
"name" : "Kelas 11"
}
]
}
expected output:
{
"_id" : ObjectId("60650e6fc4b4603e1e78bb23"),
"firstName" : "Luthfan",
"lastName" : "Difiesa",
"mobile" : "86742633497",
"gender" : "male",
"contents" : [
{
"_id" : ObjectId("5ef9d2da228f840bbd41649c"),
"name" : "Kelas 11"
}
]
}
Here's the query:
db.getCollection("user-profile").aggregate(
[
{
"$lookup" : {
"from" : "user-wishlist",
"localField" : "mobile",
"foreignField" : "userId",
"as" : "contents"
}
}
],
{
"allowDiskUse" : false
}
);
But the result is like this:
{
"_id" : ObjectId("60650e6fc4b4603e1e78bb23"),
"firstName" : "Luthfan",
"lastName" : "Difiesa",
"mobile" : "86742633497",
"gender" : "male",
"contents" : [
]
}
is't because of collection name using special character or type data from foreign or localField? thank u...

Your query looks good, just need add a stage after lookup to achieve your desire result,
{
$addFields: {
contents: {
$arrayElemAt: ["$contents.contents", 0]
}
}
}
Playground

Related

Lookup stage not working after unwind operation in aggregate pipeline in mongodb

Being relatively new in mongodb I performed an aggregation pipeline with this three table and surprisingly I am getting the "r2" array as empty in the third lookup stage of the pipeline.I crosschecked the field names and everything is alright.
db.user.aggregate([
{
$lookup:{
from:"enrollment",
localField:"user_id",
foreignField:"userID",
as:"r1"
}
},
{
$unwind:{
path:"$r1",
includeArrayIndex:"r1_id"
}
},
{
$lookup:{
from:"course",
localField:"r1.courseID",
foreignField:"courseID",
as:"r2"
}
}
])
I have three collection as user , enrollment and course which are.
User as
> db.user.find()
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" : "Christian",
"last_name" : "Hur", "email" : "christian#uta.com", "password" : "abc1234" }
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2cb"), "user_id" : 2, "first_name" : "Mary", "last_name" :
"Jane", "email" : "mary.jane#uta.com", "password" : "password123" }
{ "_id" : ObjectId("5ef4bc2563742adee5403b1d"), "user_id" : 3, "first_name" : "ari", "last_name" :
"dutta", "email" : "dutta#uta.com", "password" : "po1234" }
And , course as
> db.course.find()
{ "_id" : ObjectId("5ef4c1b64a77aec0af5e73ae"), "courseID" : 3333, "title" : "Adv PHP 201",
"description" : "Advance PHP programming", "credits" : 3, "term" : "fall" }
{ "_id" : ObjectId("5ef4c20d4a77aec0af5e73af"), "courseID" : 5555, "title" : "Java 201",
"description" : "Advanced Programming", "credits" : 4, "term" : "fall"}
{ "_id" : ObjectId("5ef4c2564a77aec0af5e73b0"), "courseID" : 6666, "title" : "Angular 1",
"description" : "Intro to Angular", "credits" : 3, "term" : "fall,spring" }
And enrollment as
> db.enrollment.find()
{ "_id" : ObjectId("5ef771f42d98ffab4460a651"), "userID" : 1, "courseID" : "3333" }
{ "_id" : ObjectId("5ef7722d2d98ffab4460a652"), "userID" : 1, "courseID" : "6666" }
Result
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" :
"Christian", "last_name" : "Hur", "email" : "christian#uta.com", "password" :
"abc1234", "r1" : { "_id" : ObjectId("5ef771f42d98ffab4460a651"), "userID" :
1, "courseID" : "3333" }, "r1_id" : NumberLong(0), "r2" : [ ] }
{ "_id" : ObjectId("5ef4ba8d500ac8876da0d2ca"), "user_id" : 1, "first_name" :
"Christian", "last_name" : "Hur", "email" : "christian#uta.com", "password" :
"abc1234", "r1" : { "_id" : ObjectId("5ef7722d2d98ffab4460a652"), "userID" :
1, "courseID" : "6666" }, "r1_id" : NumberLong(1), "r2" : [ ] }
I also checked the documentation but found no help , how can I fix this ?
You have a type mismach on courseID between the collections, in enrollment it's type string and in course it's type number.
Change your $lookup into this:
{
$lookup: {
from: "course",
let: {
courseID: {
$toInt: "$r1.courseID"
}
},
pipeline: [
{
$match: {
$expr: {
$eq: [
"$$courseID",
"$courseID"
]
}
}
}
],
as: "r2"
}
}
Try it yourself:
Mongo Playground
Also since you say you're new I personally advice you to use the _id field instead of the courseID/user_id that you generated yourself. it will just make it easier to maintain.
For Mongo version 4.2+ here is how to update the enrollment collection field:
db.enrollment.updateMany(
{},
[
{
$set: {
courseID: {$toInt: "$courseID"}
}
}
]
)

Update query on in the collection by "_id"

{
"_id" : "tenant/data/EMAIL/ENGLISH",
"tenantId" : "tenant2",
"channelType" : "EMAIL",
"template" : [
{
"_id" : "1",
"templateName" : "abc",
"effectiveStartDate" : ISODate("2017-01-01T12:00:00.000Z"),
"modifiedDate" : ISODate("2017-06-02T22:08:55.782Z"),
"active" : false
}
]
}
I need to update the "templateName" : "xyz" on the basis of "_id" : "tenant/data/EMAIL/ENGLISH"
I have tried these queries but got no success
db.getCollection('data').updateOne({"_id": "tenant/data/EMAIL/ENGLISH"},
{$set : { "template.$.templateName" : "XYZ"}}); 
db.getCollection('data').updateOne({"_id": "tenant/data/EMAIL/ENGLISH"},
{$set : { "template.templateName" : "XYZ"}}); 
Any help will be appreciated.
I have used positional-all operator to update the array.
Here is the query:
db.sample.update(
{
"_id": "tenant/data/EMAIL/ENGLISH"
},
{
$set:{
"template.$[].templateName":"XYZ"
}
}
)
Output
{
"_id" : "tenant/data/EMAIL/ENGLISH",
"tenantId" : "tenant2",
"channelType" : "EMAIL",
"template" : [
{
"_id" : "1",
"templateName" : "XYZ",
"effectiveStartDate" : ISODate("2017-01-01T12:00:00Z"),
"modifiedDate" : ISODate("2017-06-02T22:08:55.782Z"),
"active" : false
}
]
}
hope this will help :)

I Want add if data in element array not exists

I have this data in database.
{
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7b"),
"name" : "Jhones Crows",
"hobbies" : [
{
"name" : "swim",
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7b")
},
{
"name" : "run",
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7c")
}
]
}
And I try to add data into hobbies if data in hobbies not exist. I try this :
db.getCollection('milo').update(
{'_id' : ObjectId("5a6ef287370ff5dc3d6fda7b"), 'hobbies.name' : 'sport'},
{ $addToSet : { 'hobbies' : {
'name' : 'sport',
}}
},
{upsert : true}
)
And I want data result like this :
{
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7b"),
"name" : "Jhones Crows",
"hobbies" : [
{
"name" : "swim",
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7b")
},
{
"name" : "run",
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7c")
},
{
"name" : "sport",
"_id" : ObjectId("5a6ef287370ff5dc3d6fda7a")
}
]
}
so suppose the value of sport is not in hoobies.name. will add a new name object in the hobbies. but if there is not change anything

MongoDB $lookup on array of object

I have 2 collections structured as below. I have tried $lookup to get the result but I am not getting any result because of my local and foreign fields are in array of object.
Below is my structure:
{
"_id" : ObjectId("5795a3531d3f3afc19caefef"),
"name" : "category1",
"updatedAt" : "1469431592786",
"resources" : [
{
"_id" : ObjectId("5791be003fa3bedc15d3adde"),
"title" : "resource1",
"availability" : false
},
{
"_id" : ObjectId("5795a3771d3f3afc19caeff0"),
"title" : "resource2",
"availability" : true
}
]
}
Above "categories" schema have resources array of object. this resource _id is stored in bookings collection in following way:
"booking":
{
"_id" : ObjectId("57960aa8000ca7a46b7ef683"),
"name" : "1469491200000",
"__v" : 0,
"schedule" : [
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
}
Now I want to get all the schedule of booking collection with their resource information.I want to fetch resources from categories table on the basis of booking schedule.
Desired output:
[
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"resourceTitle":"title",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
},
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"resourceTitle":"mr3",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
}
]
}
]
Help me to get this desired result.
Thanks.

How to get exact document result from key value type of embedded documents

Let say I have this kind of document structured, the attributes field will be the embedded document
and I've already indexed the attributes.key and attributes.value
1-------------------------------------------------------------------------------------
{
"_id" : ObjectId( "5191d8e5d00560402e000001" ),
"attributes" : [
{ "key" : "pobox","value" : "QaKUWo" },
{ "key" : "city", "value" : "CBDRip" },
{ "key" : "address","value" : "zmycAa" } ],
"email" : "FWAUdl_2#email.com",
"firstname" : "FWAUdl_2"
}
2-------------------------------------------------------------------------------------
{
"_id" : ObjectId( "5191d8e7d00560402e000055" ),
"attributes" : [
{ "key" : "pobox", "value" : "sNFriy" },
{ "key" : "city", "value" : "JPdVrI" },
{ "key" : "address", "value" : "phOluW" } ],
"email" : "hqYNWH_86#email.com",
"firstname" : "hqYNWH_86"
}
My problem is how to get exact document when querying based only on the attributes field,
db.app.find({ attributes.key:address , attributes.value:/.*uw.*/i })
The query result is not as I expected, it should result only the 2nd document only without the 1st document.
I know that I put regex on the attributes.value, I was expecting that it only check for attributes.key that have address value.
And what if I want to filter another key, such like,
db.app.find({ attributes.key:address , attributes.value:/.*uw.*/i , attributes.key:city , attributes.value:/.*ri.*/i })
Any opinion will be helpful guys.
Thx.
I guess you need $elemMatch ( http://docs.mongodb.org/manual/reference/operator/elemMatch/ )
db.test123.find({ attributes : { $elemMatch : { 'key':"address" , 'value':/.*uw.*/i } } }).pretty()
{
"_id" : ObjectId("5191d8e7d00560402e000055"),
"attributes" : [
{
"key" : "pobox",
"value" : "sNFriy"
},
{
"key" : "city",
"value" : "JPdVrI"
},
{
"key" : "address",
"value" : "phOluW"
}
],
"email" : "hqYNWH_86#email.com",
"firstname" : "hqYNWH_86"
}
Just investigated a little and figured out following. The following uses the index mentioned below. You can do a explain() on the find() to check more index usage details
db.testing.getIndexKeys()
[ { "_id" : 1 }, { "attributes.key" : 1, "attributes.value" : 1 } ]
test:Mongo > db.testing.find({$and : [ { attributes : {$elemMatch : {key : 'address', value : /.*uw.*/i }} }, { attributes : {$elemMatch : {key : 'city', value : /.*ri.*/i }} }] }).pretty()
{
"_id" : ObjectId("5191d8e7d00560402e000055"),
"attributes" : [
{
"key" : "pobox",
"value" : "sNFriy"
},
{
"key" : "city",
"value" : "JPdVrI"
},
{
"key" : "address",
"value" : "phOluW"
}
],
"email" : "hqYNWH_86#email.com",
"firstname" : "hqYNWH_86"
}