How to set new fields default value in mongodb? - mongodb

I have had a mongoose schema like below:
var schema = mongoose.Schema({
name: String
}
I had some documents with these schema and after a while I've added a new field with a default value :
var schema = mongoose.Schema({
name: String,
job: {type: String, default: function() { return "Job" + this.name.toLowerCase() }}
}
When I get the document (findOne), I can see the default value be set. But when I check the exact row in my database, default value is not set yet!
When I add new documents, the default value is set and everything is alright; but how can I make the old documents' default value be set in database?

Try to updated your old documents using hook :
schema.post('init', function (doc) {
if(!doc.job){
doc.job = "Job" + doc.name.toLowerCase();
doc.save();
}
});

Related

How to use Object type in mongose schema?

I am trying to store the amount of time an employee has worked in my MongoDB database, but not able to make a mongoose schema whose type will object.
The desired database should have a document like this:
{
name: 'name of employee',
report: {'01-01-2023':5hr, '02-01-202':7hr, '03-01-2023':8hrs}
}
This report will contain an object whose key will be a date and the value will be minutes or hours an employee has worked on that date.
how can I make a schema to achieve the desired goal, I have tried like this but did not work.
const UserSchema = new mongoose.Schema({
name:{
type: String,
required: true
},
report: {
type: Object, // what should I write here
}
})

Mongoose set default on field update if field is not present or null

I have a mongoose schema like this suppose:-
var mSchema = new Schema({
name: { type: String, required: true}
});
and have been using this schema for a year and now i want to add gender to it like this :-
var mSchema = new Schema({
name: { type: String, required: true},
gender: { type: String, default: 'Male' }
});
whenever there will be an update request i want this gender to automatically set Male as default but i found that default don't set on update request.
(Note: It's just an example not a real life scenario. i just want mongoose default work if field is not present or null)
Is there any way in which i can set default on the updation of document ?
If you are using a function like update(), then this is not directly possible as stated by this answer. Still, you can simply switch to a function like findOne() and use save(), which should do the same.
When upserting documents, you can also check out the setDefaultsOnInsert option: https://mongoosejs.com/docs/defaults.html#the-setdefaultsoninsert-option
const options = {
// Create a document if one isn't found. Required
// for `setDefaultsOnInsert`
upsert: true,
setDefaultsOnInsert: true
};
await XY.findOneAndUpdate(query, update, options);

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 Object data type won't save with defined schema

Using Mongo and Meteor with CoffeeScript, I'm trying to save a document with one Object:
Test = new SimpleSchema(
tag:
type: Object
)
And the insert:
test1 = new Meteor.Collection("test", { schema: Test})
test1.insert({ tag: {"name": "campus"} })
Result: a document gets saved in the database but the "tag" field is never set.
Couple of different troubleshooting steps I've taken:
Changing the data type to String works and the "tag" field gets set. However, I want to reference a tag property without having to parse the string every time.
Adding a collection without the schema saves the Object exactly how I want:
test2 = new Meteor.Collection("test2")
test2.insert({ tag: {"name": "campus"} })
EDIT: Fixed using the blackbox: true flag. See below answer for clarification.
Test = new SimpleSchema(
tag:
type: Object
blackbox: true
)
According to SimpleSchema docs, all defined properties must pass validation. So any Object data type without properties is treated as an empty Object unless you add the blackbox: true flag.
Source: http://atmospherejs.com/aldeed/simple-schema#blackbox
If you have a key with type Object, the properties of the object will be validated as well, so you must define all allowed properties in the schema. If this is not possible or you don't care to validate the object's properties, use the blackbox: true option to skip validation for everything within the object.
I use simple schema and create my models of the following way, and I don't have any problem.
Test = new Meteor.Collection("test", {
schema: new SimpleSchema({
ownerId: {
type: String,
},
dateAdd: {
type: Date,
}
})
})
Test.insert({ownerId:"123",dateAdd:"..."})
In Coffee Script
Test = new Meteor.Collection("test",
schema: new SimpleSchema(
ownerId:
type: String
dateAdd:
type: Date
)
)

Mongoose Db: How can I use a parameterized method in a Mongoose query?

var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var Group = new Schema({
name: { type: String, required: true },
members: [{ type: ObjectId, ref: 'User' }],
leader: { type: ObjectId, ref: 'User' },
// more fields to filter by
});
Group.method('role', function (user) {
if (this.leader === user) return "Leader";
else if (this.members.indexOf(user) >= 0) return "Member";
else return "Non-Member";
});
I'm a Mongoose newbie and my first real query was a tricky one. I need to select a set of groups an display group name and the role of the current user (user_id is stored in session variable).
Can I use the 'role' method in a Mongoose select query?
Perhaps I should use a custom Node stream and implement the role method there?
I'm note sure that my conditions (this.leader === user) or (this.members.indexOf(user) >= 0) are correct or efficient. I need to avoid loading the User object for every Group document.
Code example needed.
Thanks for your help!
what you want to use is the aggregation framework
http://docs.mongodb.org/manual/applications/aggregation/
You might need to dip down into the native driver for this query.