Return certain fields with .populate() from Mongoose
JavascriptJsonnode.jsMongodbMongooseJavascript Problem Overview
I'm getting returned a JSON value from MongoDB after I run my query. The problem is I do not want to return all the JSON associated with my return, I tried searching the docs and didn't find a proper way to do this. I was wondering what if it is at possible, and if so what is the proper way of doing such. Example: In the DB
{
user: "RMS",
OS: "GNU/HURD",
bearded: "yes",
philosophy: {
software: "FOSS",
cryptology: "Necessary"
},
email: {
responds: "Yes",
address: "[email protected]"
},
facebook: {}
}
{
user: "zuckerburg",
os: "OSX",
bearded: "no",
philosophy: {
software: "OSS",
cryptology: "Optional"
},
email: {},
facebook: {
responds: "Sometimes",
address: "https://www.facebook.com/zuck?fref=ts"
}
}
What would be the proper way of returning a field if it exists for a user, but if it doesn't return another field. For the example above I would want to return the [email][address]
field for RMS and the [facebook][address]
field for Zuckerburg. This is what I have tried to find if a field is null, but it doesn't appear to be working.
.populate('user' , `email.address`)
.exec(function (err, subscription){
var key;
var f;
for(key in subscription){
if(subscription[key].facebook != null ){
console.log("user has fb");
}
}
}
Javascript Solutions
Solution 1 - Javascript
I'm not completely clear on what you mean by "returning a field", but you can use a lean()
query so that you can freely modify the output, then populate both fields and post-process the result to only keep the field you want:
.lean().populate('user', 'email.address facebook.address')
.exec(function (err, subscription){
if (subscription.user.email.address) {
delete subscription.user.facebook;
} else {
delete subscription.user.email;
}
});
Solution 2 - Javascript
If you only want a few specific fields to be returned for the populated documents, you can accomplish this by passing the field name syntax as the second argument to the populate method.
Model
.findOne({ _id: 'bogus' })
.populate('the_field_to_populate', 'name') // only return the Persons name
...
Solution 3 - Javascript
Try to do this:
applicantListToExport: function (query, callback) {
this
.find(query).select({'advtId': 0})
.populate({
path: 'influId',
model: 'influencer',
select: { '_id': 1,'user':1},
populate: {
path: 'userid',
model: 'User'
}
})
.populate('campaignId',{'campaignTitle':1})
.exec(callback);
}
Solution 4 - Javascript
Try to do this:
User.find(options, '_id user email facebook').populate('facebook', '_id pos').exec(function (err, users) {
Solution 5 - Javascript
Now what you can do is :
.populate('friends', { username: 1, age: 1})
Solution 6 - Javascript
In the following query i retrieved articles which match the condition show=true
the retrieved data title and createdAt
also retrieve the category of article only the title of category and it's id.
let articles = await articleModel
.find({ show: true }, { title: 1, createdAt: 1 })
.populate("category", { title: 1, _id: 1 });
Solution 7 - Javascript
you to try :
Post.find({_id: {$nin: [info._id]}, tags: {$in: info.tags}}).sort({_id:-1})
.populate('uid','nm')
.populate('tags','nm')
.limit(20).exec();
Solution 8 - Javascript
for a single level populate you can use -> populate('user','name email age')
for nested population
populate({
path:'posts',
populate({
path:'user'
select:'name email age'
})
})
Solution 9 - Javascript
Just to complement the answers above, if you want to include everything but only exclude certain attributes, you can do the following:
.populate('users', {password: 0, preferences: 0})
Solution 10 - Javascript
I was stuck on this issue. I wanted to populator and user field linked to the Blog Post. Using populate only returned everything including the password. By specifying fields as an array it works fine.
//code emitted for brevity
await Blog.findById(ID).populate("author", ["firstName", "lastName",
"profilePicture", "_id"])
//
This is the result of the response
Solution 11 - Javascript
you can try using below,
Model
.find()
.populate({path: 'foreign_field', ['_id', 'name']}) // only return the Id and Persons name
...
Solution 12 - Javascript
Hi for me it worked for me i populated user field using the populate code : --->
async function displayMessage(req,res,next){
try{
let data= await Msg.find().populate("user","userName userProfileImg","User")
if(data===null) throw "Data couldn ot be loaded server error"
else {
res.status(200).json(data)
}
} catch(err){
next(err)
}
}
i am directly getting the result . Here the fields userName , userProfile image are the ones that ive required selectively and the syntax for populate is :-->
.populate("user field to populate","fields to display with spaces between each of them " , "modelName ")
every parameter should be in inverted comma's.
Below is the output i recieve.One more thing you don't have to worry about the populating sub-document id you will automatically get them.
[ { "_id": "5e8bff324beaaa04701f3bb9", "text": "testing message route", "user": { "_id": "5e8bf062d3c310054cf9f293", "userName": "boss", "userProfileImg": "img" }, "__v": 0 }, { "_id": "5e8bff8dd4368a2858e8f771", "text": "testing message route second", "user": { "_id": "5e8bf062d3c310054cf9f293", "userName": "boss", "userProfileImg": "img" }, "__v": 0 }, { "_id": "5e8c0c08e9bdb8209829176a", "text": "testing message route second", "user": { "_id": "5e8bf062d3c310054cf9f293", "userName": "boss", "userProfileImg": "img" }, "__v": 0 }, { "_id": "5e8c0e0bcb63b12ec875962a", "text": "testing message route fourth time", "user": { "_id": "5e8bf062d3c310054cf9f293", "userName": "boss", "userProfileImg": "img" }, "__v": 0 }]