How to return array of query results (Node.js & MongoDB) - node.js

I'm trying to create an array of query results so that I can use that array to populate one of my handlebars pages. Each index in the array holds Comments with a unique attribute. I currently have it set up like this:
This kicks the whole thing off:
//num is determined above
Comment.getComments(num, function(err, comments){
if(err){
console.log("ERROR");
}
console.log(comments);
res.render('page-i-want-to-populate-with-comments', {com : comments});
});
The getComments function calls this (in my models/comment.js):
module.exports.getComments = function(num, callback){
var comArr = [];
for(var i = 0; i < num; i++){
var uniqueId = i;
Comment.find({commentId : uniqueId}, function(err, items){
comArr.push(items);
});
}
callback(comArr);
}
Ideally I would then go to page-i-want-to-populate-with-comments.handlebars and:
{{#each com}}
<div class="comment-wrapper>
{{#each this}}
<div class="comment">
<p>{{this.text}}</p> //the text contained in the comment
</div>
{{/each}}
</div>
{{/each}}
My points of failure now are that comArr is empty when sent through callback() which causes an error in the callback function.
I get that this is probably confusing but this is the best I can explain it. I've been stuck on this for a while so any advice would be appreciated.

Related

how can i retrieve objectId of parse server through req.params.id

I am trying to retrieve a parse object with objectId in the show route on nodeJS. Below is my code to help you understand better.
//SHOW route
app.get("/books/:id", function(req, res) {
var Books = Parse.Object.extend("Books");
var query = new Parse.Query(Books);
query.equalTo("objectId", req.params.id);
query.find().then(function(foundBook){
res.render("show", {book: foundBook});
}, function(error) {
res.send("Error: " + error.code + " " + error.message);
});
});
Basically, The req.params.id does not return the objectID. when i try console.log(req.params.id), it returns the Title of the book stored in the database instead of the objectId which is important for linking to the /books/:id page.
Even when i try to retrieve all the objects from the database in the index route, i noticed that <%= book.get('objectId') %> is not displayed on the ejs page.
Please help me out of this. i am a beginner MEAN stack web developer but i am using parse server because the android and web applications would be sharing the same database on parse.com.
Thank You.
<% books.forEach(function(book) { %>
<div class="col-md-3 col-sm-6">
<div class="thumbnail">
<!-- this line of code gets the image content of the array and puts it in the img tag -->
<img src="<%= book.get('coverPictureLink') %>">
<div class="caption">
<h4><%= book.get('Title') %></h4>
</div>
<p>
<!-- This code adds the button and links it to the ID of the campground that was clicked on!-->
More Info
</p>
</div>
</div>
<% }); %>
</div>
Above is sample of the html page for displaying details of a particular book
I finally figured it out. The right way to retrieve object id on the html is book.id not book.get("objectId").
app.get("/books/:id", function(req, res) {
//find the book with provided ID
var Books = Parse.Object.extend("Books");
var query = new Parse.Query(Books);
query.get(req.params.id).then(function(book) {
console.log('retrieved! ' + book.id);
res.render('show', {book: book});
}, function(error) {
console.log('error occured');
res.send('could not be retrieved');
});
});
On the html file,
<p>
More Info
</p>
This is also the same if you are using node.js. with the parse server framework. Using .get('objectId') returns undefined values. Therefore you have to use.
for (i = 0; i < result.length; i++){
console.log('ID:' + result[i].id)
}

Rendering data in handlebars using express framework

Hello I am working in Express Framework, I am using handlebars to render the data from my mysql table. While trying to render the data using below code,instead of rendering value it displaying [object object]. I posted my code below.
index.js:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows)
{
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows});
}
requestform.hbs:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data}}" class="line" class="text-line" style="margin-left:35px;"><br>
</div>
The value in the form input displaying as [object object]. I tried as data.key_value to render the data but it is not displaying the value.
Please give me a solution. Thank you.
Because the result of Mysql response is array so it should be:
var query = connection.query('SELECT * FROM requestor_auth WHERE question_id = ? AND answer = ? AND app_key = ? LIMIT 1', [data.qid, data.ansvalue, data.appid], function(err,rows) {
if(err) {
console.log("Error Selecting : %s ",err );
res.redirect('/');
} else {
res.render('requestform',{page_title:"Edit Customers - Node.js",data:rows[0]});
}
If there's a same error you should console.log() your result to check the value.
The rows argument in your callback function is by a select query always an array of objects. With handlebars you should be able to do the following:
<div class="addressto">
<h4>To,</h4>
<br>
<span style="font-size:18px;margin-left:10px;">The Collector Of</span>
<input type="text" value="{{data[0].answer}}" class="line text-line" style="margin-left:35px;">
<br>
</div>
Also multiple class names can be in one class attribute.

Why am I getting wrappedPointCut instead of the data?

I have 3 tiers of nested objects stored in mongoDB.
The first tier shows the name like it is supposed to, the second as well.
But when it goes in to the third tier it shows the text:"wrappedPointCut"
Why is this? and What does wrapedPointCut mean??
I have a handlebars test code like this:
{{#each tierOne}}
<h2>{{ this.tierOneName }}</h2>
{{#each tierTwo}}
<h2>{{ this.tierTwoName }}</h2>
{{#each tierThree}}
<h2>{{ this.tierThreeName }}</h2>
{{/each}}
{{/each}}
{{/each}}
</div>
When iterating through the nested objects in JS I get the correct output in console. Also if I add 4 objects to the third tier I get 4 headers that read:"wrapedPointCut". This must mean it knows that there is data here.
this is the mongoDB structure:
this is the Tier 3:
var TierThree = new mongoose.Schema({
tierThreeName : {
type: String
}
});
this is the Tier 2:
var TierTwo = new mongoose.Schema({
tierTwoName : {
type: String
},
tierThree : [TierThree]
});
this is the Tier 1:
var TierOne = mongoose.Schema({
tierOneName : {
type: String,
index:true
},
tierTwo: [TierTwo]
});
Here is the function that exports the third tier to monngoDB:
module.exports.createTierThree = function(newTierThree, tierOne, tierTwoName , callback){
for (var i = 0; i < tierOne.tierTwo.length; i++) {
if(tierOne.tierTwo[i].tierTwoName == tierTwoName ){
tierOne.tierTwo[i].tierThree.push(newTierThree);
tierOne.tierTwo[i].save(function (err) {
if (!err) console.log('Success!');
});
}
}
};
The problem seemed to be that I'm doing something wrong when adding to database. If I add to the database using shell command everything is fine. So the problem now is to turn mongoDB shell command to JS.

How to return the corresponding image by id in a helper with CollectionFS?

I had real problems writing the title of this question. I am using gridfs for my storage, so the files are stored in my MongoDb. Now I have the following situation:
var imageStore = new FS.Store.GridFS('images', {});
Images = new FS.Collection('images', {
stores: [imageStore]
});
Test = new Meteor.Collection('test');
The Images are stored in Images and the "posts" are stored in test. Now when I upload an image, as I can't reference the image in my Test collection, I save the ._id for that image.
FS.Utility.eachFile(event, function (file)
{
var image = Images.insert(file, function (err, fileObj)
{
});
Test.insert({name: 'Test!', userId: '123123', image: image._id});
});
Now in my template, I want to show the name and the image. But what do I return in my helper? My template for a single post looks like this:
<li>
<h2>{{name}}</h2>
<img src="{{file.url}}" alt="" class="thumbnail" />
</li>
And the Helper function:
Tests: function ()
{
return each-test-with-their-image;
}
I imagined something like this, but it looks stupid as hell:
Tests: function ()
{
var tests = Test.find().fetch();
for(var i = 0; i < tests.length; i++)
{
tests[i].file = Images.findOne({_id: tests[i].image});
}
return tests;
}
But I feel that there must be a better way.
Rather than iterate over an array of results you can just get the url in a helper as each document is displayed. This is cleaner and you don't have to recompute the whole array as docs are added/removed/changed.
html:
<li>
<h2>{{name}}</h2>
<img src="{{url}}" alt="" class="thumbnail" />
</li>
js:
Template.myTemplate.helpers({
url: function(){
var queryImage = Images.findOne({_id: this.image});
return queryImage && queryImage.url();
}
});

How to access elements in the current template in meteor?

I have a template like this,
<template name = "foo">
<p id="loading" >LOADING...</p>
<p> {{theResult}} </p>
</template>
This is how I create foos,
// foos = [a, b, c, d]. With each button click I add a new item to the array
{{#each foos}}
{{> foo .}}
{{/each}}
And how a foo works,
Template.foo.created = function(){
var name = Template.currentData();
api_call(name, function(err, result){
Session.set(name, result);
});
}
Template.foo.helpers({
'theResult': function(){
var name = Template.currentData();
if(Session.get(name)) {
$("#loading").hide();
return Session.get(name);
} else {
return "";
}
}
})
So my expectation is to when the data came from the api_call, to hide "LOADING..." para, and to show the result in theResult.
The result is showing correctly. My problem is "LOADING..." is only get hidden on the top most foo. Not the other ones.
How can I fix this?
EDIT:
As suggested instead of,
$("#loading").hide();
I used,
Template.instance().$("#loading").hide();
This didn't work too :)
This is how I'd do it
Template... if theResult is undefined, the else path will be rendered.
<template name="foo">
{{#with theResult}}<p> {{this}} </p>
{{else}}<p id="loading" >LOADING...</p>
{{/with}}
</template>
Javascript... theResult is a simple Session.get call
Template.foo.helpers({
theResult: function(){
var name = Template.currentData();
return name && Session.get(name);
}
});
Thanks to Meteor templating engine, you can access a template scoped jQuery object that will only return elements within the corresponding template.
Template.foo.helpers({
'someText': function(){
var template = Template.instance();
template.$('p').changeSomeattr();
return Session.get('myPara');
}
});

Resources