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`);
}
});
}
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 have a document in mongodb. The document in This function is able to find the document and it returns it but I can't for the life of me get this function to update the count field by 1. The current document in mongodb if it helps is:
{
_id: 60c5e4c3fba7edd232cf57e7,
counterName: 'give_me_the_count',
count: 1,
updatedAt: 2021-06-13T11:47:02.575Z
}
The code is returning the original document to updatedCounter. But updatedCounter.count is undefined.
async function updateAndReturnNewCount() {
let doc = await Counter.findOne({ counterName : "give_me_the_count" })
var count = doc.count
let updatedCounter = await Counter.findOneAndUpdate({ counterName : "give_me_the_count" },
{ $inc: {"count" : 1 }},
{ new: true,
useFindAndModify: false },
function(err, doc) {
if (err) { console.log(err)}
else {console.log("success")}
}
);
console.log("updateAndReturnNewCount fired")
return updatedCounter.count
}
Your query is incorrect for the operation you wanted to do.
Try this one:
await Counter.aggregate([
{
$match: {
counterName : "give_me_the_count"
}
},
{
$set: {
"count": {
$add: [ "$count", 1 ] // Increment $count by one
}
}
}
])
Playground
Edit:
Usage:
async function updateAndReturnNewCount() {
let doc = await Counter.findOne({ counterName : "give_me_the_count" })
var count = doc.count
let updatedCounter = await Counter.aggregate([
{
$match: {
counterName : "give_me_the_count"
}
},
{
$set: {
"count": {
$add: [ "$count", 1 ] // Increment $count by one
}
}
}
])
console.log("updateAndReturnNewCount fired");
console.log(updatedCounter);
return count++;
}
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();
I'm querying my MongoDB database and don't understand why I am getting an aggregator cursor as a result when I expect to be returned a single number. Maybe I need to get something from the cursor object? Just can't figure out what.
module.exports = CalculateAvg = async collection => {
try {
// const count = await collection.countDocuments({ word: "Hello" });
// console.log(count) // logs 140, which shows that it is accessing the db correctly
const cursor = await collection.aggregate([
{ $match: { word: "Hello" } },
{
$group: {
_id: null,
mean: {
$avg: "$value" // in the dataset, each doc has a value field which equals a number
}
}
}
]);
console.log(cursor) // logs a large AggregationCursor object, rather than a number
} catch (err) {
console.log(err);
}
};
It's because aggregate return value is aggregateCursor, I recommend checking the Mongo's Nodejs driver types file whenever you're not sure whats the return value or the parameter value for any of these functions is.
You want to use cursor toArray like so:
const cursor = await collection.aggregate([
{ $match: { word: "Hello" } },
{
$group: {
_id: null,
mean: {
$avg: "$value" // in the dataset, each doc has a value field which equals a number
}
}
}
]).toArray();
You should use next() method... For Example
const pipeline = [{
$facet: {
total: [{
$count: 'createdAt'
}],
data: [{
$addFields: {
_id: '$_id'
}
}],
},
},
{
$unwind: '$total'
},
{
$project: {
data: {
$slice: ['$data', skip, {$ifNull: [limit,'$total.createdAt']} ]
},
meta: {
total: '$total.createdAt',
limit: {
$literal: limit
},
page: {
$literal: ((skip/limit) + 1)
},
pages: {
$ceil: {
$divide: ['$total.createdAt', limit]
}
}
}
}
}];
const document = await collection.aggregate(pipeline);
const yourData = await document.next();