How to update records on continues Hierarchy in mongoose? - node.js

I have a record in such a way like below
1)
{
"name":"A",
"parents":[ADMIN],
"childrens":[B,C,D]
}
2)
{
"name":"B",
"parents":[A],
"childrens":[D,K,L]
}
3)
{
"name":"C",
"parents":[B],
"childrens":[K,L]
}
4)
{
"name":"D",
"parents":[C],
"childrens":[L]
}
Here if a add a new record 'E' and will make 'C' as parent ,then the logic is the record 'E' should be added as child to the parent of 'C'i.e for 'B' and at the same time 'E' should also be added to parent of 'B'.This logic is quite confusing when i start to write code and complex too but i achieved up to some extent that i can make 'E' as a child of 'C' and also the parent of 'C' but not further.
My Code:
function (callback) {
var item = {'employee' : employee.manager };
Employeehierarchy.find(item).exec(function (err, employeeparent) {
if (employeeparent && employeeparent.length > 0) {
Employeehierarchy.update(
{ _id: employeeparent[0]._id},
{"$push": { "childrens": employee._id } }
).exec(function (err, managerparent) {
});
callback(err,employeeparent);
} else{
callback(err,employeeparent);
}
}
});
},
//Finding the parent record of the manager in hierarchy
function (employeeparent, callback) {
var item = {'employee' : employeeparent[0].parents };
Employeehierarchy.find(item).exec(function (err, managerparent) {
if (err) {
return res.status(400).send({ message: errorHandler.getErrorMessage(err) });
} else {
if (managerparent && managerparent.length > 0) {console.log(managerparent+'managerparent')
Employeehierarchy.update(
{ _id: managerparent[0]._id},
{"$push": { "childrens": employee._id } }
).exec(function (err, managerparent) {
});
callback(err,managerparent);
} else{
callback(err,managerparent);
}
}
});
}else {
callback();
}

Related

setInterval() is not wotking in azure microsoft

