Return mongoose result in a function - javascript

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)
);

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

Removing element from nested array in Mongoose

I'm working on an upvoting/downvoting application using MongoDB and Node.JS
I have created two interlinked schemas:
var mongoose = require('mongoose');
var Voters = require('./voters');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: {type: Number, default: 0},
voters: [Voters.schema],
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
and for voters:
var mongoose = require('mongoose');
var votersSchema = new mongoose.Schema({
voter_id: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
votetype: Number
});
module.exports = mongoose.model('Voters', votersSchema);
For including users in the voters array, I'm using this code:
var voterModel = new Voters();
voterModel.voter_id = req.payload._id;
voterModel.votetype = 1;
foundPost.voters.push(voterModel);
foundPost.save();
Which works just fine. For removing users I tried several methods, but none seem to work. The current one is $pull:
foundPost.update({'voters.voter_id': req.payload._id}, {$pull: {'voters': {'voter_id': req.payload._id, 'votetype': 1}}}, function(err){
if (err) { console.log(err); }
});
The update action works in the mongo shell, but not from within node. I also tried foundPost.voters.remove, but the result was the same. Also tried Voters.findOne, but the query always returns null.
Any help would be appreciated.
Use the id method first to find the voter then remove it and last save document to apply changes:
var voter = foundPost.voters.id(req.payload._id).remove();
foundPost.save(function (err) {
if (err) return handleError(err);
console.log('the voter was removed')
});

Mongoose schema

I have these mongoose schemas:
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
});
var cartSchema= new Schema({
"items": [ItemSchema]
});
but when I want to push a new item in items, mongoose add an _id field(on the new item) but I don't understand why.
if you want to add item without _id field then you should add { _id: false } in ItemSchema.
var ItemSchema = new Schema({
"pieces": Number,
"item": { type: Schema.Types.ObjectId, ref: 'Items' }
}, { _id: false });
Mongoose assigns each of your schemas an _id field by default if one is not passed into the Schema constructor. The type assigned is an ObjectId to coincide with MongoDB's default behavior. If you don't want an _id added to your schema at all, you may disable it using this option.
You can only use this option on sub-documents. Mongoose can't save a document without knowing its id, so you will get an error if you try to save a document without an _id.
Link: http://mongoosejs.com/docs/guide.html#_id

Mongoose: Cannot call method 'push' of undefined, on nested Schema

I set up my schema like so:
var videoSchema = new Schema({
title: String,
url: String, //Link to the video
rating: { type: Number, default: 0},
description: String //a paragraph or two to go along with the video
});
var tutorialPageSchema = new Schema({
title: String, //IE Peeking, Clutching, etc.
tutorials: [videoSchema]
});
var categorySchema = new Schema({
title: String, //intermediate, beginner, config, map knowledge, etc.
pages: [tutorialPageSchema]
});
exports.Video = mongoose.model('video', videoSchema);
exports.TutorialPage = mongoose.model('tutorialPage', tutorialPageSchema);
exports.Category = mongoose.model('category', categorySchema);
Add the document like so:
var newPage = new models.TutorialPage({
title: req.query.page.title,
tutorials: []
});
parentCategory.pages.push(newPage);
In return, it gives me a nice "TypeError: Cannot call method 'push' of undefined
"
Other times the question was asked, people didn't load the schemas in the correct order or conflated the Model with the Schema when setting the schema up, but that doesn't seem to be my problem. What gives?

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