I'm trying to pass two search requests in single API call But here some times I am getting both requests results and some times getting only one request results. Basically this is my JSON structure in cloudant db:
{
"_id": "123",
"name": "Naveen",
"hoby": "Cricket"
},
{
"_id": "234",
"name": "Varun",
"hoby": "chess"
},
{
"_id": "345",
"name": "Tarun",
"hoby": "Cricket"
},
{
"_id": "456",
"name": "pavan",
"hoby": "chess"
}
Here my requirement would be to get 'hoby' of Cricket 50 members and 'hoby' of Chess 50 members. For that this is how I am trying currently:
doGet: function(request, response) {
var usersState = [];
var names = { "usersState": usersState, "message": "ok" };
if (!myDb) {
response.json({ "message": "Dataabase connection failed" });
return;
}
var queryForCricket = {
"selector": {
"hoby": "Cricket"
},
"fields": [
"_id",
"name",
"hoby"
],
"sort": [],
"limit": 50,
"skip": 0
};
var queryForChess = {
"selector": {
"hoby": "chess",
},
"fields": [
"_id",
"name",
"hoby"
],
"sort": [],
"limit": 50,
"skip": 0
};
async.parallel(
[
myDb.find(queryForCricket, function (err, body) {
if (!err) {
body.docs.forEach(function (doc) {
if (doc)
usersState.push(doc);
});
response.json(names);
}
}),
myDb.find(queryForChess, function (err, body) {
if (!err) {
body.docs.forEach(function (doc) {
if (doc)
usersState.push(doc);
});
}
})
], function (err, results) {
if (err) {
response.send({ "message": "Read operration failed" });
return;
}
});
}
I have written two queries and passing two through Async call but not getting results properly all the time. So is there any optimised way to handle query part and getting results.
The issue here is your final result depends on execution order of both callbacks of your async.parallel
find
functions. When the second find
finishes first you'll get both results but when the first find
finishes first you'll get only results of queryForCricked
query.
To get both results you should collect them in the final callback function and use response.json
there:
...
async.parallel(
[
myDb.find(queryForCricket, function (err, body) {
if (!err) {
body.docs.forEach(function (doc) {
if (doc)
usersState.push(doc);
});
}
}),
myDb.find(queryForChess, function (err, body) {
if (!err) {
body.docs.forEach(function (doc) {
if (doc)
usersState.push(doc);
});
}
})
], function (err, results) {
if (err) {
response.send({ "message": "Read operration failed" });
return;
}
response.json(names);
}
);
...
While collecting data in the shared usersState
array is completely working approach it has flaws. For example, you cannot control the order in which your find
data will be inserted. async.parallel
gives a better way to collect the data from the functions it's running. You can use callback
async.parallel
inserts into each function to collect the data in the final callback:
async.parallel(
[
function (cb) { myDb.find(queryForCricket, cb); },
function (cb) { myDb.find(queryForChess, cb); },
], function (err, results) {
if (err) {
response.send({ "message": "Read operration failed" });
return;
}
// result is an array with data from queries: [crickets.body, chess.body]
results.forEach(function (body) {
body.docs.forEach(function (doc) {
if (doc) usersState.push(doc);
});
});
response.json(names);
}
);
...