Nested objects are not update - node.js

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.

Related

Nested Documents in Mongoose

I have two Mongoose schemas, User and Code. Each user can have many codes.
user.js:
var mongoose = require('mongoose');
var codeSchema = require('./code');
var userSchema = mongoose.Schema({
google: {
id: String,
token: String,
email: String,
name: String
},
codes: [codeSchema]
}, {collection : 'users'});
code.js:
var mongoose = require('mongoose');
var codeSchema = mongoose.Schema({
code: String,
name: String,
link: String
}, {collection: 'codes'});
module.exports = codeSchema;
My problem is, whenever I access a user's array of codes by user.codes, I get something like { _id: 56c4c82a37273dc2b756a0ce },{ _id: 56c4c82a37273dc2b756a0cd } rather than the JSON for a code.
What am I missing?
You're missing populate.
By default, Mongoose will only give you the _ids of any references made in a document. populate allows you to fill out nested documents.
userSchema.findOne({}).populate('codes');
More here
please check that you are inserting other values or not this can be a case . Please write how you are inserting in array . I have two other way check out
There are two way to do this
1-->either you save refrence id of codeschema and
2--> is you can insert whole codeschema in array
1. codes: {
type: mongooseSchema.ObjectId,
ref: 'codeSchema',
required: true
},
and when all data is in array 56c4c82a37273dc2b756a0ce,56c4c82a37273dc2b756a0cd
that can be done by this query
domain.User.update({_id:id}
,{$addToSet:{code:codeObjvalue}},
function(err,res){});
and then populate them by this
domain.users.find({},'code')
.populate('code','code color email').
exec(function(err,results){
callback(err, results);
});
2-- and second is to insert whole code schema in userschema
create a codeschema object and add in set like this
var codeobj={};
codeobj.code="xyz";
codeobj.email="xyz#gmail.com"
var codeobject = new domain.code(codeobj);
domain.User.update({_id:id},{$addToSet:{code:codeobject}},function(err,user1){
});
Woops, turns out I was using the wrong dataset, not adding the codes properly (facepalm). Thanks to everyone who answered!

Adding a Static, Complex Object to Mongoose/Passport Schema

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}
});

save mongoose model and submodel after populate

I'm trying to find a way to simplify my backend logic and optimize my DB, for this it would be great if I could save a document and it's subdocuments all at once so that creating subdocuments becomes easier.
Here is a simple example:
the primary model:
var ItemSchema = new Schema({
name: {type : String},
extrainfo: {type: Schema.Types.ObjectId, ref: 'Extrainfo'},
})
mongoose.model('Item', ItemSchema);
the subdocument:
var ExtrainfoSchema = new Schema({
this: {type : String},
that: {type: String},
})
mongoose.model('Extrainfo', ExtrainfoSchema);
how I hoped to be able to save:
Item.findOne({ name: 'whatever' }).populate('extrainfo').exec(function (err, item) {
item.extrainfo.this = "something diferen" //some random change in subdocument
item.save(function(){console.log("yay")}
});
Is there a way to do this whithout having to save to the document and the subdocument individually ?
Is there a way to do this whithout having to save to the document and the subdocument individually ?
No. mongodb will write to one and only one collection during a given write operation, and mongoose doesn't have any feature as far as I know to provide a single-callback facility to write to multiple collections.

relations in mongoose with custom field

I've seen many examples about mongoose and relations, but how can I create a reference to another entity into a custom field ?
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
mongoose.connection.once('open', function(){
var Author = m.model('Author', new m.Schema({
name: String,
slugname: String
}));
var Book = m.model('Book', new m.Schema({
title: String,
author: {type: String, ref: 'Author.slugname'}
}));
});
In the code above, I'm linking Book.author into Author.slugname. it is just that I don't if this is the right way to do it.
No, you can't. Mongoose always use _id field to link documents. But...
You can set your own _id for each document, using any datatype you want. There are only two restrictions:
it should be unique
it should not be changed during document's lifetime
So, instead of adding new slugname field, use author's _id as a slugname:
var Author = m.model('Author', new m.Schema({
_id: String, // <-- slugname
name: String
}));
var Book = m.model('Book', new m.Schema({
title: String,
author: { type: String, ref: 'Author' }
}));
This is supported since Mongoose 4.5, and is called virtuals population.
Check my detailed answer on this (nearly duplicate) question.
Mongoose is set up more for direct object relations. Rather than linking your Book object to a slug for the Author object, it would suit better to link to the Author's _id property automatically created by Mongoose.
var Author = mongoose.model('Author', new mongoose.Schema({
name: String
});
var Book = mongoose.model('Book', new mongoose.Schema({
title: String
author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' }
});
You can then save an Author as the author of the Book object by either saving book.author = author or book.author = author._id. Mongoose will automatically serialize the data when saving.
var author = new Author();
author.name = 'Hank Brekke';
var book = new Book();
book.title = 'My Book';
book.author = author;
book.save();
When pulling the book object, you can have Mongoose automatically populate the author property, which by default it will not, by adding the .populate('author') modifier before calling .exec()
Book.findOne({ /* query */}).populate('author').exec(function(error, book) {
var author = book.author;
});
References:
http://mongoosejs.com/docs/populate.html

How to declare schematype/datatype of a field in mongoose which is the objetid of an item in another collection?

I am a bit confused by something in MongoDB, when using Mongoose, since I am new to it. I have two collections: authors and posts.
each author in the authors collection have the mongodb inbuilt id associated with them, which as per my understanding is of the schematype/datatype Objectid.
Now in my posts collection, I have a field which has is called author, which should have the value of the author's Objectid, similar to the foreign key concept in SQL.
My question is, which schematype/datatype should I declare the author field in the posts collection? Should I put it as Objectid? If so, would it not auto-increment and not be settable?
Mockup Of Schemas:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: **??**
});
Any help would be hugely appreciated!
You can use population for that:
var authors = new mongoose.Schema({
name: String,
email: String
});
var posts = new mongoose.Schema({
title: String,
author: { type: Schema.Types.ObjectId, ref: 'Author' }
// assuming the model will be called 'Author'
});
To use:
// Get 'author' some how (create a new one, query the
// database for existing authors, etc);
...
// Create a new post and associate it with 'author' by referencing its `_id`:
var post = new Post({
...
author : author._id
});
post.save(...);
The documentation linked above also shows how you can get Mongoose to automatically retrieve the author document when you're querying posts.

Resources