prepend email addresses with string in mongodb collection using mongoose - mongodb

My collection has a column named email which contains email address. Now I need to update all these email addresses, appending _01 at the end of the email (before #). Basically if the email is ipman#gmail.com, it should be converted to ipman_01#gmail.com. I know we can use updateMany to update multiple documents using mongoose, but to achieve what I need, I believe I need to use some kind of regex too?

Please try this :
let emails = ['ipman#gmail.com', 'ipman2#gmail.com']
let bulkArr = [];
for (const i of emails) {
let newEmail = i.split("#");
newEmail = newEmail[0] + '_01' + '#' + newEmail[1]
bulkArr.push({
updateOne: {
"filter": { email : i },
"update": { '$set': { email : newEmail } }
}
})
}
let updateResult = await MongooseModel.bulkWrite( bulkArr, { ordered : false })
/** Passing { ordered : false } to make sure update op doesn't fail if updating one document in the middle fails, Also bulkWrite returns write result check documentation for more info */
console.log('matchedCount ::', updateResult.matchedCount, 'modifiedCount ::', updateResult.modifiedCount)
Ref : .bulkWrite()

Related

MongoDB / Discord.js - checking existence of a collection

I make a discord bot with MongoDB and I create a command to modify an article from my bot’s shop.
Before modifying a particular article, it must already be found in the database. Is it possible to find out if the name typed in the command exists in the database? If it does not exist, it returns an error message.
if(!oldName) return message.channel.send('<:croix:704272420873306165> You must indicate the name of your article')
if(!newName) return message.channel.send('<:croix:704272420873306165> You must indicate the new name for your article')
if() return message.channel.send('<:croix:704272420873306165> The name of the item doesn\'t exist.')
await serverDB.set(message.guild.id, { $rename: { [ 'modules.SHOPECO.' + oldName ] : 'modules.SHOPECO.' + newName } })
await serverDB.set(message.guild.id, { $set: { [ 'modules.SHOPECO.' + `${newName}.NAME` ] : newName } })
message.channel.send("Good !")
You can use Model.findOne() for that. The reason why I'm not suggesting Model.exists() anymore is because, according to the comments on this answer, you are trying to query multiple conditions and you can keep it simple using findOne()
ArticleModel.findOne({ id: message.guild.id }, (err, res) => {
if (res.modules.SHOPECO.includes(args[0]) return message.reply('that article already exists!')
})

Updating a field within a document in MongoDB / Meteor

I am attempting to update a few different fields within a document in a collection, and seem to be having some trouble. I don't seem to be able to access any of the specific attributes I am looking to set (which are subject, standard, price). Would anyone be able to help? Here is my code so far, and the newAttributes don't seem to be making it there.
I have confirmed the doc._id is correctly populating.
Template.AppAdmin.events({
'click #editApp': function() {
let newAttributes = {};
let subject = $('#subject').val();
let standard = $('#standard').val();
let price = $('#price').val();
console.log(subject);
console.log(standard);
console.log(price);
newAttributes = { subject: subject, standard: standard, price: price };
var doc = Session.get('appId');
console.log(doc);
console.log(newAttributes);
Apps.update(doc._id, { $set: { newAttributes }});
console.log('app has been updated!');
}
});
Thank you.
UPDATE of course I figured it out, I wasn't correctly grabbing the document by ID...
This worked:
Apps.update({_id: doc}, { $set: newAttributes });
You need to remove the braces around newAttributes, because newAttributes is already an object. So your updated code will be like
Apps.update(doc._id, { $set: newAttributes });
Or
Apps.update({'_id':doc._id}, { $set: newAttributes });

Update nested array object (put request)

I have an array inside a document of a collection called pown.
{
_id: 123..,
name: pupies,
pups:[ {name: pup1, location: somewhere}, {name: pup2, ...}]
}
Now a user using my rest-service sends the entire first entry as put request:
{name: pup1, location: inTown}
After that I want to update this element in my database.
Therefore I tried this:
var updatedPup = req.body;
var searchQuery = {
_id : 123...,
pups : { name : req.body.name }
}
var updateQuery = {
$set: {'pups': updatedPup }
}
db.pown.update(searchQuery, updateQuery, function(err, data){ ... }
Unfortunately it is not updating anythig.
Does anyone know how to update an entire array-element?
As Neil pointed, you need to be acquainted with the dot notation(used to select the fields) and the positional operator $ (used to select a particular element in an array i.e the element matched in the original search query). If you want to replace the whole element in the array
var updateQuery= {
"$set":{"pups.$": updatedPup}
}
If you only need to change the location,
var updateQuery= {
"$set":{"pups.$.location": updatedPup.location}
}
The problem here is that the selection in your query actually wants to update an embedded array element in your document. The first thing is that you want to use "dot notation" instead, and then you also want the positional $ modifier to select the correct element:
db.pown.update(
{ "pups.name": req.body.name },
{ "$set": { "pups.$.locatation": req.body.location }
)
That would be the nice way to do things. Mostly because you really only want to modify the "location" property of the sub-document. So that is how you express that.

How should you query a collection via nested arrays in mongodb (Meteor)?

I'm dont think that this is a Meteor specific question, but rather around mongo and building mongo queries.
If I have the following structure,
{
username : someName,
contacts : [
{
userid : asdfae33rtqqxxx,
name : contactName,
status : friend
}
{
userid : asdfae33rtqqxxx,
name : anotherName,
status : pending
}
{
userid : asdfae33rtqqxxx,
name : contactName,
status : blocked
}
]
}
How could I pass in values from this array into a query against the users collection, to a) get the users in this array, or b) get all users in this array from the users collection with a particular status.
If this is not possible, how should I adjust my schema in order to make these sorts of queries possible?
This function will return a Meteor.users cursor based on an array of contacts and an optionally required status:
var usersByContacts = function(contacts, requiredStatus) {
var userIds = _.chain(contacts)
.map(function(c) {
if (requiredStatus) {
if (c.status === requiredStatus)
return c.userid;
} else {
return c.userid;
}
})
.compact()
.value();
return Meteor.users.find({_id: {$in: userIds}});
};
You can use it like this:
var users1 = usersByContacts(thing.contacts);
var users2 = usersByContacts(thing.contacts, 'pending');
This assumes thing has the schema referenced in your question. Also note that if you find this is a common pattern in your code, you should consider turning usersByContacts into a transform.

Remove nested document with condition in MongoDB

For the following JSON how do I remove the dog whose height is the least
{
_id:0
"name":"Andy",
"pets":[
{
"type":"dog","name":"max","height":120
},
{
"type":"dog","name":"rover","height":44
},
{
"type":"dog","name":"katie","height":100
},
{
"type":"cat","name":"minni"
}
]
}
The problem is the array of subdocuments is not a collection, you can't sort or do something else on it. But if you have an access to any language interface like JavaScript or else it's possible. You just need to extract list of subdocuments, sort them by height, remember the first one and then run the command to pull it from the array based on its name and height.
It can be done for example using this JavaScript code right in the MongoDB shell:
var min = 0; var name = "";
db.animals.find({ query:{"_id" : 0} }).forEach(
function(record){
var sets = record.pets;
min = sets[0].height;
sets.forEach(function(set){
if(set.height <= min)
{min=set.height;
name=set.name;}
});
print(min);
print(name);
query = {"_id": 0}
update = { "$pull" : { "pets" : { "name" : name } } };
db.animals.update(query, update);
})
I suspect the solution is not the most elegant but anyway it works.