Mongoose/MongoDB - Saving a record to overwrite current data: - mongodb

So I have a object in the DB that is basically blog posts, there is a array of ObjectID's in there that reference the Categories collection.
So
Posts = {
title: String,
Content: String,
Categories: [{
type: ObjectID,
ref: 'Categories'
}]
I can create the posts fine, problem comes when I try to update them:
post.title = 'hi';
post.content = 'content';
post.categories = ['44523452525','4e1342413421342'];
post.save(function(){});
For some reason it will ADD those 2 categories instead of wiping the categories array and inserting those.
How do I get it to remove those and insert new ones?

I tried to reproduce this behavior but I couldn't - here's the code sample I ran:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
mongoose.connect('mongodb://localhost/testjs');
PostSchema = new Schema({
title:String,
content:String,
cats:[]
});
var Post = mongoose.model('Post', PostSchema);
var mypost = new Post()
mypost.title = "x"
mypost.content = "y"
mypost.cats = ['a','b','c']
mypost.save(
function(err){
mypost.cats = ['d','e']
mypost.save()
}
);
After the second call to save() the array contains only what it was set to ("d","e"). Can you try it and see if you get the same result? Maybe it's related to mongoose version, or something.

Related

Create multiple documents from an array of values in Mongo DB

I'm new to MongoDB and I know this might sound silly to many but is there a way(s) where you can create multiple documents from an array of values. I have written some code for this, but is there any other efficient/shorter way of doing that.
tags.map(async tag => {
const tagDoc = await TagModel.create({ tag, postID })
})
Tag Schema -
const tagSchema = new mongoose.Schema({
postID: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Post",
}],
tag: {
type: String,
required: true,
},
}, { timestamps: true })
Case 1 : Storing Tags in Same Collection
in mysql you have to store tags in different table , but in mongodb you can use same collection to store tags as array of string
in your post schema :
const postSchema = new mongoose.Schema({
...
tags: {
type: [String],
required: true,
}
});
when saving post =>
let post = new Post();
...
post.tags = req.body.tags; // ["Tag1","hello","Testing"];
await post.save();
Case 2 : Storing Tags in Different Collection
if you want to store tags in different collection Tag , then you can use Mongoose InsertMany()
let tags = req.body.tags ; // ["Tag1","hello","Testing"];
tagsArray = tags.map((t)=> { return {postID:post._id , tag:t}});
let tagsSaved = await Tag.insertMany(tagsArray);
console.log('tagsSaved=',tagsSaved);

mongoose model to connect to mongoDB

i have created model for the mongo collection like below. but it was giving me the collection output which saved in mongoDB.
var mongoose = require('mongoose'),
Schema = mongoose.Schema({
name: {
type: String
},
age: {
type: Number
},
})
module.exports = mongoose.model('container', Schema);}
But later when i changed the last line of the code which is
"module.exports = mongoose.model('container', Schema);"
to
"module.exports = mongoose.model('container', Schema, 'container');"
it worked properly. I check the mongoose document they say to use the previous line, then why didn't it worked.
your problem seems to be from using "Schema" as a variable name
var ContainerSchema = new mongoose.Schema({
...
});
and exporting
module.exports = mongoose.model("Container", ContainerSchema);
would work.

Mongodb collection name changed after creation

Problem is that then I run this code, after I check the db records with Robomongo on windows, I see only one collection created with name 'maximas' with two records,
if I remove Model2 from code, after creation result will be the same, but must be collection 'maxima'.
Is there bug in code that i don't see, or this word is reserved, any ideas?
The code,
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/mymodels', (e)=>{
if(e) throw e;
});
var schema = new mongoose.Schema({
text: {type: String}
});
var Model1 = mongoose.model('maxima', schema);
var Model2 = mongoose.model('maximas', schema);
var newData1 = new Model1({
text: 'test'
});
var newData2 = new Model2({
text: 'test'
});
newData1.save((e)=>{
if(e) throw e;
console.log('Saved');
});
newData2.save((e)=>{
if(e) throw e;
console.log('Saved');
});
Mongoose will automatically pluralise your model name as the collection name. This is why they are both the same, as the second collection name is already in plural form.
You can pass the desired collection name as the third model argument:
var Model1 = mongoose.model('maxima', schema, 'maxima');
var Model2 = mongoose.model('maximas', schema, 'maximas');
NOTE: You can also specify your collection name as an option in your schema:
var schema = new mongoose.Schema({
text: { type: String }
}, {
collection: 'maxima'
});
...but in this case you would require a second schema so the first approach above is more suitable here.

