update mongodb with node.js using a variable in $set - javascript

I am making a voting system, the voting is done with a link. In my index.js I get the required values and put them in variables. The "type" variable stands for the field in my mongodb wich needs to be updated, I have put it in a variable because it depends on which link is clicked.
Now in the $set function they require the db field and a new value, for both I use variables but my "type" variable doesn't work. And when I go to my mongodb there is a new table created called "type". How can this be solved?
router.get('/vote/:Id/:Value/:Type', function(req, res) {
var db = req.db;
var id = req.params.Id;
var type = req.params.Type;
var value = parseInt(req.params.Value);
var newValue = value + 1;
var collection = db.get('games');
collection.update(
{"_id" : id},
{$set: {type: newValue}}
, function (err, doc) {
if (err) {
res.send("There was a problem");
}
else {
res.location("../../../admin");
res.redirect("../../../admin");
}
});
});

In javascript you cannot use variables as property names in object literals, and that's what you're trying to do.
Try it:
var a = 'someProperty';
var o = {a: 'somePropertyValue'};
console.log(o);
will print { a: 'somePropertyValue' } not {someProperty:'somePropertyValue}.
If javascript permitted referencing variables in property names in object literal notation it would have to get rid of unquoted names as those would create ambiguity.
Should a be used as the value of the property or should it be the value of the variable a?
Try creating the update object literal with an object crated beforehand without the usage of object literal notation, so your code looks something like this:
router.get('/vote/:Id/:Value/:Type', function(req, res) {
var db = req.db;
var id = req.params.Id;
var type = req.params.Type;
var value = parseInt(req.params.Value);
var newValue = value + 1;
var collection = db.get('games');
//We create the $set property/value pair using property assignment, not the object literal
var updateVal = {};
updateVal[type] = newValue;
collection.update(
{"_id" : id},
{$set: updateVal} //use it here
, function (err, doc) {
if (err) {
res.send("There was a problem");
}
else {
res.location("../../../admin");
res.redirect("../../../admin");
}
}
);
});
Even better, construct the whole $set operation beforehand.

Related

localStorage array.push

Could someone tell me how to push elements into an array in localStorage?
My code:
(localStorage.getItem('projects') === null) ? localStorage.setItem('projects', ['proj1', 'proj2', 'proj3']) : '';
var ItemGet = localStorage.getItem('projects');
function CreateObject() {
console.log(ItemGet);
var Serializable = JSON.parse(ItemGet);
Serializable.push('proj4');
console.log(ItemGet);
}
<button onclick="CreateObject()">Add Object</button>
General approach:
let old_data = JSON.parse(localStorage.getItem('projects'))
let new_data = old_data.push(some_new_data)
localStorage.setItem('projects',JSON.stringify(new_data))
I would do the following assuming that your data is not a multiDimensional array.
(localStorage.getItem('projects') === null) ? localStorage.setItem('projects',
JSON.stringify(['proj1', 'proj2', 'proj3'])) : '';
var ItemGet = localStorage.getItem('projects');
function CreateObject() {
var Serializable = JSON.parse(ItemGet);
Serializable.push('proj4');
localStorage.setItem('projects',JSON.stringify(Serializable));
}
The problem you are hitting is that data stored in localStorage has to be a string. You'll have to parse/stringify before settting/getting anything from local storage. If you didn't want to work with strings, you may find something like IndexedDB API
const stuff = [ 1, 2, 3 ];
// Stringify it before setting it
localStorage.setItem('stuff', JSON.stringify(stuff));
// Parse it after getting it
JSON.parse(localStorage.getItem('stuff'));
Here is an example of using IndexedDB API from the docs
const dbName = "the_name";
var request = indexedDB.open(dbName, 2);
request.onerror = function(event) {
// Handle errors.
};
request.onupgradeneeded = function(event) {
var db = event.target.result;
// Create an objectStore to hold information about our customers. We're
// going to use "ssn" as our key path because it's guaranteed to be
// unique - or at least that's what I was told during the kickoff meeting.
var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });
// Create an index to search customers by name. We may have duplicates
// so we can't use a unique index.
objectStore.createIndex("name", "name", { unique: false });
// Create an index to search customers by email. We want to ensure that
// no two customers have the same email, so use a unique index.
objectStore.createIndex("email", "email", { unique: true });
// Use transaction oncomplete to make sure the objectStore creation is
// finished before adding data into it.
objectStore.transaction.oncomplete = function(event) {
// Store values in the newly created objectStore.
var customerObjectStore = db.transaction("customers", "readwrite").objectStore("customers");
customerData.forEach(function(customer) {
customerObjectStore.add(customer);
});
};
};
There are also other solutions out there like PouchDB depending on your needs
Say for example you have an array. This is how you can store it in the local storage.
let my_array = [1, 2, 3, 4];
localStorage.setItem('local_val', JSON.stringify(my_array))
Now to push any data into the local storage array you have to override by the new data like bellow
let oldArray = JSON.parse(localStorage.getItem('local_val'))
oldArray.push(1000)
localStorage.setItem('local_val', JSON.stringify(oldArray))

