Printing mongoose collections in jade template; only getting one document - javascript

I’m new to web development in general and wonder why the the cursor method for mongoose only returns the first document in the collection and not all of them?
My goal is to pass these documents to a jade template.
I'm using MongoDB and Express
The code:
var array = [];
var stream = MyModel.find({}).cursor();
stream.on('data',function(task){
array.push(task)
});
stream.on('error', function(err){
//Handle error
});
stream.on('close', function(){
res.render('dashboard', { title: 'Dashboard', csrfToken: req.csrfToken(), array: array});
});
Since I'm new to this my "code-jargon" might not be spot on so i'll be happy to specify if necessary.

You can try something like
MyModel.find({},function(err,docs){
res.render('dashboard', { title: 'Dashboard', csrfToken: req.csrfToken(), array: docs});
});
according to mongoose doc, you can attach a callback to the query, so it will turn the cursor into an array of documents.

Related

TypeError: Cannot read property 'identity' of null Javascript Neo4J data

maybe you can help me with this issue. I´m trying to code in my js app a get request to a Neo4J database and send this data to a ejs page. The problem is that when my request gets nothing (null) it blocks me all the code with an error: "TypeError: Cannot read property 'identity' of null". The only what I´m looking for, is when no data are retrieved nothing should happen without throwing any errors... only continuing with the rest of the code, but I don´t know how to handle this "null".
app.get('/page/:id', function(req, res) {
var id = req.params.id;
session
.run("OPTIONAL MATCH(a:Person)-[r]-(b) WHERE id(a)=toInteger($idParam) RETURN b", {
idParam:id
})
.then(function(result2){
var RelationArr = [];
result2.records.forEach(function(record){
RelationArr.push({
id: record._fields[0].identity.low,
name: record._fields[0].properties.name,
title: record._fields[0].properties.title,
});
});
res.render('person', {
relation: RelationArr,
});
})
.catch(function(err){
console.log(err);
});
})
Check if the value exists before accessing props.
app.get('/page/:id', function(req, res) {
var id = req.params.id;
session
.run("OPTIONAL MATCH(a:Person)-[r]-(b) WHERE id(a)=toInteger($idParam) RETURN b", {
idParam:id
})
.then(function(result2){
var RelationArr = [];
result2.records.forEach(function(record){
if(record._fields[0]) {
RelationArr.push({
id: record._fields[0].identity.low,
name: record._fields[0].properties.name,
title: record._fields[0].properties.title,
});
}
});
res.render('person', {
relation: RelationArr,
});
})
.catch(function(err){
console.log(err);
});
})
Instead of changing the javascript code to handle the null, I changed the Neo4J query to avoid a "null" value:
MATCH(a)-[r]-(b) WHERE id(a)=toInteger($idParam) OPTIONAL MATCH (a) WHERE id(a)=toInteger($idParam) RETURN b
Thank you #CaptEmulation your contribution gave me the hint to look to the outcome of the query.

Why mongoose middleware "pre" remove with { query: true } is not called?

I'm a bit stuck on this problem.
I have read all the mongoose documentation about middleware and some stackoverflow issue and was unable to find-out how to solve my problem without duplicating queries (find then remove).
Normally, pre middleware on remove will not fire when call from Model and not from document. But according with the doc, if I add {query: true}, my function will be called from model query.
I use the latest monngoose version (5.4.16)
Here is my code.
let mySchema= new mongoose.Schema({
name: String,
comment: String
}, { usePushEach: true });
mySchema.pre('remove', { document: true }, function() {
console.log('remove document');
});
mySchema.pre('remove', { query: true }, function() {
console.log('remove');
});
const MyModel = mongoose.model('MyModel', mySchema);
And the call here
MyModel.deleteOne({ _id: modelId }, (errorRm) => {
if (errorRm) {
return res.json({ success: false, message: `${errorRm.message}` });
}
return res.json({ success: true, message: 'Model successfully removed' });
});
The model is successfully removed but nothing is logged from the "pre" functions...
Any help would be welcomed.
It's because you're using MyModel.deleteOne(). Use MyModel.remove() and it will work.
Acoording to the documentation:
You can pass options to Schema.pre() and Schema.post() to switch whether Mongoose calls your remove() hook for Document.remove() or Model.remove():

