Nested models mongoose with nodejs generates duplicates - node.js

here is my code for models.js where I keep models
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var GroupSchema = new Schema({
title : String
, elements : [ElementSchema]
, author : String
});
var ElementSchema = new Schema({
date_added : Date
, text : String
, author : String
});
mongoose.model('Group', GroupSchema);
exports.Group = function(db) {return db.model('Group');};
mongoose.model('Element', ElementSchema);
exports.Element = function(db) { return db.model('Element');
};
To me it looks pretty clear, but when I do
function post_element(req, res, next) {
Group.findOne({_id: req.body.group}, function(err, group) {
new_element = new Element({author: req.body.author,
date_added: new Date()});
new_element.save();
group.elements.push(new_element);
group.save();
res.send(new_element);
return next();
})
}
I don't understand why when I go in Mongo I have two collections one called Groups with nested groups (so it looks fine) and the other collection is called Elements.
Why? Shouldn't it be called just Group ?
I don't understand, a good chap that please explain it to me?
Thanks,
g

When you execute this line:
new_element.save();
you're saving the newly created element to the Elements collection. Don't call save on the element and I think you'll get the behavior you're looking for.

Its because of the following line:
mongoose.model('Element', ElementSchema);
This registers a model in mongoose and when you register a model, it will create its own collection inside mongo. All you have to do is get rid of this line and you will see it disappear.
On another note, its much cleaner and easier to setup your files to only export one model per file using the following to export the model:
module.exports = mongoose.model('Group', GroupSchema);
Hope this helps!

Related

Insert multiple document with mongoose

I made an API with express.js, and i use mongoDB for my database and mongoose as my ODM
I really confused when i want to insert multiple document to my collection in once post request.
Here my model :
const modul = require('../config/require');
const Schema = modul.mongoose.Schema;
let TeleponSchema = new Schema({
_pelanggan : {type: String},
telepon: {type: String, required: true}
});
module.exports = modul.mongoose.model('telepon', TeleponSchema, 'telepon');
and here my controller
const Telepon = require('../models/telepon.model')
exports.create = (req,res) => {
let telepon = new Telepon({
_pelanggan : req.body.pel,
telepon: req.body.telepon
});
telepon.save((err,data) => {
if(err){
res.send({message:'eror', detail: err});
}else{
res.send({message:'success', data: data})
}
});
}
Then i post my request with postman like this :
but the result in my document is :
that's the problem, the value of 'telepon' is in the same row and separated by comma instead of insert a new row and create a new _id
i want the result of my collection like this :
(example)
Any help and suggestion would be much appreciated
Thank you!
1) Per .save call you will only affect one document, check out insertMany to do multiple.
2) req.body.telepon is either an array of numbers, or is already just the comma delimited list of numbers; if it is an array the .toString will result in a comma delimited list anyways. So when you new up the Telepon it has both values in one property, which is what you see in the result.

Check stored value using mongoose

I’m looking for the fastest way to get all objectIDs of a collection with a privacy value 'public'.
In this image, privacy's value is 'public', so node should give me the '_id' of this object (in this example '57bc4b9f466fab7c099a3f94').
My attempt:
var mongoose = require('mongoose');
mongoose.connect('localhost:27017/databasename');
var Schema = mongoose.Schema;
var collectionsNameSchema = new Schema({
updated: {type: Date },
privacy: { type: Object }
}, {collection: 'spots'});
var collectionsNameData = mongoose.model('collectionsNameData', collectionsNameSchema);
...
collectionsNameData.find({privacy: 'public'})
From what i see you have a problem in query to mongoDB.
Try like this.
collectionsNameData.find({'privacy.value': 'public'});
This should return desired result.
You also may want to use projection as second parameter in find to return only fields that you want. Keep in mind that _id returned by default.
Hope this helps.

Render every subdocuments of all documents with mongoose

