Club childschema Under parent on mongoose - mongodb

I am using mongoose module
I have two Schema file
//First User File
var mongoose = require('mongoose');
const UserActivitySchema = require('./useractivity')
//User Schema
var UserSchema = new mongoose.Schema({
username: {
type: String
},
activity: [UserActivitySchema]
});
var User = module.exports = mongoose.model('User', UserSchema, 'User');
I already Tried to Create a subdocument but not able to acheive it
//Second Schema i.e supposed to be child is on useractivity.js file
var mongoose = require('mongoose');
//User Activity Schema....011217
var UserActivitySchema = mongoose.Schema({
message_count:{
type: Number,
default: 0
}
});
exports.UserActivitySchema = UserActivitySchema;
By this, It will create the Entry like this:
{
"_id" : ObjectId("5ab38941ffbb87124c673862"),
"username" : "peter",
"activity" : []
}
What I want is to like this:
{
"_id" : ObjectId("5ab38941ffbb87124c673862"),
"username" : "peter",
"activity" : {
"message_count" : 0
}
}
Any help is really Appreciated..

Mongoose populate can help you to get the required functionalities. You can learn more about populate here. You can do it in this way,
Create UserActivitySchema
var mongoose = require('mongoose');
var UserActivitySchema = mongoose.Schema({
message_count:{
type: Number,
default: 0
}
});
module.exports = mongoose.model('UserActivity', UserActivitySchema, 'UserActivity');
Now create UserSchema like this
var mongoose = require('mongoose');
const UserActivitySchema = require('./useractivity')
//User Schema
var UserSchema = new mongoose.Schema({
username: {
type: String
},
activity: {
type: mongoose.Schema.Types.ObjectId,
ref: 'UserActivity',
}
});
var User = module.exports = mongoose.model('User', UserSchema, 'User');
Now, while you are saving a user save the _id of the UserActivity in activity
When you are making your query to get user you can do like this
User.findOne({_id: 5ab38941ffbb87124c673862})
.populate('UserActivity')
.exec(function(err, user) {
// do stuff with returned user
});

Related

Mongoose Populate return null when the reference is put in sub-schema

I have 3 schemas
1. User
2. SignedToEvent
3. Events
The User contains information about user and has a relation to SignedToEvents. The SignedToEvents couples the user to an event.
The SignedToEvent is nested within User like this:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const SignedToEvents = new Schema({
event : { type: Schema.Types.ObjectId, ref: 'event' },
eventSignedDate: {type : Date, default : Date.now()},
isActive : Boolean
})
SignedToEvents.set('toObject', { getters: true });
SignedToEvents.set('toJSON', { getters: true });
const UserSchema = new Schema({
email: String,
password : String,
age : Number,
sex : String,
createdAt: { type: Date, default: Date.now },
signedToEvents : [SignedToEvents]
})
UserSchema.set('toObject', { getters: true });
UserSchema.set('toJSON', { getters: true });
module.exports = mongoose.model('user', UserSchema, 'users');
And the event schema looks like this
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const eventSchema = new Schema({
shortId : String,
name: String,
description : String,
organization : String
})
module.exports = mongoose.model('event', eventSchema, 'events');
In my API I have a call to the User collection:
User.findOne({_id : mongoose.Types.ObjectId(req.userId)})
.select("email")
.populate("event")
.exec()
.then(docs=>{
console.log(docs)
res.status(200).send(docs.signedToEvents)
});
Now, my hopes was to get an aggregated collection of User, SignedToEvent and Event. However thats not the case.
It only returns users id and email.
/Thanks
The solution was to point to my signedToEvent property and then use .event to reach the event model. Like this:
User.findOne({_id : mongoose.Types.ObjectId(req.userId)})
.select("email")
.populate("signedToEvents.event")
.exec()
.then(docs=>{
console.log(docs)
res.status(200).send(docs.signedToEvents)
});

Using Mongoose Populate Virtuals on Arrays