.find is not a function error

I'm developing a node js rest server and having an issue with my Schema queries. When I hit my end points I get the error TypeError: user.find is not a function
The following is my user.js file
var {mongoose} = require('../../dbcore/mongoose');
var Schema = mongoose.Schema;
module.exports = mongoose.model('User',new Schema( {
basicId: Schema.ObjectId,
activePurchaseIDs: {
type: [Schema.ObjectId],
default: []
},
activeOrderIDs: {
type: [Schema.ObjectId],
default: []
},
paymentOptionIDs: {
type: [Schema.ObjectId],
default: []
},
addressIDs: {
type: [Schema.ObjectId],
default: []
},
interestIDs: {
type: [Schema.ObjectId],
default: []
}
}));
and this is where it's imported/required.
var URLS = require('./urls');
var User = require('../schemas/user/user');
function init(app,mongoose) {
app.get(URLS.USERS_URL,(req,res)=>{
var user = new User({});
user.find().then((users)=>{
res.send({users});
},(err)=>{
res.status(400).send(err);
});
});
}
module.exports = init;
I was following a tutorial while writing this code and I was expecting it to work as I followed the tutorial step by step.
When you call var user = new User({}) you are creating a new MongoDB document based on the User model and assigning it to var user.
A single user document does not have a find() function, but your User model does.
var user = new User({});
User.find().then(...);
app.get(URLS.USERS_URL, async (req,res)=>{
const userList = await User.find();
if(!userList) {
res.status(500).json({success: false});
}
res.send(userList);
});
Your call to the database needs to look like this:
User.find().then((users)=>{
res.send({users});
}).catch((err)=>{
res.status(400).send(err);
});
You should call it directly on the module, because mongoose will handle creation implicitly and creating a new object isn't neccesary.
I'm not sure if your schema is correctly defined, but I'm not going to say your tutorial is wrong on that. You should go into mongo shell and check if the schema was created to verify it was designed correctly.
In my case, I wrote wrong this so check your file exports module.exports = XYZ format.
PS:- I wrote like this exports.module = XYZ

Cannot return id specific mongo documents in Angular controller

