How to execute query async in sequelizer in NodeJs - node.js

hello i have try bellow code but my code not work properly
tags.forEach(function(value) {
var where1 = {};
var attr1 = ['id'];
attr1 = ['id'];
where1['name'] = value;
tagData['name'] = value;
tagModel.getTag(where1, attr1, function(code2,result2){
if(result2.length!=0) {
var quick_start_tagData={'quick_start_id' : result1['id'], 'tag_id' :result2[0]['id']}
quick_start_tagModel.saveData(quick_start_tagData, function(code2,result2){
});
console.log(quick_start_tagData);
} else {
tagModel.saveData(tagData, function(code2,result2) {});
}
});
});
problem is for loop iterate no.of data when i check value of that data into table if table have same value then get its id and insert and if not than add new record and get its id and insert into another table
but first select query execute all time and than insert query execute in loop
how to solve this issue
Query Execute like that way
Executing (default):
SELECT id FROM pxl_tag AS pxl_tag WHERE pxl_tag.name = 'a1';
SELECT id FROM pxl_tag AS pxl_tag WHERE pxl_tag.name = 'a2';
SELECT id FROM pxl_tag AS pxl_tag WHERE pxl_tag.name = 'a3';
INSERT INTO pxl_tag (id,name,created_at,updated_at) VALUES
(DEFAULT,'a3','2018-05-04 04:35:32','2018-05-04 04:35:32');
INSERT INTO pxl_tag (id,name,created_at,updated_at) VALUES
(DEFAULT,'a3','2018-05-04 04:35:32','2018-05-04 04:35:32');
INSERT INTO pxl_tag (id,name,created_at,updated_at) VALUES
(DEFAULT,'a3','2018-05-04 04:35:32','2018-05-04 04:35:32');
but i want first select and insert step by step

You can use each method from async library.
For example:
UPDATE
async.each(tags, function(value, cb) {
var where1 = {};
var attr1 = ['id'];
attr1 = ['id'];
where1['name'] = value;
tagData['name'] = value;
tagModel.getTag(where1, attr1, function(code2, result2) {
if (result2.length != 0) {
var quick_start_tagData = {
'quick_start_id': result1['id'],
'tag_id': result2[0]['id']
}
quick_start_tagModel.saveData(quick_start_tagData, function(code2, result2) {
cb();
});
console.log(quick_start_tagData);
} else {
tagModel.saveData(tagData, function(code2, result2) {
cb();
});
}
});
}, function(err) {
if (err) {
console.log('An error ocurred');
} else {
console.log('Nothing happens');
}
});

If I understood you correctly, the problem is not that your INSERTs doesn't run right after the SELECTs. Your problem is that you are calling async functions (getTag() and saveData()) inside a sync function loop (forEach()), thus, by the time that your async functions resolve, they get the last value for tagData which is defined inside the sync loop. You should give it a different scope to get the correct tagData value.
Try this (untested):
tags.forEach(function(value) {
var where1 = {};
var attr1 = ['id'];
attr1 = ['id'];
where1['name'] = value;
tagData['name'] = value;
saveTag(tagModel, quick_start_tagModel, where1, attr1, result1, tagData);
});
//Create a function so that tagData will have a different scope for each call
function saveTag(tagModel, quickStartTagModel, where, attr, result1, tagData) {
tagModel.getTag(where, attr, function(code,result){
if(result.length!=0) {
var quickStartTagData = {'quick_start_id' : result1['id'], 'tag_id' :result[0]['id']}
quickStartTagModel.saveData(quickStartTagData, function(code, result){});
console.log(quickStartTagData);
} else {
tagModel.saveData(tagData, function(code,result) {});
}
});
}
if you strictly need to run the SELECT and INSERT sequentially (and not async), you should look at promises and async library. This might help:
Resolve promises one after another (i.e. in sequence)?

Related

How to update a table from a JSON object where the conditions are in a JSON object?

