Adding a Static, Complex Object to Mongoose/Passport Schema - node.js

I use Mongoose and Passport in my web application for the addition of new users into my MongoDB database. I use Google oauth for registering/signing in. In my user schema, I have the following defined for the google method:
//user.js
var userSchema = mongoose.Schema({
google : {
id : String,
token : String,
access_token : String,
email : String,
name : String,
picture : String,
nameInfo : Object,
}
});
I use the following method for user creation:
//passport.js
var newUser = new User();
//newUser.google.token = token;
newUser.google.name = profile.displayName;
newUser.google.nameInfo = profile._json.name
newUser.google.email = profile.emails[0].value;
newUser.google.id = profile.id;
newUser.google.picture = profile._json.image.url + '0';
newUser.google.access_token = token;
You can see that all this data goes under the "google" array in the top level of my user document. How would I add a new, complex, static array? For example, I want a new array at the top level of document in the following format:
newUser.dogs = ["cats":[]}]
I need this particular format based on a dependency in how users should look in my web code. I will eventually be adding data to the "cats" array, but it needs to start out empty. When I try varations of this, I'm only able to get the top level array - ex: my document looks like:
objectid: 1000,
google: [...],
dogs: []
when I need it to look like:
objectid: 1000,
google: [...],
dogs: [{"cats":[]}]
What do I need to change to my schema, either on the schema design, or the data going into the schema?

You want to set inner embedded docs.
Here it is sample, You can create it like this.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var Trigger = new Schema({
type : {type: String},
value: {type: Number}
});
var Field = new Schema({
label : {type: String},
type: {type: String},
triggers: [Trigger]
});
var Form = new Schema({
fields : [Field],
user_id : {type: String}
});

Related

How to create MongoSchema dynamically in Nodejs

I'm following this way.
var mySchema = new Schema({
Id : {type: String},
Name : {type: String}
}, {strict: false});
module.exports = mongoose.model('account', mySchema);
It's working fine, but everytime i restart the server my collection wipe off automatically..
i'm using this way to get collection
const collections = Object.keys(mongoose.connection.collections);
return res.status(200).json({status:true,msg:collections})
After restart the server collection shows empty, What is wrong i'm doing??

mongoose-schema - are both children array + parent doc's ID necessary?

I'm using a couple of one-to-many models and was wondering what the advantage of having both an array of "children" ObjectID()s and a "parent" model's ObjectID() in the child is. For example:
// a client will have a new card every ten visits
var ClientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [] // ObjectID()s, <--- is this necessary?
});
var CardSchema = new Schema({
client: ObjectID(), // <--- or is this enough?
visits: []
});
I think the client: ObjectID() should do the trick in most cases, specially with the Population options Mongoose offers.
It suffices to store the reference ObjectId in one of the documents.
As you can read in the documentation or in this answer, the reference field needs a type and a ref. The name of field is arbitrary. Once you have done this and registered your models, you can use the models to populate your queries.
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String
});
var cardSchema = new Schema({
client: {
type: Schema.Types.ObjectId,
ref: 'client'
}
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);
Yet, it could be helpful to store an array of ObjectId's. However, this also creates a huge window for mistakes. A mismatch of foreign key and primary key, in SQL dialect. You can always do a count query if you need to count. I would say, do either the above or do this:
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [
{
type: Schema.Types.ObjectId,
ref: 'card'
}
]
});
var cardSchema = new Schema({
card_name: String
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);

Nested objects are not update

Allora, I'm using mongoose for the first time and I decided to create 2 schemes: the first one represents a user and the second one represents his enquires. Users have an array of enquires like:
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [Enquire.schema] , "default" : [] },
});
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
I see that if I search for an enquire and update its status, it doesn't update the same enquire on the user's array, meaning that they are different object. I don't want to save an array of IDs as it will be the same as a relational database, so I see only 1 solution which is forgetting about the enquire scheme and use only the User scheme. Is it the way mongoose works? For every relationship do I have to insert everything like nested object?
I think you should use references to achieve what you want to achieve.
For more information on mongoose references and populate see Mongoose Populate documentation.
Try this, It may help you.
User Schema :
var userSchema = new mongoose.Schema({
name: String,
enquires: [{ type : mongoose.Schema.Types.ObjectId , ref : 'Enquiry' }]//array of enquiries
});
var User = mongoose.model('User',userSchema );
module.exports = User;
Enquiry Schema :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var Enquiry = mongoose.model('Enquiry',enquireSchema );
module.exports = Enquiry ;
Working :
create a new Enquiry.
Push it's ID(_id) into user's enquires array.
var enquiry = new Enquiry();
enquiry.enquire = "Dummy enquiry";//set the enquiry
enquiry.save(function(err,result){
if(!err){
//push 'result._id' into users enquires array
}
});
whenever you update an enquiry, it will be automatically updated in
user's document.
use populate to retrieve user's enquiries.
You can embed sub documents (entity) which has id and is like a document or embed native array like a normal property.
And I think the correct definition for yours is :
var enquireSchema = new mongoose.Schema({
status: {type: String, 'default': 'pending'},
enquire: String,
});
var userSchema = new mongoose.Schema({
name: String,
enquires: { type : [enquireSchema] , "default" : [] },
});
If you use refs in embedded link then there are two separate collections and be like relational db's.