I have a user model and a pet model, using Mongoose.
user model :
var userSchema = mongoose.Schema({
email : String,
password : String,
pets : [Pet.schema]
});
module.exports = mongoose.model('User', userSchema);
pet model :
var petSchema = mongoose.Schema({
name : String
});
module.exports = mongoose.model('Pet', petSchema);
I'd like to render all the pets of all users in a page. I tried to do :
app.get('/pets', function(req, res) {
Pet.find({}, function(err, pets){
res.render('pets.ejs', {"pets":pets});
});
});
But I only get an empty array [ ].
How could I get every Pets ?
More generally, I will have to use Pet model independently from the User. Should I change the way my models are constructed ?
Thanks for your help !
It looks like you're trying to embed the Pet sub document and use as if it weren't embedded.
First, if you're doing embedded, you need to define the schema for Pet before you use it (create it first). If you're embedding, you can't do a find on the Model for pets that way.
Mongoose Subdocuments
If, instead, you want to store a reference to a Pet inside a User, you need to store its ObjectId.
pets : [{ type: Schema.Types.ObjectId, ref: "Pet"}]
You would then likely use populate to fill the pets property at run time.

Getting all documents from MongoDB instead of all Models

I'm calling MongoDB from my Node app using Mongoose like this:
var query = itemModel.find();
query.exec(function (err, items) {
console.log(err);
socket.emit("items", items);
});
I have 3 models defined like this:
var Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var playerModel = require('./models/player.js').make(Schema, mongoose);
var characterModel = require('./models/character.js').make(Schema, mongoose, ObjectId);
var itemModel = require('./models/item.js').make(Schema, mongoose);
my models look like this:
function make(Schema, mongoose) {
itemSchema = new Schema({
name: String
, bonus: [{
type: String
, value: Number
}]
, price: Number
, slot: String
});
return mongoose.model('Character', characterSchema);
}
exports.make = make;
For some reason I'm getting all documents, regardless of them being items, characters or players. Since I'm calling find() on itemModel I was expecting only Items, what am I doing wrong?
The model that you have shown appears to be the item model, but you are creating the model with the 'Character' name. This means that you told Mongoose about the scheme for an item and that it is stored in the 'character' collection. Assuming you've done the same for each other model (Character/Player), you've been Mongoose that everything is in the same collection.
Then you query that collection and you seem surprised that everything is stored in the same collection. It strikes me as if you have little experience with Mongoose/MongoDB, so I will suggest you download and learn to love MongoVUE. This application is a good GUI to see what is going on under the hood of the MongoDB database. While developing, you also might want to enable debugging so you can see what queries mongoose is launching to the server (mongoose.set('debug', true)).

Mongoose embedded documents / DocumentsArrays id

In the Mongoose documentation at the following address:
http://mongoosejs.com/docs/embedded-documents.html
There is a statement:
DocumentArrays have an special method id that filters your embedded
documents by their _id property (each embedded document gets one):
Consider the following snippet:
post.comments.id(my_id).remove();
post.save(function (err) {
// embedded comment with id `my_id` removed!
});
I've looked at the data and there are no _ids for the embedded documents as would appear to be confirmed by this post:
How to return the last push() embedded document
My question is:
Is the documentation correct? If so then how do I find out what 'my_id' is (in the example) to do a '.id(my_id)' in the first place?
If the documentation is incorrect is it safe to use the index as an id within the document array or should I generate a unique Id manually (as per the mentioned post).
Instead of doing push() with a json object like this (the way the mongoose docs suggest):
// create a comment
post.comments.push({ title: 'My comment' });
You should create an actual instance of your embedded object and push() that instead. Then you can grab the _id field from it directly, because mongoose sets it when the object is instantiated. Here's a full example:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var ObjectId = Schema.ObjectId
mongoose.connect('mongodb://localhost/testjs');
var Comment = new Schema({
title : String
, body : String
, date : Date
});
var BlogPost = new Schema({
author : ObjectId
, title : String
, body : String
, date : Date
, comments : [Comment]
, meta : {
votes : Number
, favs : Number
}
});
mongoose.model('Comment', Comment);
mongoose.model('BlogPost', BlogPost);
var BlogPost = mongoose.model('BlogPost');
var CommentModel = mongoose.model('Comment')
var post = new BlogPost();
// create a comment
var mycomment = new CommentModel();
mycomment.title = "blah"
console.log(mycomment._id) // <<<< This is what you're looking for
post.comments.push(mycomment);
post.save(function (err) {
if (!err) console.log('Success!');
})

Resources