Trying to return a list of articles specific to a sectionId in angular controller. I can get back the entire list of articles using articles.query but the passed sectionId query param gets completely ignored. I tried a to abstract it to an articles service but I'm not sure how to build services correctly yet so it threw more errors. Any help / examples of how I might achieve this, preferable as a service, would be great. I am using mean.js. Thanks in advance!
Sections controller
angular.module('sections').controller('SectionsController', ['$scope', '$stateParams', '$location', 'Authentication', 'Sections', 'SectionArticlesList', 'Articles',
function($scope, $stateParams, $location, Authentication, Sections, SectionArticlesList, Articles) {
..........
// Find existing Section
$scope.findOne = function() {
$scope.section = Sections.get({
sectionId: $stateParams.sectionId // sections return fine
});
// problem starts here
$scope.articles = Articles.query({
section:$stateParams.sectionId // this param is ignored
});
$scope.articles.$promise.then(function(data) {
// all articles in collection returned instead of section specific
console.log('Articles: '+ JSON.stringify(data));
$scope.articles = data;
});
Articles Model
var ArticleSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
content: {
type: String,
default: '',
trim: true
},
section: {
type: Schema.ObjectId,
ref: 'Section'
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
UPDATE:
Following up on the advice of Kevin B and Brad Barber below, I tried adding a factory and node server route, passing the $stateParams.sectionId to the specific factory instance. I created a new route in the articles.routes.server to make sure not to have a conflict with the standard ‘/articles/:articleId’ route. Unfortunately, anything I try still either throws errors or everything in the articles collection which is the opposite of what I want to do.
section.client.controller
// Find existing Section
$scope.findOne = function() {
$scope.section = Sections.get({
sectionId: $stateParams.sectionId
});
// fails no matter what is passed to query
$scope.articles = SectionArticlesList.query($stateParams.sectionId);
//$scope.SectionArticlesList.query($stateParams.sectionId);
//$scope.articles = SectionArticlesList.query({sectionId});
$scope.articles.$promise.then(function(data) {
// still only ever returns full list of articles
console.log('Length of articles: '+ JSON.stringify(data.length));
$scope.articles = data;
});
….
articles.client.services
angular.module('articles').factory('SectionArticlesList', ['$resource',
function($resource) {
return $resource('articles/:articleSectionId', {
articleSectionId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}
]);
articles.server.routes
// Custom route
app.route('/articles/:articleSectionId')
.get(articles.listBySectionID);
// Custom binding
app.param('articleSectionId', articles.listBySectionID);
articles.server.controller
The server side controller function never appears to get called because neither of the console.logs show up.
exports.listBySectionID = function(req, res, id) {
console.log('listBySection Called....'); // this is never printed
// have tried passing - id, sectionId and {section:id}
Article.find( {section:id} ).sort('-created').populate('user', 'displayName').exec(function(err, articles) {
if (err) {
console.log('listBySection err triggered...'); // this neither
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.json(articles);
}
});
};
I think I have tried everything I can think of to pass the sectionId correctly but nothing has worked yet. The latest error in the console is the 404 below.Interestingly the sectionId IS getting through but as if it is looking for one single resource such as a single blog post.
GET /sectionArticles?sectionId=555bfaf29a005c30cbfe6931 404
I don't quite understand how the default mean.js /articles route and it's corresponding list function works but duplicating a similar structure and passing an id as a param to the query to retrieve only specific results doesn't.
Would really like to understand how this should be wired up. If anyone can point out what I am doing wrong I’d appreciate it!

angular push adds operator that that results in MongoError

I am implementing the tutorial on the mean stack https://www.youtube.com/watch?v=AEE7DY2AYvI
I am adding a delete feature to remove items from the database on a button click
My client side controller has the following 2 functions to add to db and remove
$scope.createMeetup = function() {
var meetup = new Meetup();
meetup.name = $scope.meetupName;
meetup.$save(function (result) {
$scope.meetups.push(result);
$scope.meetupName = '';
});
}
$scope.deleteMeetup = function() {
item = $scope.meetups[0];
console.log("deleting meetup: " + item["name"]);
Meetup.delete(item);
scope.meetups.shift();
}
My server side has the following code
module.exports.create = function (req, res) {
var meetup = new Meetup(req.body);
meetup.save(function (err, result) {
res.json(result);
});
}
module.exports.remove = function(req, res) {
console.log("GOING TO REMOVE!!!");
console.log(req.query);
item = req.query;
Meetup.remove(item, function (err, results) {
console.log("done");
console.log(err);
console.log(results);
});
}
When I run my code and if I delete an already loaded item in the list, it is removed from Mongodb just fine. But if I add an item to the list and I do not refresh the page, it results in an error at my server that appears as
GOING TO REMOVE!!!
{ '$resolved': 'true',
__v: '0',
_id: '54ec04e70398fab504085178',
name: 'j' }
done
{ [MongoError: unknown top level operator: $resolved]
name: 'MongoError',
code: 2,
err: 'unknown top level operator: $resolved' }
null
I if I refresh the page, the it gets deleted fine. But if I added the entry, angular seems to be adding a new variable $resolved. Why is that happening?
Also another question, What is the proper way to call delete? I call it now but I am not able to put a callback. I want a callback which returns and then I shift the list of items. I tried adding a callback but the code never reaches it.
ie I tried the following
/*
Meetup.delete(item, function () {
console.log("In callback!!");
console.log(returnValue);
console.log(responseHeaders);
$scope.meetups.splice(item);
});
*/
/*Meetup.delete(item,
function (returnValue, responseHeaders) {
console.log("In callback!!");
console.log(returnValue);
console.log(responseHeaders);
$scope.meetups.splice(item);
},
function (httpResponse){
// error handling here
console.log("Need to handle errors");
});
*/
I am very new to node and am confused. Any help is very, very appreciated
Looks like it possible to call item.delete instead of Meetup.delete(item). You can call same methods on model instance. It prevent sending angular properties to server.
But better to make a rest API with delete method
DELETE /meetups/:id
and send just a _id
Meetup.remove({id: item._id});

Categories