I want to update a taable from a JSON object. The WHERE clause of the update has more than one columns. I tried this :
connexion.query("update my_table set ? where ?", [{ "param_valeur": emails }, { "param_key": "paramKey", "flotte_id": 1 }], function (err, rows) {
console.log("=================== sql =", this.sql);
if (err)
throw err;
res.send("");
});
but at runtime the WHERE clause does not have the AND keyword ! So how to fix that ?
OK, you want to use dynamic data by sending a json to MySQL WHERE query, from what I found out until now this is not a trivial operation... So, my first answer is not a good solution for your requirements so I write a new and dynamic code. (a little bit more complicated than the first answer...)
Please try the solution and let my know if this is what you want.
my answer is based on https://www.npmjs.com/package/mysql#preparing-queries, you can read this docs section for better understanding of the double question marks syntax.
let paramsSETObj = { "param_valeur": emails };
let paramsWHEREObj = { "param_key": "paramKey", "flotte_id": 1 };
// separate the question marks with comma ', '
let questionMarksForSET = this.getQuestionMarksStr(Object.keys(paramsSETObj).length, ', ');
let valuesForSETArray = this.convertObjectToArray(paramsSETObj);
// separate the question marks with 'AND'
let questionMarksForWHERE = this.getQuestionMarksStr(Object.keys(paramsWHEREObj).length, ' AND ');
let valuesForWHEREArray = this.convertObjectToArray(paramsWHEREObj);
let sql = `UPDATE my_table SET ${questionMarksForSET} WHERE ${questionMarksForWHERE}`;
let inserts = [...valuesForSETArray, ...valuesForWHEREArray];
sql = mysql.format(sql, inserts);
connexion.query(sql, function (err, rows) {
if (err)
throw err;
res.send("");
});
// Convert an object to array, where each key is before the value
module.exports.convertObjectToArray = function (obj) {
let arr = [];
for (let key in obj) {
arr.push(key);
arr.push(obj[key]);
}
return arr;
}
/**
* Get a question marks string separate each pair with the equal sign '='
* the amount of the questions marks pairs is the same as the keys of the object from the request.
* The separator in this case is comma ',' or 'AND' - this is a must for your requirement in the question.
* example:
* questionMarksForSET: ?? = ? , ?? = ?
* questionMarksForWHERE: ?? = ? AND ?? = ?
*/
module.exports.getQuestionMarksStr = function (objKeysLength, separator) {
let questionsMarks = '';
for (let i = 0; i < objKeysLength; i++) {
// if the index is not in the last object key - add the separator else add empty string
let commaOrAndSeparator = (i !== objKeysLength - 1) ? separator : '';
questionsMarks += ' ?? = ? ' + commaOrAndSeparator;
}
return questionsMarks;
}
Try this:
connexion.query('UPDATE my_table SET param_valeur = ? WHERE param_key = ? AND flotte_id = ?', [emails, "paramKey", 1], function (err, rows) {
if (err)
throw err;
res.send("");
});

Dealing with async for each element of an array using async.js module in nodejs

I need to run a mysql query for each element of the array and add the final results to a response.
Is there no way to do this without adding a setTimeout? I find it odd. Tried everything from async / await , promises , callback , async.js module
How to deal with something like this in practice?
Here's what I'm trying to do
let reseach = { }
let drinktypes = ["1", "2", "3", "4"];
async.eachSeries(
drinktypes,
async item => {
console.log( 'item:', item )
let query = ` SELECT us.*,
fl.web_path,
pr.product_name,
pr.acidity,
pr.drink_type,
pr.recmd,
pr.raw_ingredient,
pr.milling,
pr.label_image as li,
fl2.web_path AS wp,
pr.alcohol,
pr.sake_index,
pr.kouboname,
pr.kojiname,
pr.product_details,
pr.memo,
pr.type_name,
pr.code AS code,
pr.raw_ingredient,
pr.milling,
mk.brewery_name,
mk.prefecture
FROM users_scores us
join products pr
ON us.product_id = pr.pid
LEFT JOIN fileslabels fl2 ON pr.label_image = fl2.id
join makers mk
ON pr.brewery = mk.mid
join product_label pl
ON pr.pid = pl.product_id
join files fl
ON pl.file_id = fl.id
WHERE user_id =\"${req.body.userid}\"
AND dranktimes <> 0
AND pr.drink_type = \"${item}\"`;
connection.query(query, function (error, results ,fields) {
if(!error) {
reseach[item] = results[0];
} else {
throw error;
}
});
Promise.resolve() // <-- instead of callback
},
err => {
console.log('err:', err)
console.log(reseach) // null
setTimeout(function(){
console.log("timeout", reseach); //works
}, 100);
}
)
If I understood your question right then you can simply do this with one SQL query (this query is short just for example):
let query = 'SELECT name FROM users WHERE drink_type IN (?)';
connection.query(query, drinktypes);
Using this

