Node mongo bulk update, get the updated columns name - node.js

i have a bulk updation on mongodb in nodejs
i am facing the following scenario
user can update 20-30 fields at once, possibly he dont update all, he may change 1 or 2 or 5 or maybe all, i want to know exactly which are fields ie, whose value have be over-written with new values.
i need to know this because every field carry a weightage and if they update a particular field then i have to re-calculate the weightage of all the columns and assign it to the user
for example if
User.update({_id: user_id},{ $set : {key1:value,key2:value,key3:value... }})
now suppose key3 is over-written but key1 & key2 remains as it is,
so i want to know that key3 has been over-written.
how can i do that ?

if you use findOneAndUpdate function for updating, it's possible to retrieve document before updating, with that retrieved value you then can compare it with given document to find out witch fields has been updated.
The update function will be like this:
db.collection("Collection Name").findOneAndUpdate({"Find Query"},
{$set: {"Update Query"}},
{returnOriginal: true},
(err, res) => {
//... Some codes for comparing docs
});
The "returnOriginal" option makes the query to return updated document before update operation.

Related

Overwriting some fields within a nested array of a mongoDB collection

I have an array of data that needs to be used to overwrite certain fields in a collection named "Players"
The structure of a Player looks like so:
The array of data that needs to go into documents in the Player collection is being passed into a controller function that looks like this:
exports.updateManyStats = (req, res) => {
console.log("updateManyStats API");
console.log(req.body.season);
console.log(req.body.stats);
Player.updateMany();
};
The console.logs looks like this:
What I need to do is overwrite the Players document fields goals , assists and pim for each person in the array (email is unique) where the season is whatever req.body.season is. In this case it is 2020-2021. The rest of the fields, like team, jersey, _id need to be left un-altered.
Question: What is the best way to do this? The only idea I have is to loop through each player and use $set, but that is not efficient. I feel like it might be possible with updateMany(), but not sure how to go about it that way.

How to query field exist some document in firebase

I using firebase, nodejs and i have a question how to query field exist some document.
Example :
Collections : users => document : A with field {
....
is_correct: true
}
document : B with field {
.....
}
In my above example , i have two document in collection users. On document A i have field is_correct: true and on document B field is_correct not exist.
My collection users about 15.000 document and it have 50 document contain field is_correct: true
When i write code look like :
await firestore.collection('users').where('is_correct', '==', true).get();
it can get correct me 50 document. But i don't understand it can using index on field is_correct or not ? And it can query best performance ? I understand firebase can't get document if field undefined. It impart in case ? Please help ? Thanks you
For a simple query like
firestore.collection('users').where('is_correct', '==', true)
you don't need to configure any index, Firestore does it automatically.
As you mentioned, only documents where the given field exists can match the query.
And this is the case also for Not-equal (!=) and not-in queries: they exclude documents where the given field does not exist, as explained in the documentation.
Also, note that a field exists when it's set to any value, including an empty string (""), null, and NaN (not a number).
So, in conclusion, if you want to query for documents where is_correct is not true, you need to create this field in these documents with a value different than true.

Mongodb how to aggregate more different fields of the same collection with the same request?

