I'm working on a project in node.js, mongodb, and express that has to deal with transactions.
I can hard code the variables to be put into mongodb, but if not all the fields are being filled out (not all are required) then I'm just putting empty data into the database.
this code works:
var d = new Date();
var n = d.toJSON();
var date = n;
var address = req.body.property_address;
var client_name = req.body.client_name;
var sales_price = req.body.sales_price;
var commission_percent = req.body.commission_percent;
var referral = req.body.referral;
var donation = req.body.donation;
var client_source = req.body.client_source;
var client_type = req.body.client_type;
var notes = req.body.notes;
Transaction.findOne({ name: { $regex: new RegExp(date, "i") } },
function(err, doc){
if(!err && !doc) {
console.log("there is no error, and this does not already exist");
var newTransaction = new Transaction();
newTransaction.date = date;
newTransaction.address = address;
newTransaction.client_name = client_name;
newTransaction.sales_price = sales_price;
newTransaction.commission_percent = commission_percent;
newTransaction.referral = referral;
newTransaction.donation = donation;
newTransaction.client_source = client_source;
newTransaction.client_type = client_type;
newTransaction.notes = notes;
newTransaction.save(function(err) {
if(!err){
console.log("successfully saved");
res.json(200, {message: newTransaction.date});
} else {
res.json(500, {message: "Could not create transaction. Error: " + err})
}
});
}
});
But what's the point of putting in a value that doesn't exist into mongodb? Isn't that one of the things that is supposed to be awesome about it? And my thinking is, it takes away possible queries that I might be able to do in the future.
Would it be possible to do something more like this?
Transaction.findOne({ name: { $regex: new RegExp(date, 'i' ) } },
function(err, doc){
if(!err && !doc){
var newTransaction = new Transaction();
for(var key in req.body){
newTransaction.key = req.body[key];
}
}
}
});
update
This is the code I ended up using that worked.
Transaction.findOne({ name: { $regex: new RegExp(date, "i") } },
function(err, doc){
if(!err && !doc){
var newTransaction = new Transaction();
for(var key in req.body){
if(req.body[key] != ''){
newTransaction[key] = req.body[key];
}
}
}
}
});
This is perfectly fine behaviour. You can still query a field that doesn't exist in all documents, as a non-existent field is the same as not equal.
This means the loose definition of the documents is still retained.
Looks fine to me, but I would probably not want to trust just ANY client data to serve as key, depending on how you deploy.
Perhaps:
['date', 'address', 'client_name'/*,...*/].forEach(function(key)
{
/* ... */
if (key in req.body) newTransaction[key] = req.body[key];
});
Related
im having a problem in my program. i need to pass all the values of my array to the database. Here is my program..
exports.post = function(req, res){
var obj = {};
var eacode = req.body.eacode;
db.all("SELECT * FROM localarea_listings WHERE eacode= ? ",eacode, function(err,rows2){
rows2.forEach(function (row2) {
var hcn = row2.hcn;
var shsn = row2.shsn;
console.log(hcn);
console.log(shsn);
});
db.all("UPDATE localarea_listings SET INTERVIEW_STATUS = ? WHERE eacode = ?
and hcn =? and shsn = ?",[req.body.INTERVIEW_STATUS, req.body.eacode,
req.body.hcn, req.body.shsn],function(err,rows){
if (err)
{
console.log("Error Updating : %s ",err );
}
else
console.log("Success updating localarea_listings");
});
});
};
The data will process depending on the variable eacode from the database localarea_listings.db
Lets say the values hcn is 1,2,3,4,5 and shsn is 6,7,8,9,10 respectively.
when i print hcn and shsn, the value will display what i want, which is
hcn=[1,2,3,4,5] and shsn=[6,7,8,9,10]
The problem will starts here, when i update it, it only update the first value of the array which is 1 for hcn and 6 for shsn. i tried using row2[0].hcn and row2[0].shsn but it will cause error..
I hope my question is clear. Thanks!
You need to move the update inside the forEach
exports.post = function(req, res) {
var obj = {};
var eacode = req.body.eacode;
db.all("SELECT * FROM localarea_listings WHERE eacode= ? ", eacode, function(err, rows2) {
rows2.forEach(function(row2) {
var hcn = row2.hcn;
var shsn = row2.shsn;
console.log(hcn);
console.log(shsn);
db.all("UPDATE localarea_listings SET INTERVIEW_STATUS = ? WHERE eacode = ? and hcn = ? and shsn = ? ",[req.body.INTERVIEW_STATUS, req.body.eacode, hcn, shsn], function(err, rows) {
if (err) {
console.log("Error Updating : %s ", err);
} else
console.log("Success updating localarea_listings");
});
});
});
};
Parse-server doesn't support groupBy for queries. So instead of adapting code to work with the duplicate entries i've decided to create a Job to clean the data.
I've created a cloud function using underscore but the results are not good. It's deleting non-duplicate entries too.
I want to remove a entry if another entry exists with the same post_id and user_id
Parse.Cloud.job("removeDuplicateItems", function(request, status) {
var _ = require("underscore");
var hashTable = {};
function hashKeyForTestItem(testItem) {
var fields = ["user_id", "post_id"];
var hashKey = "";
_.each(fields, function (field) {
hashKey += testItem.get(field) + "/" ;
});
return hashKey;
}
var testItemsQuery = new Parse.Query("Post_shares");
testItemsQuery.each(function (testItem) {
var key = hashKeyForTestItem(testItem);
if (key in hashTable) { // this item was seen before, so destroy this
return testItem.destroy();
} else { // it is not in the hashTable, so keep it
hashTable[key] = 1;
}
}).then(function() {
status.success("removal completed successfully.");
}, function(error) {
status.error("Uh oh, something went wrong.");
});
});
Is there a better way of doing this?
I am trying to loop over a Firebase reference. It works but for some reason the forEach loop runs one more time than there are objects in the reference. This causes the Promise.all() function to fail and the whole promise to fail. Here is my code. I have no Idea what I'm doing wrong.
return userReceiptMetrics.child(userID).child('postItemIDs').orderByChild('itemID').equalTo(oldProductID).once('value', function(oldSnapshot) {
var oldPostItemIDs = [];
var metrics = oldSnapshot.val()
if (oldSnapshot.val() != null) {
return Promise.all(oldSnapshot.forEach(function(record) {
console.log(record.val());
var oldKey = record.key;
var newKey = oldKey.replace(oldProductID, newProductID);
var data = record.val();
oldPostItemIDs.push(oldKey);
data.itemID = newProductID;
updateObject['userReceiptMetrics/'+userID+'/postItemIDs/'+newKey] = data;
updateObject['userReceiptMetrics/'+userID+'/postItemIDs/'+oldKey] = null;
})).then(function() {
return Promise.all(oldPostItemIDs.map(function(oldPostItemID) {
return userReceiptMetrics.child(userID).child('postItems').child(oldPostItemID).then(function(oldPostItem) {
var oldKey = oldPostItem.key
var newKey = oldKey.replace(oldProductID, newProductID)
var data = record.val()
updateObject['userReceiptMetrics/'+userID+'/postItems/'+newKey] = data;
updateObject['userReceiptMetrics/'+userID+'/postItems/'+oldKey] = null;
progress(38);
});
}))
}).catch(function(error) {
console.log('fudge louise');
});
}
});
Here is the console output:
App listening on port 8080
Press Ctrl+C to quit.
FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "_state" at /productUpdateQueue/tasks to your security rules for better performance
FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "_state" at /productUpdateQueue/tasks to your security rules for better performance
{ date: '2016-12-21 22:05:03',
itemID: 'Macys-EReceipts-MENS HOSIERY-Size(No size provided)-Color(No color provided)-786888403743',
postID: '-KZbmaThvxNmrvHwh_mc' }
{ date: '2016-12-21 22:05:03',
itemID: 'Macys-EReceipts-MENS HOSIERY-Size(No size provided)-Color(No color provided)-786888403743',
postID: '-KZbxAUcwzcP28C91EZA' }
FIREBASE WARNING: Using an unspecified index. Consider adding ".indexOn": "itemID" at /userReceiptMetrics/HeQST8hSkoPUmkBiVDR0tpSPo0x2/postItemIDs to your security rules for better performance
fudge louise
So it looks like the Promise.all() call failed because there is an empty object at the end of the list of objects. Here is the corrected code.
return userReceiptMetrics.child(userID).child('postItemIDs').orderByChild('itemID').equalTo(oldProductID).once('value', function(oldSnapshot) {
var oldPostItemIDs = [];
var metrics = oldSnapshot.val()
if (oldSnapshot.val() != null) {
return Promise.all(oldSnapshot.forEach(function(record) {
console.log(record.val());
var oldKey = record.key;
var newKey = oldKey.replace(oldProductID, newProductID);
var data = record.val();
oldPostItemIDs.push(oldKey);
data.itemID = newProductID;
updateObject['userReceiptMetrics/'+userID+'/postItemIDs/'+newKey] = data;
updateObject['userReceiptMetrics/'+userID+'/postItemIDs/'+oldKey] = null;
})).then(function() {
return oldPostItemIDs.map(function(oldPostItemID) {
return userReceiptMetrics.child(userID).child('postItems').child(oldPostItemID).then(function(oldPostItem) {
var oldKey = oldPostItem.key
var newKey = oldKey.replace(oldProductID, newProductID)
var data = record.val()
updateObject['userReceiptMetrics/'+userID+'/postItems/'+newKey] = data;
updateObject['userReceiptMetrics/'+userID+'/postItems/'+oldKey] = null;
progress(38);
});
})
}).catch(function(error) {
console.log('fudge louise');
});
}
});
I may be missing something basic as why is it happening.
GET: example.com/users
//gives all data
GET: example.com/users?status=1
//gives data with status = 1
GET: example.com/users // this does not work
gives same data as pervious API condition with status=1
On third hit, self.whereObj is not initialising to default empty object instead it takes previous value of {'status' = '1'}, however self.page and self.limit is taking default value if no query parameter is provided in query string.
example.com/users?limit=3, // takes override to 3 form default value of 5
example.com/users // self.limit takes default 5 and this works fine
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not ?
var Bookshelf = require('../../dbconfig').bookshelf;
Bookshelf.Collection = Bookshelf.Collection.extend({
limit: 5,
page: 1,
whereObj: {}
myFetch: function (query_params,expectedWhereFields) {
var self = this;
var whereObj = self.whereObj ; // this is not initializing
// var whereObj = {}; this is initialising
var page = self.page;
var limit = self.limit; //this is not showing nay initialisation error
for (var x in query_params) {
if (expectedWhereFields.includes(x)) {
whereObj[x] = query_params[x];
}
if (x === 'page') {
page = query_params[x];
}
if (x === 'limit') {
limit = query_params[x];
}
}
var offset = (page - 1) * limit;
function fetch() {
return self.constructor.forge()
.query({where: whereObj})
.query(function (qb) {
qb.offset(offset).limit(limit);
})
.then(function (collection) {
return collection;
})
.catch(function (err) {
return err
});
}
return new fetch();
}
});
module.exports = Bookshelf;
UPDATED
service.js
var Model = require('./../models/Users');
var express = require('express');
var listUsers = function (query_params, callback) {
var expectedWhereFields = ["type", "status", "name"];
Model.Users
.forge()
.myFetch(query_params, expectedWhereFields)
.then(function (collection) {
return callback(null, collection);
})
.catch(function (err) {
return callback(err, null);
});
};
module.exports = {
listUsers: listUsers
};
model/Users.js
var Bookshelf = require('../../dbconfig').bookshelf;
var Base = require('./base');
// Users model
var User = Bookshelf.Model.extend({
tableName: 'user_table'
});
var Users = Bookshelf.Collection.extend({
model: User
});
module.exports = {
User: User,
Users: Users
};
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not?
Because objects are reference values. When you set var whereObj = self.whereObj;, both refer to the same object, and when you copy the query parameters into the object properties you are effectively writing into your defaults instance. This does not happen with primitive values such as strings - they don't have mutable properties.
I'm struggling to make this works. i'm dealing with sequelize promisses and i want to return the queried elements to the view, but instead its returning null. I know its because promises are async requests and it does not return a result immediatly after you call it, ok, but how to return the values, put it into an array and than return the array?
this is the code i have so far.
router.post('/register', function(req, res, next) {
var sales = req.body.sales;
var person = req.body.personID;
var promisses = [];
var delivery = req.body.delivery;
for(var i =0;i<sales.length;i++){
var product_id = sales[i].product_id;
var amount = sales[i].amount;
var price = sales[i].produto_price;
var salePromisse = Sale.create({
'product_id': product_id,
'person_id': person,
'amount': amount,
'price': price,
'total': amount*price
});
//i couldnt find a word which describes what movimentacao means...lets keep it.
var movimentacao = Movimentacao.create({
"tipo": 0,
"id_product": product_id,
"id_provider": "",
"data": new Date(),
"price": amount*price
});
promisses.push(salePromisse);
promisses.push(movimentacPromisse);
}
Promise.all(promisses).then(function (promissesArray){
var name = "";
var suc = 0;
var total = 0;
var salesResult = [];
var salesObject = {};
if(!delivery){
res.send({msg: "aaaaa"});
}else{
promissesArray.forEach(function(pro){
if(pro!==null && pro !== undefined){
if(pro['$modelOptions'].tableName === undefined){
Product.findById(pro.product_id).then(function (product){
salesObject.product = product.name;
salesObject.price= pro.price;
salesObject.amount = pro.amount;
salesObject.total = pro.total;
total += salesObject.total;
salesResult.push(salesObject);
salesObject = {};
return Person.findById(per);
}).then(function (person) {
name = person.name;
});;
}
}
});
//here is where i would like to return to the view salesResult and name.
//res.render("folder/view", {sales: salesResult, person: name});
console.log(salesResult);
}
});
});
Well, the promisses array has the CREATE instance for each of my models, and i'm creating a few types of it.
I want to insert on the database, check if the promise resolved is dealing with an specific table (the field modelOptions is undefined on it, i already debugged), query all the other results because on the promisses array i have just the id, and than put into the array to be able to return to the view, but on the console.log on the last line, it returns null. How can i improve the code to be able to do all i want and than return to the view?
Dont worry, all the model related variables are beeing declared above.
Thanks.