Accessing mongoose schema array with body-parser

Here is an example schema:
var schema = mongoose.Schema;
var userSchema = new schema ({
username: {type: String},
hobby: [{
indoor: {
type: {type: String},
description: {type: String}
},
outdoor: {
type: {type: String},
description: {type: String}
}
}]
});
module.exports = mongoose.model('User', userSchema);
So, a very simple schema. It asks for a user name, and then it asks for a user to list their hobbies, and is split between indoor and outdoor hobbies, and inside of an array.
Using body-parser, I could get to a user name in a form input like this:
var user = new User();
user.username = req.body.username;
That's simple enough. But how do I get to the hobbies inside of the array? I've tried doing:
user.hobby.indoor.type = req.body.type
But this doesn't work; it just gives me an error. Any help would be appreciated.
The following code will help you access your key properly. As hobby is an array, you need to provide an index for fetching its objects. Dot notation works with objects
user.hobby[0].indoor.type
Js Fiddle: https://jsfiddle.net/x18nyd2e/
So I did end up finding the answer to my problem. Here is an example of what to do:
var user = new User();
user.username = req.body.username;
user.hobby = {{
indoor: {
type: req.body.type,
description: req.body.description
}
}];
And that's how you can get to a property inside of an array.

how to implement the function like left join of mysql in mongoose

I am going to implement the function like left join of mysql in mongoose.
the date is
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String
});
var storySchema = Schema({
_creator : { type: Number, ref: 'Person' },
title : String
});
var personProfile = Schema({
userid : {type: Number, ref: 'Person'},
birthday: Date,
profilelink: String,
email: String
});
var Story = mongoose.model('Story', storySchema);
var Person = mongoose.model('Person', personSchema);
var personProfile = mongoose.model('Personprofile', personProfile );
I am going to display the Story model with the user profile.
We have to get the profile info with the _creator of story and the userid of personProfile
How can I get the info using mongoose query?
Thanks Nelis
What your are trying to do is not possible because there is no join statement on mongodb.
You can achieve this in two ways:
1 - By DBRefs: Changing your Schema to one that include all the user info and do not split them in two different schemas as you are doing, see denormalized. Then you can use the Population function to get all the persons data.
2 - By Manual references: The second solution is to make a second call to the database getting the personProfile data using the userid as a filter.
Example 1:
This way you can get all persons data without a second call to the database.
var personSchema = Schema({
_id : Number,
name : String,
birthday: Date,
profilelink: String,
email: String
});
var storySchema = Schema({
_creator : { type : Schema.Types.ObjectId, ref: 'Person' },
title : String
});
Story
.find()
.populate(['_creator'])
.exec(function(err, stories) {
//do your stuff here
}
Notice that I'm using the type Schema.Types.ObjectId and not the Number. This way, you can assign a new value to _creator passing either the _id or the person object and the mongoose will convert the object to its _id. For example, you can post something like
{
_creator : {
_id : 123123123123,
name : 'Foo',
birthday: '0000-00-00',
profilelink: 'http://foo.bar',
email: 'foo#bar.com'
},
title : 'Mr'
}
... and the mongoose will convert to
{
_creator : 123123123123,
title : 'Mr'
}
Example 2:
This way your data still normalized and you can get all the persons data with a second call.
Story
.find()
.exec(function(err, stories) {
var arrayLength = stories.length;
for (var i = 0; i < arrayLength; i++) {
var story = stories[i];
personProfile.findById(story._creator, function (err, person) {
story._creator = person;
}
};
// do your stuff here
}

Resources