setInterval() is not working in Azure Microsoft. I need a function to do the task every month or week? so what can I do? the code is working without azure but with azure not working?
nodejs code :
setInterval(async function check() {
if ((date.getDate() == 8) && (date.getHours() == 18) && (date.getMinutes() == 39) && (date.getSeconds() == 00)) {
await Drawings.find({}).then((data) => {
data.sort(function (a, b) {
return b.stars - a.stars;
})
if (data == null) {
return;
}
AllDrawings.updateMany({
"potmCurrentWinner": true
}, {
$set: {
"potmCurrentWinner": false
}
}, async function (err) {
if (err) {
return;
}
// move the drawing to potm
await AllDrawings.updateOne({
"DrawingName": data[0]['DrawingName']
}, {
$set: {
"potmCurrentWinner": true,
"potm": true
}
}, async function (err) {
//move file
await User.updateOne({
userName: data[0].Drawer
}, {
$inc: {
stars: 25
}
})
console.log("done3");
await User.updateOne({
userName: data[0].Drawer
}, {
$inc: {
drawingOfTheMonth: 1
}
});
//delete all drawwing the u give star
await User.updateMany({}, {
$set: {
drawingThatGotYourStar: []
}
});
await Drawings.deleteMany({});
console.log("done4");
});
});
})
you have missing code here, the brackets from the initial condition and the closing parenthesis for the setInterval function call

Need help for mongoose .find()

I need the result of Mongoose's find().exec in the below format. Is it possible to format the result like that?
var myFunction = function(foo, bar) {
model1.find({ elem: foo, elem2: bar }).exec(function(err, data) {
if (err) {
/* ... */
}
if (data) {
if (data.passed == true) {
return { passed: true, point: data.point };
} else {
return { passed: false, point: data.point };
}
} else {
return { passed: false, point: "not tried" };
}
});
};
object = {
...
someitem: array.map(function(arr) {
return {
_id: program._id,
title: program.title,
slug: program.slug,
status: myFunction(arr._id, arr._id2) /* Like This */
};
});
...
}
and excuse me for My bad english :D
You have to return promise from the function in order to get the values which are coming form mongoose query.So change your function to be:
var myFunction = function(foo,bar) {
return new Promise(function(resolve, reject){
model1.find({elem : foo, elem2 : bar}).exec(function (err, data){
if(err){
/* Blablabla*/
reject(err);
}
if(data){
if(data.passed == true){
resolve({passed:true, point:data.point});
} else {
resolve({passed:false, point:data.point});
}
} else {
resolve({passed:false, point:'not tried});
}
});
});
}
Than if you want to call the function and get the value you have to do like:
let promises, obj_elem = [];
for(let i =0;i < array.length;i++){
promises.push(myFunction(array[i]._id, array[i]. _id2));
}
/* You can't do it sync manner so you have to use some kind of async process */
Promise.all(promises).then((result)=>{
for(let i =0;i < result.length;i++){
obj_elem.push({
_id: program._id,
title: program.title,
slug: program.slug,
status: result[i].passed
});
}
console.log(obj_elem); //here you will have values you want
});

MongoDB, increment field with condition

Is it possible, using mongoose middleware, to increment two fields one with a condition and the other without? In this case i want to increment "stats.ratings" by one, if the user inserts an input greater than 0, else increment zero.
"stats.answered" always increments one
See code below
module.exports.updateStats = function (req, res) {
var rating = parseInt(req.body.rating, 10);
var wasRated;
if (rating > 0) {
wasRated = true;
} else wasRated = false
Collection.findOneAndUpdate({
_id: req.body._id
}, {
$cond: {
if: wasRated,
then: {
$inc: {
"stats.answered": 1,
"stats.ratings": 1
}
},
else: {
$inc: {
"stats.answered": 1,
"stats.ratings": 0
}
}
}
},
function (err, doc) {
if (err)
throw err;
res.status(200);
})
}
What you can do is this:
// define the default case
var update = {
$inc: {
"stats.answered": 1
}
};
if(parseInt(req.body.rating, 10) > 0) {
// override default in some cases
update = {
$inc: {
"stats.answered": 1,
"stats.ratings": 1
}
}
}
and then
Collection.findOneAndUpdate({
_id: req.body._id
}, update,
function (err, doc) {
if (err)
throw err;
res.status(200);
})
}

returning Mongoose query result from Async call

I'm working on a problem where I need to query the db for an instance of a Voter, and use that instance to update an Election, returning to the original function whether that update was successful or not. My code currently looks like this:
function addCandidatesToElection(req, res) {
let electionName = req.body.electionName;
let candidates = req.body.candidates;
let addedCandidatesSucessfully = true;
for(let i=0; i<candidates.length; i++) {
addedCandidatesSucessfully = _addCandidateToElection(electionName, candidates[i]);
console.log("added candidates sucessfully:" + addedCandidatesSucessfully);
}
if(addedCandidatesSucessfully) {
res.send("createElection success");
} else {
res.send("createElection fail");
}
}
which calls this function:
function _addCandidateToElection(electionName, candidateName) {
async.parallel(
{
voter: function(callback) {
Voter.findOne({ 'name' : candidateName }, function(err,voter) {
callback(err, voter);
});
}
},
function(e, r) {
if(r.voter === null){
return 'Voter not found';
} else {
Election.findOneAndUpdate(
{'name': electionName },
{$push: { candidates: r.voter }},
{new: true},
function(err, election) {
if(err){ return err; }
return (election) ? true : false;
});
}
}
);
}
I've already tried printing out the Voter instance(r.voter) to check if it exists (it does), and also printing out the election object returned by the mongoose call, which also works. However, I'm getting a null value in the
addedCandidatesSucessfully = _addCandidateToElection(electionName, candidates[i]);
line, regardless of the result of the call. I think it has to do with the mongoose call returning a local value which is never returned to the function that called _addCandidateToElection, but I don't know how I should return that. I've tried putting control flags such as
let foundAndUpdatedElection = false;
on the first line of _addCandidateToElection and updating it inside the Mongoose query's callback, but apparently it doesn't change.
How should I return the result of the query to the addCandidatesToElection function?
You should probably 'promisify' your code to help you better deal with the asynchronous nature of js. Try the following instead of your example:
function findVoter(candidateName) {
return new Promise(function(resolve, reject) {
Voter.findOne({ 'name' : candidateName }, function(err,voter) {
if(error) {
reject(error);
} else {
resolve(voter);
}
});
});
}
function addCandidateToElection(electionName, candidateName) {
return findVoter(candidateName).then(function(voter) {
return new Promise(function(resolve, reject) {
Election.findOneAndUpdate(
{'name': electionName },
{$push: { candidates: voter }},
{new: true},
function(err, election) {
if (err) {
reject(err);
} else {
resolve(!!election);
}
});
});
}
function addCandidatesToElection(req, res) {
let electionName = req.body.electionName;
let candidates = req.body.candidates;
let addedCandidatesSucessfully = true;
let candidatePromiseArray = [];
for(let i=0; i<candidates.length; i++) {
candidatePromiseArray.push(addCandidateToElection(electionName, candidates[i]));
}
Promise.all(candidatePromiseArray)
.then(function(results) {
console.log(results);
res.send('create election success');
})
.catch(function(error) {
console.error(error);
res.send('failed');
});
}
You will also no longer need to use the async library because promises are now native in ES6

How can i have auto-increment field in nedb?

I want to have exactly auto-increment field like relational or objective databases, so i need an integer _id field with automatically set field value, value should be one more last record _id value like this:
data:
{_id:1,name"foo"}
{_id:2,name"bar"}
remove last record:
{_id:1,name"foo"}
add new record:
{_id:1,name"foo"}
{_id:3,name"newbar"}
I added a function to my datastore and calculate maximum of _id and plus 1 max(_id)+1 and set as field value, but there is problem here:
When we use auto-increment field in relational databases, it works like i said and after you remove last record it reserved a deleted record number and new inserted records continue increment but in my way its says the _id of removed record for new record.
My code is:
var Datastore = require('nedb'),
localDb = new Datastore({
filename: __dirname + '/dbFilePath.db',
autoload: true
});
localDb.getMax = function(fieldName, onFind){
db.find({}).sort({_id:-1}).limit(1).exec(function (err, docs) {onFind && onFind(err, docs['_id']);});
return localDb;
}
localDb.insertAutoId = function(data, onAdd){
var newIndex = 0;
localDb.getMax(function (err, maxValue) {
newIndex = maxValue+1;
if(!data["_id"])
data["_id"] = newIndex;
localDb.insert(data, function (err, newDoc) {
onAdd && onAdd(err, newDoc);
});
});
return localDb;
}
An improved answer for nedb would be:
db.getAutoincrementId = function (cb) {
this.update(
{ _id: '__autoid__' },
{ $inc: { seq: 1 } },
{ upsert: true, returnUpdatedDocs: true },
function (err, affected, autoid) {
cb && cb(err, autoid.seq);
}
);
return this;
};
Which is equivalent to the mongodb way:
db.getAutoincrementId = function (cb) {
this.findAndModify({
query: { _id: '__autoid__' },
update: { $inc: { seq: 1 } },
new: true
}
function (err, autoid) {
cb && cb(err, autoid.seq);
}
);
return this;
};
You can store the last value of the index in the database. Something like this:
var Datastore = require('nedb');
var db = new Datastore({
filename: __dirname + '/dbFilePath.db',
autoload: true
});
// Initialize the initial index value
// (if it already exists in the database, it is not overwritten)
db.insert({_id: '__autoid__', value: -1});
db.getAutoId = function(onFind) {
db.findOne( { _id: '__autoid__' }, function(err, doc) {
if (err) {
onFind && onFind(err)
} else {
// Update and returns the index value
db.update({ _id: '__autoid__'}, { $set: {value: ++doc.value} }, {},
function(err, count) {
onFind && onFind(err, doc.value);
});
}
});
return db;
}
I do not know if it will be useful for you anymore I use a database to store the next ids, inspired in the mysql system. Who always reserves the next id.
So I created a function that verifies if there is an id to the db, if it does not, it add with the value "1", and when it updates it looks for and if it exists and it performs the sequence.
This gave me full control over my ids.
The schema would be:
{
name: nameDb,
nextId: itemID
}
If you want you can create functions for updating documents, versioning, etc.
example:
db.autoincrement = new Datastore({filename: 'data/autoincrement.db', autoload: true});
function getUniqueId(nameDb, cb) {
db.autoincrement.findOne({name: nameDb}, function (err, doc) {
if (err) {
throw err;
} else {
if (doc) {
const itemID = doc.nextId + 1;
db.autoincrement.update({name: nameDb}, {
name: nameDb,
nextId: itemID
}, {}, function (err, numReplaced) {
db.autoincrement.persistence.compactDatafile();
if (err) {
throw err;
} else {
// console.log(numReplaced);
}
cb(doc.nextId);
});
} else {
const data = {
name: nameDb,
nextId: 2
};
db.autoincrement.insert(data, function (err, newDoc) {
if (err) {
throw err;
} else {
// console.log(newDoc);
}
cb(1);
});
}
}
});
}
insert new document example:
function insert(req, cb) {
getUniqueId("testdb", function (uniqueId) {
data.itemId = uniqueId;
db.testdb.insert(data, function (err, newDoc) {
if (err) {
cb({error: '1', message: 'error#2'});
throw err;
}
cb({error: '0', message: 'Item add'});
});
});
}

Resources