How is this JavaScript object somehow converted to a string?

I have been working on a Node.JS/MongoDB backend for a product catalogue system and I have run into a weird bug.
The Process
First I load the product information from the product collection. This product contains information such as its name, description and also a list of file upload IDs that point to images of the product in an array of strings.
I then, for each upload ID, load the information for each photo. I then replace the array of upload ID strings with an array of file information objects.
However, when I output the resulting product object, the list of images is a list of strings that represent JavaScript as if they were written in code.
The Code
// products.controller.js
async function populateImageInformation(productRecord) {
let imageInfo = [];
for(let uploadId of productRecord.images) {
let imageData = await File.getByUploadId(uploadId);
imageInfo.push(imageData);
console.log(typeof imageData); // => object
}
console.log(typeof imageInfo); // => object
console.log(typeof imageInfo[0]); // => object
productRecord.images = imageInfo;
console.log(typeof productRecord.images); // => object
console.log(typeof productRecord.images[0]); // => string
return productRecord;
}
async function getAll(req, res, next) {
try {
let productRecords = await Product.find({});
for(let productRecordI in productRecords) {
productRecords[productRecordI] = await populateImageInformation(productRecords[productRecordI]);
}
res.json(productRecords);
} catch (e) {
next(e);
}
}
Mongoose schema file:
// file.model.js
getByUploadId: function(uploadId) {
return this.findOne({
uploadId
});
}
I do not understand that when I set the productRecord.images property to imageInfo the values in the array suddenly become string representations of the values.
The string does not contain JSON, but instead contains a human-readable string representation of how an object is hard-coded into JavaScript. These strings cannot be parsed as JSON at all. JSON expects keys to be wrapped in double quotes whereas the JavaScript code produced doesn't have this.
Is there any reason for this to happen? I have never seen this occur.
The problem is due to mongoose schema , they protect the model by types you declared in schema . Object Returning by find is a mongoose model, they do type check when you update any value on it.
Let's come to your scenario . I have created an example . See below
const mongoose = require('mongoose');
const db = require('./db');
const Schema = mongoose.Schema;
const productSchema = new Schema({
name: {type: String},
images: [String] // Note schema have array of string
});
const productModel = mongoose.model('product', productSchema);
db.connect().then(() => {
//find record from productSchema
return productModel.find({})
.then((productRecords) => { //productRecords - don't forget is a mongoose model object
// productRecords from db [{"name":"gilette","images":["idx","idy"],"_id":"5ac324c4fad317265b9df226","__v":0}]
//TRIAL A
for (let productRecordI in productRecords) {
productRecords[productRecordI] = populateImageInformation(productRecords[productRecordI]);
}
console.log(typeof productRecords[0].images[0]); //=> string;
//SOLUTION for the problem is copy mongoose data without reference
//TRIAL B
productRecords = JSON.parse(JSON.stringify(productRecords));
for (let productRecordI in productRecords) {
productRecords[productRecordI] = populateImageInformation(productRecords[productRecordI]);
}
console.log(typeof productRecords[0].images[0]); //=> Object;
});
//just a mock function change images to object
function populateImageInformation(productRecord) {
imageInfo = [];
for (let uploadId of productRecord.images) {
let imageData = {name: uploadId};
imageInfo.push(imageData);
console.log(typeof imageData); // => object
}
productRecord.images = imageInfo;
return productRecord;
}
}).catch((err) => {
console.log('err', err);
});

Getting variable outside of query block in Nodejs with sqlLite

I want to store all the rows from table to array(arr), I need to get the stored array outside of the defined query section. Is there a way I can get all the rows outside db.each such that I can manipulate them further.
var arr=[];
db.each("SELECT * FROM login", function(err, row) {
var title=row.title;
var context=row.context;
var newItem = {
'user': user,
'pwd': pwd
};
arr.push(newItem);
});
console.log(arr); //Outputs []
Because db.each is an asynchronous function, you need to use another function as a callback, like:
var arr=[];
db.each("SELECT * FROM login", function(err, row) {
var title=row.title;
var context=row.context;
var newItem = {
'user': user,
'pwd': pwd
};
arr.push(newItem);
}, function(){
console.log(arr)
});
Reference: https://github.com/mapbox/node-sqlite3/wiki/API#databaseeachsql-param--callback-complete

How can I pass variable when render view to script tag in Node.js

