Get Request for data in MongoDB with ExpressJs - node.js

I am new to nodejs/web app and I am trying to get data out from MongoDB.
My mongoDB has documents under collection "a"
{_id:("1"), "Question":"mcq1", "Answer":"one", "Keyword":"CLASS"}
{_id:("2"), "Question":"mcq2", "Answer":"two", "Keyword":"CLASS"}
{_id:("3"), "Question":"mcq3", "Answer":"three", "Keyword":"OVERLOAD"}
{_id:("4"), "Question":"mcq4", "Answer":"four", "Keyword":"OODP"}
I want to extract the data "Question": field_value, "Answer":field_value out using nodejs -> expressjs through a button and textbox form using the unique Keyword and to be displayed in a table form as below.
<tr>
<td><%= Question %></td>
<td><%= Answer %> </td>
</tr>
I have been able to get what i want with the monogodb shell using
db.a.find({"Keyword":CLASS},{"Question":1,"Answer":1,_id:0})
Currently the textbox and button onclick codes are below.
Input Keyword to search: <input type="text" id="searchBtn" value="">
<button type="button" onclick="alert(document.getElementById('searchBtn').value)">Click me!</button>
How can i extract the Question and Answer with the button click?
Using db.a.find({"Keyword":CLASS},{"Question":1,"Answer":1,_id:0})
i want to get a table in the form of
Question, Answer,Keyword
mcq1, one, CLASS
mcq2, two, CLASS

If you do a db query based on that keyword you'll get the occurrences in mongo, so you can do a form(GET/POST) field with the input and the button you already have. This will be caught in your express code as a route, there you can implement some basic code filling your search needs and the return value will be some simple data or an array if multiple match.
This is a basic search that one user (Miqe) once taught me here, first you need the query (or you can just put directly there) and later search in the mongo. But pay attention that your callback function will return the result, here is just a console.log() after returning the values you can assign them to a variable and pass through a template engine rendering in the html in the desire format.
query = {username: username, password: password}
dbo.collection('Users').find(query, function(err, user){
if(err) throw new Error(err);
if(!user)
console.log('Not found');
else
console.log('Found!');
})
Here is just the code to find in a collection named Users, you still need to join with the route and do a connection to the DB.
I'll leave a link who helped me a lot! The mongo documentation is still a good start too.
https://www.w3schools.com/nodejs/nodejs_mongodb_query.asp

Related

Ejs form, send array of data that can be converted into postgresql update queries

My app includes a scoresheet grid where each cell represents a student's score in one topic. The teacher can enter scores in each cell before clicking a submit button that sends them all at once.
Here is the ejs form that I have right now:
scoresheet.ejs
<tbody>
<% students.forEach((student, i) => { %>
<tr>
<td class="student-cell right">
<%= student.last_name %>, <%= student.first_name[0] %>
</td>
<% topics.forEach(topic=> { %>
<td class="score-cell center">
<input type="text" class="score-input" name="scores_<%= student.id %>_<%= topic.id %>">
</td>
<% }); %>
</tr>
<% }) %>
</tbody>
This form produces a req.body that looks something like this:
scores_1_2: '75',
scores_1_3: '92',
scores_1_4: '100',
scores_1_5: '100',
scores_1_6: '',
scores_2_1: '65',
scores_2_2: '60',
scores_2_3: '50',
scores_2_4: '35',
I'm trying to take this data and convert it into Postgresql query (or mutiple queries).
For example, the line scores_2_4: '35' would become
UPDATE scores SET points = 35 WHERE student_id = 2 AND topic_id = 4
The scores table is a many-to-many join table to connect students and topics.
I suspect that I still have a bit of work to do with my form. I'm probably not sending this data in an ideal way. This is my best solution so far to include a student_id and topic_id along with the teacher's score input.
If this approach is acceptable, then I also need a hint about how to convert all of this data into an update statement.
I'm using current versions of postgresql, nodejs, express, ejs and the node-postgres package.
Thank you in advance for any insight.
This is my best solution so far to include a student_id and topic_id along with the teacher's score input.
Yes, it's fine. You just have to parse the scores_${student_id}_${topic_id} format on the server back into the data structure you expect.
A more customary encoding is to use bracket notation instead of underscores though. Many parsers for application/x-www-form-urlencoded POST bodies can automatically transform this into a nested object, see e.g. Can not post the nested object json to node express body parser and How to get nested form data in express.js?.
<input type="text" class="score-input" name="scores[<%= student.id %>][<%= topic.id %>]">
I also need a hint about how to convert all of this data into an update statement.
Use multiple UPDATE statements for simplicity:
const { scores } = req.body;
for (const studentId in scores) {
const studentScores = scores[studentId];
for (const topicId in studentScores) {
const points = studentScores[topicId];
// TODO: check for permission (current user is a teacher who teaches the topic to the student)
await pgClient.query(
'UPDATE scores SET points = $3 WHERE student_id = $1 AND topic_id = $2',
[studentId, topicId, points]
);
}
}
You might want to throw in a parseInt or two with proper input validation for the studentId, topicId and points if you need them to be integers instead of strings; otherwise postgres will throw an exception.