Delete filled in details after restart

I'm trying to let a person fill in some details and return an overview of the details. There is an option to restart the conversation (look at code) but when the conversation is restarted and the person fill in some new details, it will show the old details of the first filled in details.
How can i fix this problem ?
bot.dialog('overview', function (session, options) {
if (session.message && session.message.value) {
if(session.message.value.actions == "Accept"){
}
return;
}
var overview_msg = require('./cards/overview.json');
var date = new Date();
overview_msg.attachments[0].content.body[0].items[1].columns[1].items[0].text = overview_msg.attachments[0].content.body[0].items[1].columns[1].items[0].text.replace(/{{name}}/,nameGuest)
overview_msg.attachments[0].content.body[0].items[1].columns[1].items[1].text = overview_msg.attachments[0].content.body[0].items[1].columns[1].items[1].text.replace(/{{date}}/,date.toDateString() +' ' + date.toLocaleTimeString());
overview_msg.attachments[0].content.body[1].items[1].facts[0].value = overview_msg.attachments[0].content.body[1].items[1].facts[0].value.replace(/{{email}}/, mailGuest);
overview_msg.attachments[0].content.body[1].items[1].facts[1].value = overview_msg.attachments[0].content.body[1].items[1].facts[1].value.replace(/{{phone}}/, phoneGuest);
overview_msg.attachments[0].content.body[1].items[1].facts[2].value = overview_msg.attachments[0].content.body[1].items[1].facts[2].value.replace(/{{extra}}/, numberPeople);
overview_msg.attachments[0].content.body[1].items[1].facts[3].value = overview_msg.attachments[0].content.body[1].items[1].facts[3].value.replace(/{{lunch}}/, lunchGuest);
overview_msg.attachments[0].content.body[1].items[1].facts[3].value = overview_msg.attachments[0].content.body[1].items[1].facts[3].value.replace(/{{allergy}}/, lunchAllergyGuest);
overview_msg.attachments[0].content.body[1].items[1].facts[3].value = overview_msg.attachments[0].content.body[1].items[1].facts[3].value.replace(/{{vegan}}/, lunchVegan);
session.send(overview_msg);
bot.dialog('restart', function (session) {
session.beginDialog('overview');
}).triggerAction({matches: /restart|quit/i});
I think it may relate to how you define variables nameGuest, mailGuest, phoneGuest, etc which are not shown in your code snippet.
For getting values from Input.Text of adaptive-card, you can try the following code snippet:
bot.dialog('form', [
(session, args, next) => {
let card = require('./card.json');
if (session.message && session.message.value) {
next(session.message.value)
} else {
var msg = new builder.Message(session)
.addAttachment(card);
session.send(msg);
}
},
(session, results) => {
// Get the User input data here
session.send(JSON.stringify(results));
}
]).triggerAction({
matches: ['form', 'Action.Submit']
})
Yes i managed to get it done.
Instead of replacing the value in the json i referred to the variable.
example:
overview_msg.attachments[0].content.body[1].items[1].facts[0‌​].value = VARIABLE

mocking the populate method using mockgoose for mongoose (mongodb library for node.js) is null

Having trouble debugging an issue that mockgoose has for populating a property with fields set. Yads mockgoose http://github.com/yads/Mockgoose fork solved the bug of making the populate option work, but if you specify fields it returns a null for the populated property. I tried looking through the source code and stepping through with the debugger but not sure where to look. I can see in the debugger that the populate option triggers a call to get the child element - and I see the call made returns the right child result with the correct fields, but when the parent element finally comes back it has the property to the child element set to null.
The query:
Posts.findById(foo).populate('createdBy', {fname:1, lname:1});
Incorrectly returns a post with post.createdBy = null. Omitting the fields parameter of fame, lname, somehow makes it work again with post.createdBy returning the full object.
Following are some excerpts from the code - though I'm not sure those are the right places to look.
collections.js
this.find = function (conditions, options, callback) {
var results;
var models = db[name];
if (!_.isEmpty(conditions)) {
results = utils.findModelQuery(models, conditions);
} else {
results = utils.objectToArray(utils.cloneItems(models));
}
results = filter.applyOptions(options, results);
if (results.name === 'MongoError') {
callback(results);
} else {
var result = {
toArray: function (callback) {
callback(null, results);
}
};
callback(null, result);
}
};
util.js
function cloneItems(items) {
var clones = {};
for (var item in items) {
clones[item] = cloneItem(items[item]);
}
return clones;
}
function cloneItem(item) {
return _.cloneDeep(item, function(value) {
// Do not clone items that are ObjectId objects as _.clone mangles them
if (value instanceof ObjectId) {
return new ObjectId(value.toString());
}
});
}
And here's a conversation about the issue
https://github.com/mccormicka/Mockgoose/pull/90

CRM 2011 Retrieving lookup

I'm new in CRM development. I know a basic thing like "best practice for crm 2011"
I wanna understand now how to work with lookup fields. And I think I chose the easiest way for my self.
I have an costum entity "contract" it has 5 more field, 2 of these are lookups.
First lookup (agl_contractId) - it is a link by it self
Second lookup (agl_ClientId) - link to Client.
What do I need?
When I choose fill First lookup (agl_contractId), script should find in this contract a Client and copy-past it to current form.
I've done script but it isn't work... (((
function GetAccountFromContract()
{
XrmServiceToolkit.Rest.Retrieve(Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue(),
'agl_osnovnoy_dogovoridSet',
null,null,
function (result) {
var Id = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
if (result.Id != null) {
var LookupData = new Array();
var LookupItem = new Object();
var lookuptextvalue = lookupvalue[0].name;
var lookupid = lookupvalue[0].id;
var lokupType = lookupvalue[0].entityType;
alert(lookupvalue);
alert(lookupData);
Xrm.Page.getAttribute("agl_accountid").setValue(lookupData);
}
},
function (error) {
equal(true, false, error.message);
},
false
);
}
If I understand you well: When you select Contract in agl_osnovnoy_dogovorid field, you want to pull Client property from that Contract and put it in agl_accountid field?
If that is right:
First, get Id of selected Contract (from agl_osnovnoy_dogovorid field)
var selectedContract = new Array();
selectedContract = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
{
var guidSelectedContract = selectedContract[0].id;
//var name = selectedContract[0].name;
//var entType = selectedContract[0].entityType;
}
Second, retrieve Client from agl_osnovnoy_dogovorid. Your oData query will be like:
http://crmserver/org/XRMServices/2011/OrganizationData.svc/ContractSet(guid'" + guidSelectedContract + "')/CustomerId
(In example I'm using CustomerId field. For your case enter Schema Name of Client field).
Now, execute query and put result into agl_accountid field:
$.getJSON(
Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/ContractSet(guid'" + guidSelectedContract + "')/CustomerId",
function(data){
if(data.d.CustomerId != null && data.d.CustomerId.Id != null && data.d.CustomerId.Id != "undefined")
{
//set agl_accountid field
Xrm.Page.getAttribute("agl_accountid").setValue([{id:data.d.CustomerId.Id, name:data.d.CustomerId.Name, typename:data.d.CustomerId.LogicalName}]);
}
});
Your using REST to retrieve data but also using FetchXml example to setup the agl_accoutid lookup.
Also some of the conditions are not clear … anyway … I’ve incorporated the change to your original post.
function GetAccountFromContract()
{
var aodLookupValue = Xrm.Page.getAttribute("agl_osnovnoy_dogovorid").getValue();
if (!aodLookupValue) return;
XrmServiceToolkit.Rest.Retrieve( aodLookupValue[0].id ,
'agl_osnovnoy_dogovoridSet', null,null,
function (result) {
var customer = result.d["your attribute name"];
if (customer) {
var LookupData = new Array();
var LookupItem = new Object();
var lookuptextvalue = customer.Name;
var lookupid = customer.Id;
var lokupType = customer.LogicalName;
alert(lookupvalue);
alert(lookupData);
Xrm.Page.getAttribute("agl_accountid").setValue(lookupData);
}
},
function (error) {
equal(true, false, error.message);
}, false );
}

Resources