Here is my Follow model
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let FollowSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
followers: [{
type: Schema.Types.ObjectId,
ref: 'Card'
}],
following: [{
type: Schema.Types.ObjectId,
ref: 'Card'
}]
});
module.exports = mongoose.model('Follow', FollowSchema);
Here's my Card model
let mongoose = require('mongoose');
let Schema = mongoose.Schema;
let CardSchema = new Schema({
title: String,
content: String,
likes: Number,
createdById: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Card', CardSchema);
A typical Follow Model in DB will have something like this:
{
"_id" : ObjectId("59f0eef155ee5a5897e1a66d"),
"user" : ObjectId("59e3e617149f0a3f1281e849"),
"following" : [
ObjectId("59e21942ca5652efc4ca30ab"),
ObjectId("59e13b2dca5652efc4ca2cf5")
]
}
Here's what I'm trying to do:
To get all post from those you follow, find user in Follow model, and for each ObjectId in the following array, pull all documents from Card model, matching createdById field.
Using Mongoose Populate Virtuals, how do I do the schema relationship and populate query eventually?
Or, how would I go about creating and querying such a relationship with or without virtuals?

Mongoose query returning empty array in response

This is Morning Star schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var morningStarSchema = new Schema({
title : {type: String, lowercase : true, required :true},
visit : {type: String, lowercase : true, required :true},
Sightseeing : {type: String, lowercase : true, required :true},
image : {type: String},
price : {type: String},
})
module.exports = mongoose.model('morningStar',morningStarSchema)
API for Morning Star schema
created database in MongoDB with collections lets cruise and snow vacations with data in it , but when I do get request I get an empty array
var morningStar = require('../models/morningstar')
module.exports = function (router) {
router.post('/lets-cruise', function(req, res) {
var user = new morningStar();
user.title = req.body.title;
user.visit = req.body.visit;
user.Sightseeing = req.body.Sightseeing;
user.image = req.body.image;
user.price = req.body.price
user.save();
res.send('User created')
});
router.get('/snow-vacations', function(req, res){
morningStar.find(function(err, company) {
if (err)
{
res.send(err);
} else {
res.json(company);
}// return all nerds in JSON format
});
});
return router;
}

MongoDB/Mongoose- How to use nested objects/documents or subdocuments

I am creating simple RestApi using MongoDB, Mongoose, Node.js, Express.js and In which there will be multiple users and many more users can sign up and there will be an entry for each user in user collection(database). And my user Schema(users.js) will be like
var mongoSchema = mongoose.Schema;
var userSchema ={
mobileno: {
type:String
},
firstname: {
type:String
},
lastname: {
type:String
},
facebookid: {
type:String
},
userimage: {
type:String
}
}
module.exports = mongoose.model('user', userSchema);
Now each user can save one or more products as follows
Now which one would be the best solution:
Should I use separate collection (products collection with one field
like mobile no for reference)
Or Should I use subdocument or nested objects
My personal choice is second one but I am new in MongoDB and Mongoose environment. Please help me what I need to change in users schema.
You can do it like this :
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema{
mobileno: {
type:String
},
firstname: {
type:String
},
lastname: {
type:String
},
facebookid: {
type:String
},
userimage: {
type:String
}
}
var productSchema = new Schema{
_user:{type: Schema.ObjectId, ref: 'user'}
prod_name: {
type:String
},
prod_cost: {
type:String
}
}
module.exports = mongoose.model('user', userSchema);
module.exports = mongoose.model('products', productSchema);
You can reference user to product table (i,.e, just like joins in mysql)
And populate while fetching the profile :
Models.products.find(criteria, projection, options).populate([
{path: '_user', select: 'prod_name, prod_cost'},
]).exec(callback);
Thanks & Regards
The second choice is generally preferred. The schema for the product key would look like -
products: [productname: String, productdesc: String, ]
However, in some cases the first option to create a separate product collection makes more sense. This would happen if the collection depends on some external source and is fairly dynamic in nature. Here you would find it easier to update at one place rather than a lot of places. In this case, you can have a schema like
products: [productSchema]
Here for getting the product details, you would need to do $lookup operations
I think, the better way is other way around.
Save the product as a collection and user as another collection.
In product collection, save the reference of user.
Then use populate() to populate user in product, if you want.
After reading existing stack overflows answers I think following approach would be right. Please suggest or correct me if I am wrong.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var productSchema = new Schema{
prod_name: {
type:String
},
prod_cost: {
type:String
}
}
var userSchema = new Schema{
mobileno: {
type:String
},
firstname: {
type:String
},
lastname: {
type:String
},
facebookid: {
type:String
},
userimage: {
type:String
},
products: [productSchema]
}
module.exports = mongoose.model('user', userSchema);
module.exports = mongoose.model('products', productSchema);

Mongoose: how to set a schema-field to be the ID?

Given the following schema:
var UserSchema = new Schema({
, email : { type: String }
, passwordHash : { type: String }
, roles : { type: [String] }
});
I'd like email to be the key.
How can I define this?
I could do:
var UserSchema = new Schema({
, _id: { type: String }
, passwordHash : { type: String }
, roles : { type: [String] }
});
so MongoDB would recognize it as the id-field, and adapt my code to refer to _id instead of email but that doesn't feel clean to me.
Anyone?
Since you're using Mongoose, one option is to use the email string as the _id field and then add a virtual field named email that returns the _id to clean up the code that uses the email.
var userSchema = new Schema({
_id: {type: String},
passwordHash: {type: String},
roles: {type: [String]}
});
userSchema.virtual('email').get(function() {
return this._id;
});
var User = mongoose.model('User', userSchema);
User.findOne(function(err, doc) {
console.log(doc.email);
});
Note that a virtual field is not included by default when converting a Mongoose doc to a plain JS object or JSON string. To include it you have to set the virtuals: true option in the toObject() or toJSON() call:
var obj = doc.toObject({ virtuals: true });
var json = doc.toJSON({ virtuals: true });