How to fix this function, to retrieve data contain search keywords?

I'm developing website using MERN stack technologies. In that application I want to provide search facility. There is text box search button next to it. I want to open search results in new page. For example,
Data table contains products. If some user type 'milk' and click on search new page should show all milk product details.
when I click on search button it updated browser URL to this,
http://localhost:3000/search_result/this_is_search_string
This is the frontend code,
<form className="form-inline">
<input type="text"
className="form-control"
value={this.state.name}
onChange={this.on_change_name}/>
<Link to={'/search_result/'+this.state.name} className="btn btn-primary">Search</Link>
</form>
First problem is URL updated when click on button, but it not redirect to new page.
In search_result page componentDidMount() method looks like this,
componentDidMount(){
axios.get('http://localhost:4000/item/')
.then(response => {
this.setState({ search_result: response.data });
})
.catch(function (error) {
console.log(error);
})
}
I want to pass url appended value to above function' 2nd line,
axios.get('http://localhost:4000/item/') end of /item/. So I could load retrieved values to table.
Also in the backend controller file' method look like this.
export const get_items_by_name=(req,res)=>{
//Item.find(req.params.id,(err,item)=>{{name: "Renato"}
Item.find({name: "a"},(err,item)=>{
if(err){
res.send(err);
}
res.json(item);
});
};
In SQL there is a way to perform select query with LIKE. But I'm new to MERN stack. So how could I update above method to search and retrieve values as URL appended.
I need your help guys how to figure out this. Thank for your help specially with implementation support.
In your problem you need to change your controller something like this try it,
export const get_items_by_name=(req,res)=>{
//Item.find(req.params.id,(err,item)=>{{name: "Renato"}
Item.find({name:`/.*${req.body.name}.*/` },(err,item)=>{
if(err){
res.send(err);
}
res.json(item);
});
};
I tested this via postman and it works. You need to find way to do your page rendering part.

I have an array that is generated on page, saved as an variable. How to to send it with a POST to db (mongodb, node, express)

A node, express, mongodb question.
I have a webpage, with a some JS-code. The user types some things into the my form and then they can generate a table with data. Before the table is printed to the user the data as saved as a variable (Array). The array itself is named obj.invoices.
I can easily save the data from the form to the DB using the "name". When I use it shows up in the req.body, which i then can use in my controller and save it to the DB.
But how do i pass the generated variable (obj.invoices) from the page so that it will follow along in the POST and shows up in the req.body?
As for now the array isn't parsed so i cant build a function in express/mongoose to save the data to the DB.
I solved it but I'm quite sure this is a bad solution.
When finished generating the array I run this function,
function showArray() {
var json_data = JSON.stringify(myArray);
document.getElementById('showArray').innerHTML = json_data;
}
This convert the array to string, and then post it into a input within my form;
<div class="field">
<div class="control">
<textarea id="showArray" class="textarea is-info" type="text" name="ArrayToDb"></textarea>
</div>
</div>
So when i submit my form the array as a string is posted with the req.body. Then in my controller.js for the app I convert the string back to an array;
let jsonArray = JSON.parse(req.body.ArrayToDb)
and then i save it to the DB
newLan.fakturor = jsonArray;
newLan.save(function (err) {
console.log(newLan._id)
});
Like I said, this is most likely a really bad way to do it but it works for me, for now.

Using Ember Data to load data async from node sever

