i did find a post by id and i did console log output and it was that:
{ comments: [ 5c263bf01b764a11c479f69c, 5c263c41133ace1655edee76 ],
_id: 5c263bc61b764a11c479f69b,
title: 'good laptop',
category: 'Laptop',
brand: 'dell',
Condition: 'Good Condition',
image: 'https://avisassets.abgemea.com/.imaging/flexibleIntroLarge/dms/DMS/local/ZA/fleet/fleet-page/luxury-cars-feature.jpg',
price: 2000,
priceState: 'Negociable',
city: 'Algiers',
phone: '71717171555',
email: 'test#test.com',
description: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
date: '28/11/2018',
userId: 5c25344c321f0d5a777ace00,
__v: 2 }
i did read mongoose documentation about populate but i didn't figure out how to populate the userIdand also populate comments and the nested userId under the comments
Assuming userId is a field in your Posts schema, you can do it this way:
Posts.findOne({ id: 'your-post-id' })
.populate('userId')
.populate({ path: 'comments',
populate: { path: 'userId',
model:'User' }
})
.exec(callback);
Your schemas should be similar to this:
var postsSchema = new Schema({
comments: { type: [Schema.ObjectId], ref: 'Comment' },
userId: { type: Schema.ObjectId, ref: 'User' },
...
});
var commentsSchema = new Schema({
userId: { type: Schema.ObjectId, ref: 'User' },
...
});
Related
I'm trying to populate my user requests.profileId but it returns only nulls.
I have the following schemas:
First Schema:
const profileSchema = new mongoose.Schema({
_id: { type: Number }, //<- _id is defined as a number which represents mobile number (easier for me to handle)
first: { type: String },
second: { type: String },
});
module.exports = mongoose.model('Profile', profileSchema, 'profiles');
Second Schema:
const userSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
requests: [
{
profileId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Profile',
},
requestTime: { type: Date, default: Date.now },
},
],
});
module.exports = mongoose.model('User', userSchema, 'users');
Here is my code:
const user = await User.findById(req.user).populate('requests.profileId');
console.log(user.requests);
Here is the output:
[
{
_id: 6201633869648e2b74c00a10,
profileId: null,
requestTime: 2022-02-07T18:21:44.722Z
},
{
_id: 6201633b69648e2b74c00a11,
profileId: null,
requestTime: 2022-02-07T18:21:47.238Z
},
{
_id: 620238f9d2b5dd3dee6c41a2,
profileId: null,
requestTime: 2022-02-08T09:33:45.176Z
},
{
_id: 620239253220343dfd7cfdd9,
profileId: null,
requestTime: 2022-02-08T09:34:29.780Z
}
]
Here is the output without populate:
[
{
_id: 6201633869648e2b74c00a10,
profileId: 393732353235303134343330, //<- typeof profileId is obeject
requestTime: 2022-02-07T18:21:44.722Z
},
{
_id: 6201633b69648e2b74c00a11,
profileId: 393732353435353333313131,
requestTime: 2022-02-07T18:21:47.238Z
},
{
_id: 620238f9d2b5dd3dee6c41a2,
profileId: 393732353435353333313131,
requestTime: 2022-02-08T09:33:45.176Z
},
{
_id: 620239253220343dfd7cfdd9,
profileId: 393732353435353333313131,
requestTime: 2022-02-08T09:34:29.780Z
}
]
Currently Profile.findById(mobileNumber) works fine.
Any ideas what went wrong?
Will greatly appreciate your assistance.
Thanks in advance :)
Try this might work let me know if it doesn't
const user = await User.findById(req.user).populate('Profile');
console.log(user.requests);
try this:
User.findById(req.user).populate({
path: 'requests',
populate: {
path: 'profileId',
model: 'Profile'
}
})
For future readers having the same issue!
I've found a solution for this issue.
I had to change the profileId type to Number in my userSchema:
const userSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
requests: [
{
profileId: {
type: Number // and NOT use type: mongoose.Schema.Types.ObjectId,
ref: 'Profile',
},
requestTime: { type: Date, default: Date.now },
},
],
});
module.exports = mongoose.model('User', userSchema, 'users');
Now it works!
I have 2 collection in same db. I need to using find() to select only "Events" that have "team" equal "team1"
Thank you very much.
I have try to find by population field but it doesn't work.
This is my Event schema
const Event = mongoose.model('Event', new mongoose.Schema({
title: {
type: String,
required: true,
min: 3
},
eventType: {
type: String,
lowercase: true
},
date: {
type: Date,
default: Date.now()
},
venue: String,
country: String,
callLog: {
type: String,
max: 1000
},
eventImgUrl: [String],
editedBy : {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
timestamp: {
type: String,
default: Date.now()
}
}));
This is my User schema
const User = mongoose.model('User', new mongoose.Schema({
username: {
type: String,
required: true,
min: 3,
lowercase: true
},
name: String,
email: String,
team: String,
role: {
type: String,
enum: ['admin', 'creator', 'viewer']
}
}));
This is my Controller
const events = await Event.find()
.populate({ path: 'editedBy', select: ['name', 'team']});
res.send(events);
To find all Events that have a team of "team1":
const team1Events = await Event.find({ team: "team1" });
select just specifies the fields returned. You need to use populate match:
await Event.find()
.populate({ path: 'editedBy', match: { yourField: 'yourmatch' }});
I have a User model and a Book model. I want some data from my books to be denormalized on each User document, but still have the option to populate if needed. If I set ref: 'Book' on the books.$._id it gets populated inside the _id path which is unintended. I would like the population to overwrite the denormalized data.
How do I accomplish this?
in users.model.js:
const { Schema } = require('mongoose');
const UserSchema = new Schema({
name: String,
books: {
type: [
{
_id: Schema.Types.ObjectId,
title: String,
length: Number,
},
],
default: [],
},
});
Desired outcome
in users.controller.js:
app.get('/', async (req, res, next) => {
const users = await User.find({})
/*
users: [{
_id: ObjectId(),
name: 'Andrew',
books: [{
_id: ObjectId(),
title: 'Game of Thrones',
length: 298,
}, { ... }],
}, { ... }]
*/
});
app.get('/:id', async (req, res, next) => {
const book_id = req.params.id;
const user = await User.findById(book_id).populate({
path: 'books',
model: 'Book',
});
/*
user: {
_id: ObjectId(),
name: 'Andrew',
books: [{
_id: ObjectId(),
name: 'Game of Thrones',
length: 298,
author: 'Simone Dunow',
releasedOn: Date(),
price: 30,
...
}, { ... }],
}
*/
});
Schemas I've tried so far:
books: {
type: [
{
_id: Schema.Types.ObjectId,
title: String,
length: Number,
},
],
default: [],
ref: 'Book',
},
returns array of { _id: null }
books: {
type: [
{
_id: {
type: Schema.Types.ObjectId,
ref: 'Book',
},
title: String,
length: Number,
},
],
default: [],
},
books are populated inside of _id: { _id: { Book } }
books: {
type: [
{
type: {
_id: Schema.Types.ObjectId,
title: String,
length: Number,
},
ref: 'Book',
},
],
default: [],
},
throws exception: invalid type
const UserSchema = new Schema({
name: String,
books: [{
id: { type : Schema.Types.ObjectId, ref : 'Book'} //Whatever string you have used while modeling your schema
title: String,
length: Number,
}],
});
While using the schema you can populate as follows :
populate({ path: 'books.id' })
Output :
{
_id : // someid
name : "somename"
books : [
{
id : {//document referring to Books collection},
title : "sometitle",
length : //somelength
}, ...
]
}
To anybody that might be still looking to achieve a full replacement, full disclosure: It might be a bit hacky for some evangelists or even have a performance toll on high traffic apps, but if you really want to do it, you can tap into the toJSON method of the schema like the following:
UserSchema.method('toJSON', function () {
let obj = this.toObject();
obj.books = obj.books.map(
(book) => (Schema.Types.ObjectId.isValid(book.id)) ? book : book.id
);
return obj;
});
What's going on here is basically we're replacing the whole property with the populated result when the book.id has been populated otherwise we just return the original object by checking the validity of the book's id (when populated will be a full bloomed object rather than an id).
I am using MongoDB + Node.js to create an app, but I am receiving an error for this code:
company.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var companySchema = Schema({
creator: {
type: Schema.Types.ObjectId,
ref: 'User'
},
name: String,
description: String,
categories: [String],
website: String,
address: String,
statuses: [{
date: { type: Date, default: Date.now },
status: String
}],
friends: [{
name: String,
description: String
}],
priority: Number,
isActive: Boolean,
contacts: [{
type: Schema.Types.ObjectId,
ref: 'ContactPerson'
}],
createdOn: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Company', companySchema);
api.js
api.route('/company')
.post(function(req, res) {
var company = new Company({
creator: req.decoded.id,
name: req.body.name,
description: req.body.description,
categories: req.body.categories,
website: req.body.website,
address: req.body.address,
friends.name: req.body.friendName,
statuses: { status: "New Company" },
priority: req.body.priority,
});
company.save(function(err, newCompany) {
if(err) {
res.send(err);
return
}
res.json({ message: "New company has been created!" });
});
})
Error
friends.name: req.body.friendName,
SyntaxError: Unexpected token .
I also tried with friend['name'] but the result was the same: SyntaxError: Unexpected token [
Please tell me where is my mistake
Try:
var company = new Company({
creator: req.decoded.id,
name: req.body.name,
description: req.body.description,
categories: req.body.categories,
website: req.body.website,
address: req.body.address,
friends: {
name: req.body.friendName
},
statuses: { status: "New Company" },
priority: req.body.priority,
});
or:
var company = new Company({
creator: req.decoded.id,
name: req.body.name,
description: req.body.description,
categories: req.body.categories,
website: req.body.website,
address: req.body.address,
'friends.name': req.body.friendName,
statuses: { status: "New Company" },
priority: req.body.priority,
});
depend on what you're after.
Use latest version of nvm and then run it
Write nvm use version 16.
And then write: npx nodemon index.
I am trying to populate() all the subscriptions in my User model with data from the Show model. I have tried .populate('subscriptions.show') but it does nothing to the results.
If I make subscriptions a plain array of Refs like so
subscriptions: [{type: Schema.Types.ObjectId, ref: 'Show'}]
doing a populate('subscriptions') works as intended
I have looked at every similar question I could find on Stackoverflow and what I could find on the docs. I can't see what I am doing wrong.
complete test file source that i am working with https://gist.github.com/anonymous/b7b6d6752aabdd1f9b59
Schema and Models
var userSchema = new Schema({
email: String,
displayName: String,
subscriptions: [{
show: {type: Schema.Types.ObjectId, ref: 'Show'},
favorite: {type: Boolean, default: false}
}]
});
var showSchema = new Schema({
title: String,
overview: String,
subscribers: [{type: Schema.Types.ObjectId, ref: 'User'}],
episodes: [{
title: String,
firstAired: Date
}]
});
var User = mongoose.model('User', userSchema);
var Show = mongoose.model('Show', showSchema);
Initial Data
var user = new User({
email: "test#test.com",
displayName: "bill"
});
user.save(function(err, user) {
var show = new Show({
title: "Some Show",
overview: "A show about some stuff."
});
show.save();
user.subscriptions.push(show);
user.save();
});
The Query
User.findOne({
displayName: 'bill'
})
.populate('subscriptions.show')
.exec(function(err, user) {
if (err) {
console.log(err);
}
console.log(user);
});
results in:
{
_id: 53a7a39d878a965c4de0b7f2,
email: 'test#test.com',
displayName: 'bill',
__v: 1,
subscriptions: [{
_id: 53a7a39d878a965c4de0b7f3,
favorite: false
}]
}
Some code perhaps, also some corrections to your approach. You kind of want a "manyToMany" type of join which you can make as follows:
var async = require("async"),
mongoose = require("mongoose"),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/user');
var userSchema = new Schema({
email: String,
displayName: String,
subscriptions: [{ type: Schema.Types.ObjectId, ref: 'UserShow' }]
});
userShows = new Schema({
show: { type: Schema.Types.ObjectId, Ref: 'Show' },
favorite: { type: Boolean, default: false }
});
var showSchema = new Schema({
title: String,
overview: String,
subscribers: [{ type: Schema.Types.ObjectId, ref: 'User' }],
episodes: [{
title: String,
firstAired: Date
}]
});
var User = mongoose.model('User', userSchema);
var Show = mongoose.model('Show', showSchema);
var UserShow = mongoose.model('UserShow', userShows);
var user = new User({
email: 'test#test.com',
displayName: 'bill'
});
user.save(function(err,user) {
var show = new Show({
title: "Some Show",
overview: "A show about some stuff."
});
show.subscribers.push( user._id );
show.save(function(err,show) {
var userShow = new UserShow({ show: show._id });
user.subscriptions.push( userShow._id );
userShow.save(function(err,userShow) {
user.save(function(err,user) {
console.log( "done" );
User.findOne({ displayName: "bill" })
.populate("subscriptions").exec(function(err,user) {
async.forEach(user.subscriptions,function(subscription,callback) {
Show.populate(
subscription,
{ path: "show" },
function(err,output) {
if (err) throw err;
callback();
});
},function(err) {
console.log( JSON.stringify( user, undefined, 4) );
});
});
});
});
});
});
That should show a populated response much like this:
{
"_id": "53a7b8e60462281231f2aa18",
"email": "test#test.com",
"displayName": "bill",
"__v": 1,
"subscriptions": [
{
"_id": "53a7b8e60462281231f2aa1a",
"show": {
"_id": "53a7b8e60462281231f2aa19",
"title": "Some Show",
"overview": "A show about some stuff.",
"__v": 0,
"episodes": [],
"subscribers": [
"53a7b8e60462281231f2aa18"
]
},
"__v": 0,
"favorite": false
}
]
}
Or without the "manyToMany" works also. Note here that there is no initial call to populate:
var async = require("async"),
mongoose = require("mongoose"),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/user');
var userSchema = new Schema({
email: String,
displayName: String,
subscriptions: [{
show: {type: Schema.Types.ObjectId, ref: 'UserShow' },
favorite: { type: Boolean, default: false }
}]
});
var showSchema = new Schema({
title: String,
overview: String,
subscribers: [{ type: Schema.Types.ObjectId, ref: 'User' }],
episodes: [{
title: String,
firstAired: Date
}]
});
var User = mongoose.model('User', userSchema);
var Show = mongoose.model('Show', showSchema);
var user = new User({
email: 'test#test.com',
displayName: 'bill'
});
user.save(function(err,user) {
var show = new Show({
title: "Some Show",
overview: "A show about some stuff."
});
show.subscribers.push( user._id );
show.save(function(err,show) {
user.subscriptions.push({ show: show._id });
user.save(function(err,user) {
console.log( "done" );
User.findOne({ displayName: "bill" }).exec(function(err,user) {
async.forEach(user.subscriptions,function(subscription,callback) {
Show.populate(
subscription,
{ path: "show" },
function(err,output) {
if (err) throw err;
callback();
});
},function(err) {
console.log( JSON.stringify( user, undefined, 4) );
});
});
});
});
});
check answer: https://stackoverflow.com/a/28180427/3327857
Car .find() .populate({
path: 'partIds',
model: 'Part',
populate: {
path: 'otherIds',
model: 'Other'
}
})