I have an array of data that I want to insert in my database:
[
{
"id":"816307",
"email": "john.doe#test.com",
"firstName": "John",
"lastName": "Doe"
},
{
"id":"391650",
"email": "mary#williams",
"firstName": "Mary",
"lastName": "Williams"
},
{
"id":"183751",
"email": "paul.smith#test.com",
"firstName": "Paul",
"lastName": "Smith"
},
]
I know that I can use the .create method from mongoose to insert all the data.
However, in the data, I need to be able to have a combination of new values and existing values. For example, if a user with id 816307 (John Doe) already exists but have a different email it should update the value and at the same time if a user with id 391650 (Mary Williams) does not exist it should create it.
The id field cannot be updated.
It seems like the best method to use is currently updateMany and to use the upsert option to insert new elements at the same time .updateMany().
But, how to do to reference the id? I cannot use $eq and hardcode anything here, I would like that the document automatically finds the proper item by its id and update it if it exists, otherwise, create it.
Since each object has it's own filter & update, then you might not be able to do it using .updateMany(), instead you can use MongoDB's .bulkWrite(), with which you could do things in one DB call, internally MongoDB would do multiple write ops.
Try below code :
let input = [
{
id: "816307",
email: "john.doe#test.com",
firstName: "John",
lastName: "Doe",
},
{
id: "391650",
email: "mary#williams",
firstName: "Mary",
lastName: "Williams",
},
{
id: "183751",
email: "paul.smith#test.com",
firstName: "Paul",
lastName: "Smith",
},
];
let bulkArr = [];
input.forEach((each) => {
bulkArr.push({
updateOne: {
filter: each.id,
update: {
$set: {
email: each.email,
firstName: each.firstName,
lastName: each.lastName,
},
},
upsert: true,
},
});
});
db.collection.bulkWrite(bulkArr)
Related
I have a collection with a layout that looks something like this:
student1 = {
"First_Name": "John",
"Last_Name": "Doe",
"Courses": [
{
"Course_Id": 123,
"Course_Name": "Computer Science",
"Has_Chosen_Modules": false
},
{
"Course_Id": 284,
"Course_Name": "Mathematics",
"Has_Chosen_Modules": false
}
]
};
I also have the following update query:
db.Collection_Student.update(
{
$and: [
{First_Name: "John"},
{Last_Name: "Doe"}
]
},
{
$set : { "Courses.0.Has_Chosen_Modules" : true }
}
);
This code will currently update the Computer Science Has_Chosen_Modules value to true since the index is hardcoded. However, what if I wanted to update the value of Has_Chosen_Modules via the Course_Id instead (as the course might not necessarily be at the same index every time)? How would I achieve this without it affecting the other courses that a given student is taking?
You can select any item in the sub array of your document by targeting any property in the sub array of your document by using dot .
You can easily achieve this by the following query.
db.Collection_Student.update(
{
First_Name: "John",
Last_Name: "Doe",
'Courses.Course_Id': 123
},
{
$set : { "Courses.$.Has_Chosen_Modules" : true }
}
);
Conditions in search filter are by default treated as $and operator, so you don't need to specifically write $and for this simple query.
dbo.collection("users")
.findOne({email: emailGiven, "friends.email": element.email},
{ friends: { $elemMatch: { email: element.email } } },
function(errT, resultT) {})
I have the query above in node.js but for some reason the query's elemMatch part doesn't work on node.js but when I execute the same query in mongo terminal it works, so I'm thinking maybe node.js doesn't support $elemMatch? If this is the case, could anyone tell me what would be the equivalent of this query in node.js?
Sample data from my DB:
/* 4 */
{
"_id" : ObjectId("5ad20cef8248544860ce3dc1"),
"username" : "test",
"email": "",
"fullName" : "",
"friends" : [{email: "",
status :""}],
"alarms": [ {"id":111,
"title": "TITLE",
"location": "",
"startTime": "10-10-1996 10:18:00",
"endTime": "10-10-1996 10:18:00" }, {},{}
],
"pnumber" : ""
}
The node.js driver findOne has a different call signature than the findOne in the MongoDB shell. You pass the field selection object as the projection element of the options parameter:
dbo.collection("users")
.findOne({"friends.email": email},
{projection: { friends: { $elemMatch: { email: email } } } },
function(errT, resultT) {...});
If you want to find for any values which is stored in some variable, you use regex for that. Your query should look like
dbo.collection("users").findOne({
email: new RegExp(emailGiven, 'i'),
"friends.email": new RegExp(element.email, 'i')
}, {
friends: {
$elemMatch: {
email: new RegExp(element.email, 'i')
}
}
}, function(errT, resultT) {})
i is for case insensitive comparison here
If I have a collection with multiple documents for one person like:
{ FullName: "Jane Doe", Camp: "may12", Week1: "0", Week2: "1", Week3: "0" }
{ FullName: "Jane Doe", Camp: "may13", Week1: "0", Week2: "0", Week3: "1" }
{ FullName: "Jane Doe", Camp: "may14", Week1: "0", Week2: "1", Week3: "0" }
and I need to update her name to "Jane Smith", I get her name from a Session:
var nameAddressFullName = Session.get('clientName');
Get all the documents with her name in put them into an array:
var documentNameAddressP = Programs.find({ FullName: nameAddressFullName}).fetch();
Then try to update all the names (I need to update based on _id values only), I'd need something like:
Programs.update({ _id: {$in: {documentNameAddressP._id}}, {$set: {FullName: nameChange}}); //????
We need to update all Jane Doe's documents to the full name Jane Smith keeping all the rest of the properties intact.
If you do this update via a method call to server then you can bulk update all the documents there in one go with {multi: true} in your update query.
From the client you can easily iterate over the cursor:
Programs.find({ FullName: nameAddressFullName}).forEach(function(doc){
Programs.update({ _id: doc._id },{ $set: { FullName: nameChange }});
});
You can select element to update in update query:
Programs.update({FullName: nameAddressFullName},{$set: {FullName: nameChange}})
https://docs.mongodb.org/manual/reference/operator/update/set/
Here below is once again my hypothetical Users collection where more than one address is allowed:
{
"firstName": "Joe",
"lastName": "Grey",
...
"addresses":
[
{
"name": "Default",
"street": "...",
...,
"isDefault": true
},
{
"name": "Home",
"street": "...",
...,
"isDefault": false
},
{
"name": "Office",
"street": "...",
...,
"isDefault": false
}
]
}
Let's suppose I want to update the second address (Home) with the following new item:
{
"name": "New home",
"street": "Ruta del Sol"
},
How do I update the second item of the array with the new item, also considering that the new item might or might not provide all the fields of an address?
In this post Will shown me how to update a field at a given index, ensuring the address name remains unique. Now, instead of updating a single field, I want to update an entire item.
All you need to do is transform new json data for update . Example:
Let us assume you have new Json data with only two fields 'name' and 'isDefault' .
var newData = {"name" : "New Val","isDefault":true};
var updateData = {};
for (key in newData ) {
updateData["addresses.$."+key]=newData[key];
};
db.projectPlan.update({_id:1, 'addresses.name': 'Home'}, {$set:updateData});
var renamed = 'Office'; // from user input
var users = getUserMongoCollection();
var address = {
name: "Office,
street: "Ruta del Sol"
};
users.update({_id:userId },
{ $set : { 'addresses.1' : address } }, function(err){
//all done!
});
I'm writing an app in meteor and trying to get familiar in mongodb, I am trying to update a user with the following schema.
user = {
... SOME DATA....,
"profile": {
"firstName": "HELLO",
"lastName": "MIKE",
"phoneNumber": "0432456524",
"userRole": "General Practitioner",
"practice": {
"name": "Hello koramaiku",
"address": "222 Hello St Helloville",
"state": "NSW",
"postcode": "2000"
},
"AHPRANumber": "4586546545",
"providerNumber": "4565498751321"
}, ..... SOME MORE DATA
}
I have a settings form, which will modify the some details in the profile object of the user.
I have a form which allows you to edit the firstName, lastName and phoneNumber in the profile object, without replacing some of the existing values.
var userData = {
firstName: 'Hello',
lastName: 'Kora',
phoneNumber: '0422222222'
};
Meteor.users.update({'_id': Meteor.userId() }, {$set : userData}, function(error){
........
});
However, if I perform the update, it overwrites the entire profile object with the new values instead of replacing just the values that I need. From I what I understand the $set modifier would replace the data at a certain field if they already exist and adds to set if they don't exist.
Is there a way to update a document's data as the above, without overwriting data that I don't want replaced?
Thanks.
Use the .
userData = {
"profile.firstName": 'Hello',
"profile.lastName": 'Kora',
"profile.phoneNumber": '0422222222'
};
These will ensure only those particular keys are altered.