My Model :
App.Contacts = DS.Model.extend({
name : DS.attr('string'),
number : DS.attr('number')
});
This is how i save a record :
App.AddController = Ember.Controller.extend({
actions : {
addContact : function(){
var post = this.store.createRecord('Contacts',{
name : this.get('name') ,
number : this.get('number')
});
post.save();
}
}
});
Acc to Ember's offical guide, this would send a POST request to /Contacts , so to handle it, i used this in nodejs/expressjs
app.post('/contacts',function(req,res){
posts.push( req.body);
console.log(posts);
res.send({status: 'OK'});
});
Now i wish to retrieve it, into another template called all so i used :
App.AllRoute = Ember.Route.extend({
model : function(){
return this.store.find('Contacts');
},
setupController : function(controller,model){
controller.set('contactList',model);
}
});
Acc to Emberjs guides, model hook supports promises out-of-the-box . so i assumed this should work.
My template :
<script type="text/x-handlebars" id="all" >
Hello
<table>
{{#each contact in contactList}}
<tr>
<td>{{contact.name}} </td>
<td>{{contact.number}} </td>
</tr>
{{else}}
<tr><td>No contacts yet </td> </tr>
{{/each}}
</table>
</script>
Question
But the model returns nothing, i understand that this.store.find('Contacts') doesn't return a javascript array, but essentially and object , implimenting Ember.Enumerable
But on the server side, the posts is an javascript array, therefore there might be an type mismatch between then. how to resolve this?
EDIT:
To avoid any confusions in client side Ember code , This works properly, so there is some problem with the round trip to server.
App.AllRoute = Ember.Route.extend({
model : function(){
return this.store.all('Contacts');
},
setupController : function(controller,model){
controller.set('contactList',model);
}
});
If you could provide a jsfiddle, it be nice. I'm not sure whether contactList is defined or not and whether the alias for that controller is actually defined. So based on what I see, I think the problem is you're iterating over a controller that does not have the model properly defined.
I'd suggest trying to do:
{{#each}}
<tr>
<td>{{contact.name}} </td>
<td>{{contact.number}} </td>
</tr>
{{else}}
<tr><td>No contacts yet </td> </tr>
{{/each}}
If you really want to use the contactList controller, then you need to make sure that the App.AllController "needs" the contactListController.
App.ContactListController = Ember.ArrayController.extend({}) // needs to be an array controller
App.AddController = Ember.ArrayController.extend({
needs: ["contactList"], // controller's used within this controller
contactList: Ember.computed.alias("controllers.contactList"), // needed to iterate over the model how you're doing it.
Both of these solutions should work assuming your data is actually loaded in Ember Data. You might want to check the "data" tab on the ember-data console. If you don't have that browser extension installed, do it. It's incredibly useful.
If all else fails, try logging to verify expected values using {{log contactList}}
Good luck

How do you post data to CouchDB both with and without using JavaScript

I have a show which displays a form with fields populated from a document. I'd like to change the values in the field and then save the updated document.
I'm having trouble finding a clear, concise example of how to do this.
Seriously, just finishing this example would work wonders for so many people (I'm going to leave a lot of stuff out to make this concise).
Install Couchapp
This is outside the scope of my question, but here are the instructions for completeness.
Create a couchapp
Again, this is kind outside the scope of my question. Here is a perfectly concise tutorial on how to create a couchapp.
Create a template
Create a folder in the root of your couchapp called templates. Within the templates folder create an HTML page called myname.html. Put the following in it.
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<form method='post' action='#'>
<fieldset>
Hello <input type='text' name='name' value='{{ name }}'>
<input type='submit' name='submit' value='submit'>
</form>
</body>
</html>
Create a show
See the tutorial above for hwo to do this.
Add this code to a show called myname.
function(doc, req) {
if (doc) {
var ddoc = this
var Mustache = require("vendor/couchapp/lib/mustache");
var data = {
title: "The Name",
name: "Bobbert"
}
return Mustache.to_html(ddoc.templates.myname, data)
} else {
return ('nothing here baby')
}
}
Update the document with a new name by ...
So who can complete this step via both the client side and the server side?
Please don't point me to the guide, I need to read it in your words.
Thanks.
Edit:
Although the return value isn't pretty, just posting a form to the update handler will update the document.
You will probably want to look into update handler functions.
An update handler handles granular document transformations. So you can take 1 form, that has one distinct purpose, and only update the relevant fields in your document via the update handler.
Your update handler will need to take a PUT request from your form. A browser can't do this directly, so you'll need some javascript to handle this for you. If you're using jQuery, this plugin can take your form and submit it seamlessly via AJAX using PUT for you.
Inside the function, you can take the fields you are accepting, in this case name and apply that directly to the document. (input validation can be handled via the validate_doc_update function)
Update Handler (in your Design Document)
{
"updates": {
"name": function (doc, req) {
doc.name = req.form.name;
return [doc, "Name has been updated"];
}
}
}
HTML
<form id="myForm" action="/db/_design/ddoc/_update/name/doc_id">...</form>
JavaScript
$(document).ready(function() {
$('#myForm').ajaxForm({
type: "PUT",
success: function () {
alert("Thank you");
}
});
});
Once you've gotten this basic example up and running, it's not much more difficult to add some more advanced features to your update handlers. :)

Resources