I'm trying to use floats as keys in a mongodb database since I have to store the respective amount of each money value (e.g. 0.01: 10). But when I try saving the data via mongoose (node server using express) it only saves the data with normal (String) keys in the db.
This is my schema:
var ProtokollSchema = new Schema({
"date": String,
"0.01": {type: Number, default: 0},
"0.02": {type: Number, default: 0},
"0.05": {type: Number, default: 0},
"0.10": {type: Number, default: 0},
"0.20": {type: Number, default: 0},
"0.50": {type: Number, default: 0},
"1.00": {type: Number, default: 0},
"2.00": {type: Number, default: 0},
...
});
This is the express function setting the data:
.post(function(req, res) {
var protokoll = new ProtokollSchema();
protokoll["date"] = req.body["date"];
protokoll["0.01"] = req.body.data["0.01"];
protokoll["0.02"] = req.body.data["0.02"];
protokoll["0.05"] = req.body.data["0.05"];
protokoll["0.10"] = req.body.data["0.10"];
protokoll["0.20"] = req.body.data["0.20"];
protokoll["0.50"] = req.body.data["0.50"];
protokoll["1.00"] = req.body.data["1.00"];
protokoll["2.00"] = req.body.data["2.00"];
...
protokoll.save(function(err) {
if (err) res.json(err);
res.json({ message: "Comment successfully added!"});
});
})
Is there a solution or is it just not possible to do?
All keys in a schema must be a string whatever the key string looks like a normal string, a float or others.
Make sure that req.body.data be really with values like {"0.01": xxx, "0.02": xxx, ...};
You should use Model to create a document instead of Schema
//wrong way
var protokoll = new ProtokollSchema();
//Right way - Use the schema to generate a model and use model to new a docuemnt.
var Protokoll = mongoose.model('Protokoll', ProtokollSchema);
var protokoll = new Protokoll({"0.01": xxx, "0.02": xxx, ...});
The actual problem was that MongoDB simply doesn't support dots in its keys (see this question) Initially I thought the problem was the Schema of mongoose but obviously it wasn't.
Related
Im getting validation error at path badgeid, why am i getting this when my getting it when badgeid is a number, and what im saving is a number?`
Checks that i already checked:
achievement value is 5,
achievement type is Number
error:
(node:8260) UnhandledPromiseRejectionWarning: ValidationError: achievement_users validation failed: badgeid: Cast to Number failed for value "{ badgeid: 0,
progress: 0,
_id: 5c94c04a758c8a204440499e }" at path "badgeid"
save code:
var achievement = new achivementUsers();
achievement.badgeid = achievement;
return achievement.save().then(function (response) {
schema:
{
badgeid: {type: Number, default: 0},
progress: {type: Number, default: 0},
completed: {type: Boolean, default: false},
userid: {type: String, default: 'No name'},
}
You are overriding the variable achievement. You are setting achievement with the new model so you need to use another name instead:
//somewhere in the code `achievement` is 5
var achievementUser = new achivementUsers();
achievementUser.badgeid = achievement;
return achievementUser.save().then(function (response) {});
Or you can initialize the value when you create the model object. But it is still a good practice to use different variable names for different context.
//somewhere in the code `achievement` is 5
var achievement = new achivementUsers({
badgeid: achievement
});
return achievement.save().then(function (response) {});
What way would I go to save 40 different types of crimes, that each have and id and chance?
How would I get the ids, chance and update them?
What I got so far:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var crime_modelSchema = new Schema({
userid : String,
crimes: [
{
id: {type: Number, default: 1},
chance: { type: Number, default: 50}
}
],
ip: String,
time: Number,
});
module.exports = mongoose.model('crime_model', crime_modelSchema);
Is this the way to go or am I far?
For specific user:
db.crime_model.update({userid: user_id_you_want, "crimes.id": crimes_id_you want}, {$set: {"crimes.$.chance": 'update chnace'}});
For all user with specific crime id
db.crime_model.update({"crimes.id": crimes_id_you want}, {$set: {"crimes.$.chance": 'update chnace'}}, {multi: true});
Get id, chance you can directly retrieve the crime
db.crime_model.find({}, {crimes: 1})
I followed this SO question to generate an auto-increment sequence field in mongoose.
But on implementing & running the code I get the following error:
TypeError: Cannot read property 'seq' of null
Heres my code below:
Counter.js File
// app/models/counter.js
// load the things we need
var mongoose = require('mongoose');
// define the schema for our user model
var counterSchema = mongoose.Schema({
_id: {type: String, required: true},
seq: {type: Number, default: 0}
});
// methods ======================
// create the model for users and expose it to our app
module.exports = mongoose.model('Counter', counterSchema);
SupportTicket.js File
var Counter = require('../models/counter');
var ticketSchema = mongoose.Schema({
issue: String,
ticketNo: Number,
dateCreated : { type: Date, default: Date.now }
});
ticketSchema.pre('save', function(next) {
var doc = this;
Counter.findByIdAndUpdate({_id: 'entityId'}, {$inc: { seq: 1}}, function(error, counter) {
if(error)
return next(error);
doc.ticketNo = counter.seq;
next();
});
});
I can't figure out why am I getting the "Cannot read property 'seq' of null"
Any suggestions?
counter.findByIdAndUpdate({_id: 'url_count'},
{$inc: {seq: 1} },
{upsert: true , new: true},
function(error, counter)
Add This line.This will work fine.
{upsert: true , new: true}
my URLs look like this at the moment:
http://www.sitename.com/watch?companyId=507f1f77bcf86cd799439011&employeeId=507f191e810c19729de860ea&someOtherId=.....
So, as you can see, it gets pretty long, pretty fast.
I was thinking about shortening these ObjectIds.
Idea is that I should add new field called "shortId" to every model in my database. So instead of having:
var CompanySchema = mongoose.Schema({
/* _id will be added automatically by mongoose */
name: {type: String},
address: {type: String},
directorName: {type: String}
});
we would have this:
var CompanySchema = mongoose.Schema({
/* _id will be added automatically by mongoose */
shortId: {type: String}, /* WE SHOULD ADD THIS */
name: {type: String},
address: {type: String},
directorName: {type: String},
});
I found a way to do it like this:
// Encode
var b64 = new Buffer('47cc67093475061e3d95369d', 'hex')
.toString('base64')
.replace('+','-')
.replace('/','_')
;
// -> shortID is now: R8xnCTR1Bh49lTad
But I still think it could be shorter.
Also, I found this npm module: https://www.npmjs.com/package/short-mongo-id
but I don't see it's being used too much so I can't tell if it's reliable.
Anyone has any suggestions?
I ended up doing it like this:
Install shortId module (https://www.npmjs.com/package/shortid)
Now you need to somehow stick this shortId to your objects when they're being saved in the database. I found the easiest way to do this is to append this functionality on the end of mongoose's function called "save()" (or "saveAsync()" if you promisified your model). You can do it like this:
var saveRef = Company.save;
Company.save = function() {
var args = Array.prototype.slice.call(arguments, 0);
// Add shortId to this company
args[0].shortId = shortId.generate();
return saveRef.apply(this, args);
};
So you just basically at each Model.save() function append this functionality to add shortId. That's that.
Edit:
Also, I discovered that you can do it better and cleaner like this straight in Schema.
var shortId = require('shortid');
var CompanySchema = mongoose.Schema({
/* _id will be added automatically by mongoose */
shortId: {type: String, unique: true, default: shortId.generate}, /* WE SHOULD ADD THIS */
name: {type: String},
address: {type: String},
directorName: {type: String}
});
EDIT :
Now you can use the nanoid library which is much more performant and optimized. The documentation is also nice : https://github.com/ai/nanoid/
All existing modules use 64 chars table for conversion. So they have to use '-' and '_' chars in charset. It causes url encoding when you share short url through twitter or facebook. So be careful with it.
I use my own short id module id-shorter that free from this problem because it uses alpha-numeric set for converting.
Wish you success!
I have this schema where I validated the elements of array book, but I don't know how to validate the array itself.
var DictionarySchema = new Schema({
book: [
{
1: {
type: String,
required: true
},
2: String,
3: String,
c: String,
p: String,
r: String
}
]
});
For example, I would like to put the book array as required. Any help?
You can use a custom validator to do this. Simply check that the array itself is not empty:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
var bookSchema = new Schema({
1: { type: String, required: true },
2: String,
3: String,
c: String,
p: String,
r: String
});
var dictSchema = new Schema({
books: [bookSchema]
});
dictSchema.path('books').validate(function(value) {
return value.length;
},"'books' cannot be an empty array");
var Dictionary = mongoose.model( 'Dictionary', dictSchema );
var dict = new Dictionary({ "books": [] });
dict.save(function(err,doc) {
if (err) throw err;
console.log(doc);
});
Which will throw an error when there is no content in the array, and otherwise pass off the validation for the rules supplied for the fields in the array.