another shock with express and mongodb, I would like to aggregate more different fields of the same collection with the same request called aggregate4, together with another request called query (query is full text) (aggregate is regex) but I'm having difficulty, example:
collection.aggregate([{$match:{
$text: {$search: '\"' + query.split(' ').join('\" \"') + '\"'}, //full text req.query
name_lower: new RegExp('^'+ aggregate1), // req.query.aggregate1 ok
surname_lower: new RegExp('^'+ aggregate2),//req.query.aggregate2 ok
sex_lower: new RegExp( aggregate3),//req.query.aggregate3 ok
$or:[{
note4_lower: new RegExp(aggregate4), //problem //req.query.aggregate4
note5_lower: new RegExp(aggregate4),//problem //req.query.aggregate4
}]
}]).limit(myLimit)
.toArray(function.......
note that note4_lower and note5_lower share the same request (aggregate4), unfortunately I only receive the note4.lower column in this case or note5.lower reversing the or and.
I tried to do the same with two $OR one for note4_lower and one for note5.lower, I also tried with collection.find as well as aggregate but nothing, or I receive only the "COLUMN" note4.lower or only the "COLUMN" note5.lower ... In both columns there are NULL fields (so either the field has note4.lower or note5.lower)
can someone help me?
I hope I explained myself well, thanks!

Is there a way to add an incrementing id in one statement in MongoDB?

So I got a small database, It's not going to grow much more and I'm trying to get one document from the db in an API that I implemented in python so that with a given document Id I retrieve the document in the db. However, I find it a little hard to put the user to write a random number from the db. All I require is a function that modifies each document by setting an id field and to Auto-Increment. As I said, it's not going to grow that much and the performance isn't really an issue here.
So far what I've been able to do is this:
var i = 0
db.MyCollection.update({},
{$set : {"new_field":1}},
{upsert:false,
multi:true}
i ++;),
I achieved to set an id field but it sets the same number to each document (the count of every document) So let's say that if the db has 10 docs, it'll set the Id to 10.
Find-and-modify operation returns the document updated (before or after the update depending on returnDocument setting). You can use this with $inc to implement a counter. Ruby example where c is a collection:
irb(main):005:0> c['foo'].insert_one(counter:true,count:1)
=> #<Mongo::Operation::Insert::Result:0x8040 documents=[{"n"=>1, "opTime"=>{"ts"=>#<BSON::Timestamp:0x00005609f260b7e0 #seconds=1594961771, #increment=2>, "t"=>1}, "electionId"=>BSON::ObjectId('7fffffff0000000000000001'), "ok"=>1.0, "$clusterTime"=>{"clusterTime"=>#<BSON::Timestamp:0x00005609f260b538 #seconds=1594961771, #increment=2>, "signature"=>{"hash"=><BSON::Binary:0x8060 type=generic data=0x0000000000000000...>, "keyId"=>0}}, "operationTime"=>#<BSON::Timestamp:0x00005609f260b290 #seconds=1594961771, #increment=2>}]>
irb(main):011:0> c['foo'].find_one_and_update({counter:true},{'$inc':{count:1}})
=> {"_id"=>BSON::ObjectId('5f112f6b2c97a6281f63f575'), "counter"=>true, "count"=>1}
irb(main):012:0> c['foo'].find_one_and_update({counter:true},{'$inc':{count:1}})
=> {"_id"=>BSON::ObjectId('5f112f6b2c97a6281f63f575'), "counter"=>true, "count"=>2}
irb(main):013:0> c['foo'].find_one_and_update({counter:true},{'$inc':{count:1}})
=> {"_id"=>BSON::ObjectId('5f112f6b2c97a6281f63f575'), "counter"=>true, "count"=>3}
irb(main):014:0> c['foo'].find_one_and_update({counter:true},{'$inc':{count:1}})
=> {"_id"=>BSON::ObjectId('5f112f6b2c97a6281f63f575'), "counter"=>true, "count"=>4}
Why not just use this logic? Instead of updating all via one query, just launch multiple queries one by one? Mongo will do it pretty fast, even if you have >1M docs in database (according to your phrase: I got a small database) because pre-builded index on _id field.
this is a javasript code, but I guess, you'll understand the logic of it
let all_documents = db.MyCollection.find({});
for (let i = 0; i < all_documents.length; i++) {
db.MyCollection.update({_id: all_documents[i]._id }, {$set : {"new_field": i}}, {upsert:false})
}

mongodb querying logic mongoose and nodejs

I apologize beforehand if this is a repeat question but i could not find any and i am a beginner.
I am making a filter for documents of db.
lets say I want to query 8 fields of documents written in a object
filter={key1:{lowerlimit: 'value', upperlimit:'value'},
key2:{lowerlimit: 'value', upperlimit:'value'},
key3:{lowerlimit: '', upperlimit:'value'},
key4:{lowerlimit: 'value', upperlimit:''},
key5:[],
key6:['value','value'],
key7:['value','value','value'],
key8:['value']}
now how do i write the logic of query so that the fields whose value is not specified will not get query. if i query all the parameters as they are. no documents will be displayed because 'key5' is empty array and using $in on it will result in no documents.
You'd want to remove the key5 field from your query object when it's empty.
if (!filter.key5.length) {
delete filter.key5;
}

Resources