Mongoose Schema hasn't been registered for model when populating

I am trying to join 2 collections using the populate method, I have 3 models artists, albums and songs. My mongodb connection is made on server.js.
my artist model is :
var mongoose = require('mongoose');
//var Album = mongoose.model('Album').schema;
console.log(Album);
var artistsSchema = mongoose.Schema({
name:{
type:String,
required:true
},
albums:{
type:[{type:mongoose.Schema.Types.ObjectId,ref :'Album'}]
}
});
var Artist = mongoose.model('Artist',artistsSchema);
module.exports.getArtistsFull = function(callback,limit)
{
Artist.find().limit(1)
.populate({
path:'albums'
,populate :{path:'albums'}
}).exec(callback);
}
And my albums model:
var mongoose = require('mongoose');
var albumsSchema = mongoose.Schema({
name:{
type:String,
required:true
},
songs:{
type:[{type:mongoose.Schema.Types.ObjectId,ref :'Song'}]
}
});
var Album = mongoose.model('Albums',albumsSchema);
module.exports.getAlbumsWithSongs = function(id,callback,limit){
Album.findById(id)
.populate({
path : 'songs',
populate :{path:'songs'}
}).exec(callback);
}
Whenever I call Artist.getArtistsFull function I get an error"Schema hasn't been registered for model Album", I used console.log(Album) on my Album variable inside artist model and I got the functions that were written there, but I don't have access to albumsSchema.
The problem was actually a simple typo
var Album = mongoose.model('Albums',albumsSchema);
changed to
var Album = mongoose.model('Album',albumsSchema);

Adding to an array of lists in mongodb?

Silly question here, but I'm having trouble finding an example on the web.
I have set up a model on mongoDB that has arrays of objects, like so:
var ProjectSchema = new Schema({
project_id: { type: String },
item: {
title: { type: String },
owners: [{
first_name : {type: String} ,
middle_name : {type: String},
other_name: {type: String},
last_name: {type: String},
order: {type: Number, 'default': 1}
}]
}
}]
So you can see that item is a list of fields. And then owners is an array of lists of fields. When I create the project, I'm trying to set the owner like this:
var newProject = new Models.Project({
'item.title': title,
'item.owners[0].last_name': name,
'item.owners[0].order': 1
});
This doesn't generate an error, but the item fields don't get saved either (item.title saves fine).
I tried this too, but it gives me an error:
var newProject = new Models.Project({
'item.title': title,
item.owners.push({last_name: name, order: 1})
});
How am I supposed to refer to these sub-docs so I can save them?
Don't use dot notation in the fields of a new document, create it using the actual structure of the doc instead:
var newProject = new Models.Project({
item: {
title: title,
owners: [{
last_name: name,
order: 1
}]
});
it is a simple JSON object. With Javascript, it is quite straight forward. Below code generates the sample object given in the mongoDB doc:
var address1 = new Object();
address1.street = "123 Fake Street";
address1.city = "Faketon";
address1.state = "MA";
address1.zip = "12345";
var address2 = new Object();
address2.street = "1 Some other Street";
address2.city = "Boston";
address2.state = "MA";
address2.zip = "12345";
var data = new Object();
data._id = "joe";
data.name = "Joe Bookreader";
var addressArray = new Array();
addressArray.push(address1);
addressArray.push(address2);
data.addresses = addressArray;
alert(JSON.stringify(data));