I am working with loopback mongodb. Here is my query
const counter = await db.collection("counters").findOneAndUpdate(
{ prefix: "C" },
{ $inc: { sequence_value: 1 } },
{ projection: { "sequence_value" : 1 }, returnNewDocument: true }
);
It returns
{
lastErrorObject: { n: 1, updatedExisting: true },
value: { _id: 'customerid', sequence_value: 590 },
ok: 1
}
So I have two questions here.
Why it is not returning new document here? I am always getting old sequence_value.
What is lastErrorobject and ok? I only need the document object like this { _id: 'customerid', sequence_value: 590 }
const getCounter = () => new Promise((resolve, reject) => {
db.collection("counters").findOneAndUpdate(
{ prefix: "C" },
{ $inc: { sequence_value: 1 } },
{ projection: { "sequence_value" : 1 }, returnNewDocument: true },
(err, result) => {
if (err) { return reject(err); }
resolve(result);
},
);
});
const counter = await getCounter();
Related
In the function below, if the user, topic and subtopic do not exist, a new testRecord is inserted into the testRecords array of the User collection. This works fine. On the other hand, if the combination of the user, topic and subtopic exist, only the scores array of testRecords is to be populated with the new scores. This is not working. The code segment that begins: if(existingTopicSubtopic) is the part that is not working.
exports.updateUserTestRecord = async (req, res) => {
console.log('req.body', req.body)
const {topicName, subtopicName, rightAnswers, wrongAnswers, date} = req.body;
const {
userId
} = jwt.verify(req.headers.authorization, process.env.JWT_SECRET);
const existingTopicSubtopic = await User.findOne(
{
_id: userId,
'testRecords.topic': topicName,
'testRecords.subtopic': subtopicName
},
)
let user;
if(existingTopicSubtopic) {
console.log('EXISTING USER')
user = await User.findOneAndUpdate(
{
_id: userId,
'testRecords.topic': topicName,
'testRecords.subtopic': subtopicName
},
{
$addToSet : {
testRecords : [
{
'scores.$.rightAnswers': rightAnswers,
'scores.$.wrongAnswers': wrongAnswers,
'scores.$.date': date,
}
]
}
},
)
} else {
console.log('NOT EXISTING USER')
user = await User.findOneAndUpdate(
{
_id: userId,
},
{
$addToSet : {
testRecords : [
{
topic: topicName,
subtopic: subtopicName,
scores: [
{
rightAnswers,
wrongAnswers,
date,
}
]
}
]
}
},
)
}
}
For inner array operation, we need to use $[identifier] like $[element]. In your case:
if (existingTopicSubtopic) {
await User.findOneAndUpdate(
{
_id: userId,
"testRecords.topic": topicName,
"testRecords.subtopic": subtopicName,
},
{
$addToSet: {
"testRecords.$[element].scores": {
rightAnswers: rightAnswers,
wrongAnswers: wrongAnswers,
date,
},
},
},
{
arrayFilters: [
{
"element.topic": topicName,
"element.subtopic": subtopicName,
},
],
}
);
} else {
await User.findOneAndUpdate(
{
_id: userId,
},
{
$addToSet: {
testRecords: {
topic: topicName,
subtopic: subtopicName,
scores: [
{
rightAnswers,
wrongAnswers,
date,
},
],
},
},
}
);
}
I have a mongoDB collection which I use with a mongoose Schema :
const balanceSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId, ref: 'user'
},
incomes: { Number },
fees: { Number },
},
{ strict: false })
I use the strict mode to false, so I can push any 'key' I want with its value.
I would like to delete just one of the "incomes" category, but I can't specify the line because there is no 'defined key'.
Here is an exemple of the data inside :
{
"_id": {
"$oid": "60c763df3d260204865d2069"
},
"incomes": {
"income1": 1300,
"anyKeyNameIWant": 400
},
"fees": {
"charge1": 29,
"charge2": 29,
"chargetest": 29,
"charge7": 29
},
"__v": 0,
}
I tried this, but no success :
module.exports.deleteOneBalance = (req, res) => {
let data = req.body
if (!ObjectID.isValid(req.params.id))
return res.status(400).send('ID unknown : ' + req.params.id);
BalanceModel.update(
{ _id: req.params.id },
{
$unset: { "incomes.salairetest": "400" }
}), (err, docs) => {
if (!err) res.send('Deleted. ' + data)
else console.log('Error : ' + err)
}
}
Any idea ?
There are several ways to delete fields with dynamic field names.
One solution is this one:
var unset = {};
unset["incomes." + "anyKeyNameIWant"] = null;
db.balanceModel.updateOne({ _id: req.params.id }, { $unset: unset })
Or you can use an aggregation pipelinie like this:
db.balanceModel.updateOne(
{ _id: req.params.id },
[
{ $set: { incomes: { $objectToArray: "$incomes" } } },
{ $set: { incomes: { $filter: { input: "$incomes", cond: { $ne: ["$$this.k", "anyKeyNameIWant"] } } } } },
{ $set: { incomes: { $arrayToObject: "$incomes" } } }
]
)
If you want to remove/unset specific value/(s) from the documents then you have to provide the complete path of that key.
Let's take an example if you want to remove anyKeyNameIWant then your path will be incomes.anyKeyNameIWant and the update query will be like this
db.sample.update(
{
_id: ObjectId("60c763df3d260204865d2069")},
{
$unset: {"incomes.anyKeyNameIWant":""}
})
In your code, you are passing an object having the key incomes in $unset which will remove the complete incomes key from the document
Here is the link to the official document in case you want more details $unset
I want to stream a MongoDB query in NodeJS because, in Angular, i have a chart and i want to update the data without making a refresh.
So far, this is my code (NodeJS):
exports.gettoday = function (request, response) {
db.collection("nifi5", function (err, collection) {
collection
.aggregate([
{
$group: {
_id: {
minute: {
$minute: { $dateFromString: { dateString: "$created_at" } },
},
hour: {
$hour: { $dateFromString: { dateString: "$created_at" } },
},
day: {
$dayOfMonth: { $dateFromString: { dateString: "$created_at" } },
},
month: {
$month: { $dateFromString: { dateString: "$created_at" } },
},
year: {
$year: { $dateFromString: { dateString: "$created_at" } },
},
},
avg: { $avg: "$value_temperature" },
},
},
])
.stream()
.toArray(function (err, items) {
if (err) {
response.statusMessage = {
devMessage: err,
clientMessage: "Unexpected error, try again latter",
};
response.send(response.statusMessage).end();
}
let tarray = { labels: [], data: [] };
items.forEach((element) => {
element.date = element._id.hour + ":" + element._id.minute;
element.avg = Math.round(element.avg * 100) / 100;
});
items.sort(function (a, b) {
return a.date < b.date ? -1 : 1;
});
items.forEach((element) => {
tarray.labels.push(element.date);
tarray.data.push(element.avg);
});
return response.json(tarray);
});
});
};
Angular:
gettodaydata(): Observable<any> {
return this.http.get(`${environment.baseURL}gettoday`).subscribe((data) => {
this.data_line.push(...data.data);
this.labels_line.push(...data.labels);
this.isLineChartLoading = false;
});
}
Can u please help me streaming this controller and fetch the data in Angular to update my chart when new data comes do my database ?
Thank you all!
You should give a try to socket.io, it creates a persistent connection and responds to events in real time.
I am trying to convert this oracle query to Mongoose equivalent. I am trying to do it using findOneAndUpdate, but don`t know how to convert this NVL thing.
here is my query
Update Authentication
Set Datetime = Sysdate,
Isactive = 'Y',
Version = '1.0.0',
Firstlogin = Nvl(Firstlogin, Sysdate),
Lastlogin = Sysdate
This is what i have tried. I have used $cond and inside it ifNull, but its not working, Also used $cond and then and if condition to check for null, bot no luck at all.
function createOrUpdate() {
let filter = { count: { $lt: 4 } };
let options = { upsert: true, returnOriginal: false, multi: true };
let userID = "asdfasdf"
let testUser = {
userId: userID,
userNick: "user.nickName",
reqTime: 1,
}
let update = {
$inc: { count: 1 }, $addToSet: {
"users": {
$each: [testUser],
}
},
$cond: [
{
$ifNull: ['$roomName', true], $set: {
roomName: "1112"
},
$set: {
roomName: "1112"
}
},
]
};
// { },
// let update = {
// $cond: {
// if: {
// $or:[{$eq: ["roomName",null]},{$eq: ["roomName",""]}]
// },
// then: {
// $set: {
// roomName: "varxy"
// }
// },
// else: {
// $set: {
// roomName: "roomName"
// }
// }
// },
// $inc: { count: 1 },
// "$set": { "users":{ "userId": userID, "user": testUser } }
// }
ModelRooms.findOneAndUpdate(
filter,
update,
options, function (err, doc) {
if (err) {
logger.error(`Error:: ${err}`);
}
else {
logger.info(`User added to room`);
}
});
}
I am using node is along with mongoose.while I am executing this query its taking 30+ sec for execution
I think its due to looping how to improve the performance can anyone guide me I am new to mongoose
companies
.findById(
{
_id: companyProfile,
},
function(err, company) {
if (err) {
return res.status(400).send({
message: "Some Error Occured!",
});
} else {
var responseJson = [];
company.ambulances.forEach(function(doc) {
Gps.find({
$and: [
{
device: doc.deviceId,
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
],
})
.sort({
$natural: -1,
})
.limit(1)
.exec(function(err, gpsLocations) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
} else {
responseJson.push({
gps: gpsLocations,
});
if (
company.ambulances.length === responseJson.length
) {
res.json(responseJson);
}
}
});
});
}
},
)
.populate("ambulances");
Well, first try to convert the callbacks to Promises, in order the code to be easier to understand. Now about the speed, you can match all the Gps objects using the $in operator. So the result will be something like that.
try {
const company = await companies.findById({ _id: companyProfile });
const gpsLocations = await Gps.find({
$and: [
{
device: { $in: company.ambulances },
},
{
longitude: {
$exists: true,
$ne: "",
},
},
{
locationDate: {
$exists: true,
$ne: "",
},
},
{
latitude: {
$exists: true,
$ne: "",
},
},
]
}).sort({
$natural: -1,
}).populate("ambulances");
return res.json(gpsLocations.map(gpsLocation => ({
gps: gpsLocation,
})));
} catch(e) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err),
});
}