I have two models like this:
var UserSchema = mongoose.Schema({
name : {type: String, required: true},
image : {type: String, required: true}
});
var RoomSchema = mongoose.Schema({
_user : {type: mongoose.Schema.ObjectId, ref: 'User', required: true},
name : {type: String, required: true}
});
I know how to use populate like this:
Room.findOne({_id : req.body._id}).populate('_user').exec(function(err, room){
console.log(room);
});
And works fine, my problem is that I need to write something like (witch is wrong):
Room.findOne({_id : req.body._id}, function(err, room){
room.populate('_user');
console.log(room);
});
Because I have no access to the function that find the rooms and I have a long list of different Objects Ids that I need to populate. Any ideas how to solve this problem?
You can use Model.populate to do this:
Room.findOne({_id : req.body._id}, function(err, room){
Room.populate(room, {path: '_user'}, function(err, room) {
console.log(room);
});
});
Related
Here are two collections' schema
var activitySchema = new Schema({
activity_id: {type: String, index: {unique: true}, required: true},
begin_date : String,
...
})
var registrationSchema = new Schema({
activity_id: {type: String, index: {unique: true}, required: true},
registration_id: {type:String, trim: true, index: true ,required: true },
email : String,
...
})
I want activity.begin_date , registration.id , registration.email in the same query. How can I do? I've found some solutions on the internet, but still don't know whether using populate or aggregation $lookup (this one seems new).
Here's how I tried, but not working at all.
models.Registration.aggregate([
{
$lookup: {
from: "Activity",
localField: "activity_id",
foreignField: "activity_id",
as: "activity_docs"
}
},
{"$unwind" : "activity_docs"},
], function( err , result ){
if(result){
fullDoc = result;
}else{
next( err );
}
})
activity_id should be ObjectId data type. ObjectId documentation
If you want to use pupoluate, you must to use ref to the other schema.
Population documentation
var activitySchema = new Schema({
begin_date : String,
...
})
var Activity= mongoose.model('Activity', activitySchema );
var registrationSchema = new Schema({
activity_id: {type: Schema.Types.ObjectId, ref : 'Activity', required: true},
email : String,
...
})
var Registration = mongoose.model('Registration', registrationSchema);
So the query such as :
var query = Registration.find({_id: 'registration_id parameter'});
query.select('_id activity_id email');
query.populate('activity_id','_id begin_date');
query.exec(function(error,result){
if(error){
/// handle error
}else{
// handle result
}
});
I have problem which has seriously been bothering for the past few days. I have mongoose setup for a nodejs project I have defined all the schemas and models as shown below
var studentSchema = new Schema({
fullname: {type: String, required: true},
student_id: {type: String, required: true, unique: true},
votingNo: {type: Number, required: true, unique: true},
voted: {type: Boolean, required: true, default: false}
});
var Student = mongoose.model('Student', studentSchema, 'student');
I have exported the model and i'm using it in another module.
whenever I try query for results like so:
model.Student.find({}, function (err, students) {
console.log(err);
console.log(students);
});
I get results. But the moment I add a filter, like so:
model.Student.find({student_id: studentId}, function (err, students) {
console.log(err);
console.log(students);
});
The result is always an empty array.
I've tried using findOne() but it's always returning null.
Try to call the queries like this
var Student = mongoose.model('Student');
Student.find({}, function (err, students) {
console.log(err);
console.log(students);
});
If it doesn't work, add this before your call to be sure that the database is open.
var mongoose = require('mongoose');
console.log(mongoose.connection.readyState); // Should not return 0
Hope it helps!
I wanted to make a base 'Entity Schema', and other model entities would inherit from it.
I did it, kinda, but then strange thing happened.
Those are my schemas:
AbstractEntitySchema
MessageSchema
UserSchema
RoomSchema
File: https://github.com/mihaelamj/nodechat/blob/master/models/db/mongo/schemas.js
But in MongoDB, they are all saved in the same document store: 'entity models' not separate ones, like Messages, Users..
Did I get what was supposed to happen, but not what I wanted, separate stores?
If so I will just make a basic JSON/object as entity and append the appropriate properties for each entity. Or is there a better way?
Thanks.
Discriminators are a schema inheritance mechanism. They enable you to have multiple models with overlapping schemas on top of the same underlying MongoDB collection. rather than different documents. It seems that you misunderstand the discriminators of mongoose. Here is one article could help you to catch it correctly.
Guide to mongoose discriminators
Here are some codes sample to meet your requirement, to save the derived schema as separated documents
function AbstractEntitySchema() {
//call super
Schema.apply(this, arguments);
//add
this.add({
entityName: {type: String, required: false},
timestamp: {type: Date, default: Date.now},
index: {type: Number, required: false},
objectID: {type: String},
id: {type: String}
});
};
util.inherits(AbstractEntitySchema, Schema);
//Message Schema
var MessageSchema = new AbstractEntitySchema();
MessageSchema.add({
text: {type: String, required: true},
author: {type: String, required: true},
type: {type: String, required: false}
});
//Room Schema
var RoomSchema = new AbstractEntitySchema();
RoomSchema.add({
name: {type: String, required: true},
author: {type: String, required: false},
messages : [MessageSchema],
});
var Message = mongoose.model('Message', MessageSchema);
var Room = mongoose.model('Room', RoomSchema);
// save data to Message and Room
var aMessage = new Message({
entityName: 'message',
text: 'Hello',
author: 'mmj',
type: 'article'
});
var aRoom = new Room({
entityName: 'room',
name: 'Room1',
author: 'mmj',
type: 'article'
});
aRoom.save(function(err, myRoom) {
if (err)
console.log(err);
else
console.log("room is saved");
});
aMessage.save(function(err) {
if (err)
console.log(err);
else
console.log('user is saved');
});
If you want multiple overlapping models with different MongoDB collections, then you use this approach:
function extendSchema (Schema, definition, options) {
return new mongoose.Schema(
Object.assign({}, Schema.obj, definition),
options
);
}
Example
const extendSchema = require('mongoose-extend-schema');
const UserSchema = new mongoose.Schema({
firstname: {type: String},
lastname: {type: String}
});
const ClientSchema = extendSchema(UserSchema, {
phone: {type: String, required: true}
});
You simply extend the original object the schema was created with and recreate a new schema on its basis. This is some sort of abstract schema which you inherit from.
Check this npm module: https://www.npmjs.com/package/mongoose-extend-schema
Since ES6 this works as well:
var ImageSchema: Schema = new Schema({
...CommonMetadataSchema.obj,
src: String,
description: String,
});
'use strict';
var mongoose = require('mongoose'),
ItemSchema = null;
module.exports = mongoose.model('Item', {
name: {type: String, required: true},
comments: [{type: mongoose.Schema.ObjectId, ref: 'Comment'}],
rating : {type: Number}
});
'use strict';
var mongoose = require('mongoose');
module.exports = mongoose.model('Comment', {
ItemId: {type: mongoose.Schema.ObjectId, ref: 'Item'},
userId: {type: mongoose.Schema.ObjectId, ref: 'User'},
text: {type: String, required: true},
createdAt: {type: Date, required: true, default: Date.now},
rating : {type: Number, required: true},
votes: {type: Number, default: 0}
});
var Item = mongoose.model('Item', ItemSchema);
module.exports = Item;
schemas are above.. the match is not working how I think it should. Really having a hard time emulating these joins.. I'm just trying to return one item with it's comments and the average rating given for it within the comments..
Item.findOne({_id : request.params.itemId} , 'comments',function(err, item){
Comment.aggregate([
{$match: {_id: {$in: item.comments}}},
{$group: {_id: '$itemId', avgRating: {$avg: '$rating'}}}], function(err, result){
reply(result);
});
});
}
If I take out the match, it returns all items with avgRating... I'm implementing something wrong in the $match.
here's what I've tried with removing the findOne:
Comment.aggregate([
{$match: {itemId : request.params.itemId}},
{$group: {_id: '$itemId', avgRating: {$avg: '$rating'}}}], function(err, result){
reply(result);
console.log('BBBBBB', result);
});
Not sure if this is what you meant by removing the findOne, but this is also not working.. request.params is returning the correct ID. it's definitely a valid field in comments, there is a comment seeded in the DB with this matching ID...
i'm having a problem with updating a member in schema that contained in other schema.
var User = new mongoose.Schema({
first_name : { type: String, required: true , lowercase: true},
last_name : { type: String, required: true , lowercase: true},
log : { type: [Log], default: [Log] },
});
var Log = new mongoose.Schema({
left_groups : [{ type: mongoose.Schema.Types.ObjectId, ref: 'Group' }],
});
i'm trying to update the left_groups member (from the user) which is a reference to group schema and i can't do that.
after a research on the net, the best i came up with is:
User.update({_id: "549a972f243a461c093f8ebb"}, {log:{$push:{left_groups: gr}}}, function () {
console.log("updated")
});
and this seems not working for me.
//gr[0] means for group.
i succeed to figure it out..
i'm not sure it's a proper solution though:
Group.findOne({_id: "549b18c73117388028c3990f"}, function (err, gr) {
User.findOne({_id: '549b18c73117388028c39904'}, function(err, user){
user.log[0].left_groups.push(gr);
user.save();
});
})