I'm using hbs as a template engine along with html.
This is my setting.
app.set('view engine', 'html');
app.engine('html', hbs.__express);
In my route.js
router.get('/home', isAuthenticated, function(req, res){
res.render('home', {
user: data something });
});
In my home.html I want to use user variable not as a template but to do something
<script>
var user = {{user}}; // It don't recognize user variable
/* do something about user variable */
</script>
Extending ting-y's answer.
If user is number or boolean:
var user = {{user}};
If user is a string:
var user = "{{user}}";
If user is an object or array, convert it into urlencoded JSON string and use:
var user = JSON.parse(decodeURI("{{user}}");
Standard approach
I like to you this more clean approach in rendering javascript variables using handlbars
json_utils.js
function tryParseJSON (jsonString){
try {
var o = JSON.parse(jsonString);
if (o && typeof o === "object") {
return o;
}
}
catch (e) { }
return null;
}
module.exports.safeJSONParse =tryParseJSON;
module.exports.encodeJSON = function(obj) {
obj = JSON.stringify(obj);
return encodeURI(obj);
};
module.exports.decodeJSON = function(obj) {
obj = decodeURI(obj);
console.log(obj);
return tryParseJSON(obj);
};
app.js
var express = require("express"),
jsonUtils = require("./json_utils");
var app = express();
app.get("/",function(req,res) {
var data = {
"name" : "John Doe",
"age" : 18,
"isAlive" : false,
"emergencyContacts" : [999999999,888888888,777777777]
};
res.render("home",{ "data" : jsonUtils.encodeJSON(data)});
});
home.handlebars
<script src="/utils_json_client.js"></script>
<script>
var data = jsonDecode("{{data}}");
console.log(data);
// {
// "name" : "John Doe",
// "age" : 18,
// "isAlive" : false,
// "emergencyContacts" : [999999999,888888888,777777777]
//}
<script>
try var user = "{{user}}";
if you user only contains string
You're using Handlebars rendering engine, the correct syntax would be {{#user}} more info
Surround them with quotes to cast those values into variables in javascript
<script>
var user = "{{#user}}";
</script>
You should use like this if your variable is a object. If you just type var={{user}} it will give an error if you type var user='{{user}}' it will be a string.
But if it is an object you must initialize with [].
var user = ['{{user}}'];

Parse query Javascript - "contains" on relational data

Consider I have an object A having pointer to object B.
Object B has a property "title" in it.
I want to query on object A with a string which is contained in title of object B.
Something like
var query1 = new Parse.Query("objectA");
query1.include("objectB");
query1.contains("objectB.title", anyQuery);
query.find({
success: function(obj){
},
error: function(obj, error) {
}
});
"anyQuery" here can be any string entered by a user in search field. Consider a user inputs "Mary" as query I should get all objectA related to objectB having title containing "Mary" in it. For example "Maryland".
Basically in simple words I want to execute a like query on related data in parse.
Edit
Thank you for the reply. I read the documentation at https://parse.com/docs/js_guide#queries-relational. I would like to extend my question. I want to use the query formed by matchesQuery in an or condition what I have done in my code is below but I get no results:
if(filterQuery) {
var Organization = Parse.Object.extend("Organization");
//LIKE QUERIES
var nameLikeQuery = new Parse.Query(Parse.User);
nameLikeQuery.contains("nameLc", filterQuery);
var phoneLikeQuery = new Parse.Query(Parse.User);
phoneLikeQuery.contains("phone", filterQuery);
var emailLikeQuery = new Parse.Query(Parse.User);
emailLikeQuery.contains("username", filterQuery);
var organizationMatchQuery = new Parse.Query(Organization);
organizationMatchQuery.contains("titleLc", filterQuery);
var userOrganizationQuery = new Parse.Query(Parse.User);
userOrganizationQuery.matchesQuery("organization", organizationMatchQuery);
var userQuery1 = new Parse.Query.or(nameLikeQuery, phoneLikeQuery);
var userQuery2 = new Parse.Query.or(emailLikeQuery, userQuery1);
userQuery = new Parse.Query.or(userQuery2, userOrganizationQuery);
} else {
userQuery = new Parse.Query(Parse.User);
}
if(type != "ALL") {
userQuery.equalTo("userType", type);
}
userQuery.include("organization");
userQuery.descending("createdAt");
userQuery.find();
As stated by Chris, this scenario is well documented under Relational Queries here:
https://parse.com/docs/js_guide#queries-relational
So for your particular needs it would look like:
var objectBQuery = new Parse.Query("objectB");
objectBQuery.contains("title", anyString);
var objectAQuery = new Parse.Query("objectA");
objectAQuery.matchesQuery("objectB", objectBQuery);
objectAQuery.find().then(function (list) {
// use list
}, function (error) {
console.log(error);
});

Categories