Is there anything wrong with my mongoose schema - javascript

I've stuck for 3 hours wrong and couldn't solve this issue. I'm getting nothing from my document.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var accountSchema = mongoose.Schema({
username: String,
salt: String,
hash: String,
cover: String,
createAt: {type: Date, default: Date.now},
subscriber_email: String
});
module.exports = mongoose.model('account', accountSchema);
I tested with other schema they all worked but not this one. My data's like below

I think the reason you are not able to view anything in your document is the way you are exporting the accountSchema.
Try replacing Account with account while exporting the schema.
Try this:
module.exports = mongoose.model('Account', accountSchema);
Everything else looks fine.
I hope this helps.

Related

Schema hasn't been registered for model in Schema but not others from the same source

I am trying to populate a node express route with information from Schemas, and I keep getting this error. What I cannot understand is that I am referencing three different fields in the same exact Schema and for some reason, I am only getting this error for one of those fields.
This is my route function where I am getting "MissingSchemaError: Schema hasn't been registered for model "completed_by_user""
// Schemas
const Transaction = require ("../models/transaction");
User = require ("../models/user");
Ticket = require ("../models/ticket");
Job = require ("../models/job");
Client = require ("../models/client");
// Functions
let numberWithCommas = require("../functions/numberWithCommas");
module.exports = function(app) {
// =======================Tickets
// index
app.get("/tickets", function(req, res){
Ticket.find({}).populate("created_by", "assigned_user", "completed_by_user").exec(function(err, tickets){ //This is where it happens
if(err){
console.log(err)
} else {
res.render("tickets", {tickets: tickets});
}
});
});
And this is the Ticket Schema itself:
const Transaction = require ("./transaction");
User = require ("./user");
Ticket = require ("./ticket");
Job = require ("./job");
Client = require ("./client");
// =======================Ticket Schema
var ticketSchema = new mongoose.Schema({
ticket_name: String,
description: String,
created_by: [{type: mongoose.Schema.Types.ObjectID, ref: "User"}],
assigned_user: [{type: mongoose.Schema.Types.ObjectID, ref: "User"}],
completed_by_user: [{type: mongoose.Schema.Types.ObjectID, ref: "User"}],
due_date: {type: Date},
completed_date: {type: Date},
completed_description: String,
date_added: {type: Date, default: Date.now}
});
module.exports = mongoose.model("Ticket", ticketSchema);
I am not getting this error for "created_by" or for "assigned_user" but I am getting it for "completed_by_user." I don't understand why this would be since they are all populated in the same Schema. This is not the only occurrence of this type of issue I am having, but I am sure it is for the same reason. I even tried changing the order I require the schemas and that has not helped either. Is there something obvious I am missing? Thanks.
.populate(["created_by", "assigned_user", "completed_by_user"])
Try this because .populate function takes only one argument by putting it into array it takes multiple

Return mongoose result in a function

I'm trying to return a result from my mongoose find operation. I know a lot of question have already been asked for this but i think this is different. Here's my user :
var UserSchema = new mongoose.Schema({
variable: {type: mongoose.Schema.ObjectId, ref: 'Variable'}
});
My user have a method to retrieve his variable. Here's the problem.
UserSchema.methods.getVariable = function() {
//TODO ?
}
I don't know how to populate my field and then return the result of the populate...
I think you can just use populate
var UserSchema = new mongoose.Schema({
variable: {type: mongoose.Schema.ObjectId, ref: 'Variable'}
});
UserSchema.
findOne({your:"query"}).
populate('variable').
exec().
then(
user=>console.log("user is:",user)
);

Shorten ObjectId in node.js and mongoose

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!

Whats the reason for not being able to nest Schemas without an array

I was just wondering why something like this isn't allowed in mongoose schema definitions:
var NameSchema = new mongoose.Schema({
first: {type: String, trim: true },
last: {type: String, trim: true }
});
var UserSchema = new mongoose.Schema({
name: NameSchema, // this line causes an error
age: {type: Number}
});
It seems like a design decision, I was just wondering if I could get an explanation as to why it isn't supported
Thanks!
You can nest a schema using this method:
name: [{ some: "props" } ]
or
name: [NameSchema]
The problem with giving directly the schema definition (without using "type: ...") is that Mongoose can't make the difference between the option object and the schema object. Mongoose will think that NameSchema is actually an option object (containing options such as the type, trim...).

Mongoose schema within schema

How can I add a schema to another schema? This doesn't seem to be valid:
var UserSchema = new Schema({
name : String,
app_key : String,
app_secret : String
})
var TaskSchema = new Schema({
name : String,
lastPerformed : Date,
folder : String,
user : UserSchema
})
I checked the website and it shows how to declare it for an array but not for single.
Thanks
There are a few ways to do this. The simplest is just this:
var TaskSchema = new Schema({
name : String,
lastPerformed : Date,
folder : String,
user : Schema.ObjectId
});
Then you just have to make sure your app is writing that id and using it in queries to fetch "related" data as necessary.
This is fine when searching tasks by user id, but more cumbersome when querying the user by task id:
// Get tasks with user id
Task.find({user: user_id}, function(err, tasks) {...});
// Get user from task id
Task.findById(id, function(err, task) {
User.findById(task.user, function(err, user) {
// do stuff with user
}
}
Another way is to take advantage of Mongoose's populate feature to simplify your queries. To get this, you could do the following:
var UserSchema = new Schema({
name : String,
app_key : String,
app_secret : String,
tasks : [{type: Schema.ObjectId, ref: 'Task'}] // assuming you name your model Task
});
var TaskSchema = new Schema({
name : String,
lastPerformed : Date,
folder : String,
user : {type: Schema.ObjectId, ref: 'User'} // assuming you name your model User
});
With this, your query for all users, including arrays of their tasks might be:
User.find({}).populate('tasks').run(function(err, users) {
// do something
});
Of course, this means maintaining the ids in both places. If that bothers you, it may be best to stick to the first method and just get used to writing more complex (but still simple enough) queries.
As of version 4.2.0, mongoose supports single subdocuments.
From the docs:
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
// Array of subdocuments
children: [childSchema],
// Single nested subdocuments. Caveat: single nested subdocs only work
// in mongoose >= 4.2.0
child: childSchema
});
What about this simple solution?
var TaskSchema = new Schema({
name : String,
lastPerformed : Date,
folder : String,
user : {
name : String,
app_key : String,
app_secret : String
}
})

Categories

Resources