Deleting a field with $unset operation it just converting it to a null value - node.js

I'm trying to delete some fields on my mongodb database but instead the fields are just getting mutated to a null value and that's an issue because when fetching data im using loops and they get broken passing true null value ... for deleting data i'm using the following :
User.updateOne({_id : user._id } ,{ $unset :{ "days.0.tasks.0" = "" })
what i'm getting :
Is there a way to delete entirely the objects inside the tasks array?

$unset is not working as you'd expect it because you are using it on an element inside an array. Removing the element at position 0 means shifting all other elements in the array. To prevent messing with those other elements, $unset is setting the element at position 0 to null.
MongoDB docs
I suggest using the $pull operator to delete specific elements from an array or use $pop for the first / last items .
OR :
you can get the user tasks array and splice it then push it back using $set operator.

Related

Update specific field in an array of object in a MongoDb Document

I have a document with that format :
{
"field1":"string",
"field2":123,
"field3":
[
{
"subField1":"string",
"subField2": object,
// other fields after
},
{
"subField1":"string",
"subField2": object,
// other fields after
},
// other fields after
]
// other fields after
}
I want to update at once the field3.$.subField2 field only, with a different value in each of the elements of the array composing field3.
Does anyone knows how to properly do it ?
One reason I want to do this is I have several asynchronous operations that are meant to update differents fields of the array field, and I have concurrency issues...
I tried with findOneAndUpdate(query, $set{"field3.$.subField2": arrayOfValues}) but it does not works, it seems I can only pass one single value that would be set to each element of the array (all the same).
arrayOfValues would be of course an array with only the values I want with the matching indexes and same size of the document's array.

How to remove empty fields on Update

When I remove an array element from a document field, I would like to remove that field, if zero length, or empty object. I do not want fields with empty arrays or empty objects saved on db.
I use this snippet for update document:
await documentInstance.findByIdAndDelete(req.params.id,async(error,doc)=>{
await empInstance.findByIdAndUpdate(employId,{
$pull:{
documents:req.params.id
}
},{omitUndefined:true});
});
When I remove the only item from array, I get an empty array.
Thanks.

Get all documents whose property equals one of the elements in an array

I have a Post model that has a publisher property defined in its schema (I'm using Mongoose). The publisher property is a string that refers to a publisher's name.
I also have an array called sourceNames that holds all the different publisher names. I want to query my database for ALL the posts whose publisher matches any one of the array elements in sourceName. My current query looks like this:
const query = postModel
.find({ publisher: { $all: sourceNames } })
.limit(limit)
.skip(startIndex);
My query isn't returning anything when I exec it. Does anyone know if what I'm trying to do is possible in a single query (Rather than loop over sourceNames and make a query for each individual element?
Short
Just replace $all with $in
Expl
$all is trying to match an array with all elements in your array.
$in instead, tries to match a string or array with one in the array.

Increment nested field value in mongodb if exists or create nested fields

I need to increment the multi level nested field value if it exists or create the complete nested field Object structure.
Structure of my document
Doc1 {
_id:ObjectId(),
myField: {
nested:{
x: 5,
y: 10,
z: 20
}
}
}
Goal Explanation: I need a way to write a single query:
If myField exists: Increment the value of my nested field
myField.nested.x by 10.
If myField does not exists: Create the below field with initial values same as given in the Doc1.
Attempt and explanation:
db.collection('collectionName').findOneAndUpdate(
{_id:"userId","myField" : { $exists : true }},
{$inc:{'myField.nested.x':10}
})
This way, I can increment the nested field if it exists but in case of non existence I cannot set myField as same as Doc1.
Although, I can use another query after response in my NodeJs callback to achieve my required behaviour. But I need some elegant solution in a single query.
I am using MongoDB version 4.0.4, Thanks in Advance.
Try this query
If the field does not exist, $inc creates the field and sets the field to the specified value.
db.collection('collectionName').findOneAndUpdate({_id:"userId"},
{$inc:{'myField.nested.x':10}
})

Mongo DB C# code using 2 level , 3 level and 4 level of array

I have to update in C# code using MongoDB. Here I had implement 2nd level array of update in below (subBranchindex is taken in a generic list object):-
for (var index = 0; index < subBranchindex.Count; index++)
{
if (subBranchindex[index]._id == new ObjectId(subBranchid))
{
IMongoQuery queryEdit = Query.EQ("BranchOffice.SubBranchlist._id", new ObjectId(subBranchid));
UpdateBuilder update = Update.Set("BranchOffice.$.SubBranchlist."+ index +".Name",subBranch.SubName).
SafeModeResult s = dc.Collection.Update(queryEdit, update,
UpdateFlags.None, SafeMode.True);
}
}
Here 2nd level array, I was using (for loop Statement) to taken Index value for array. Next I can use 3rd, 4th and 5th level of array means more than (for loop statement) will be assign. So don't need [for loop Statement] and also don't need to assign hardcore number in index.
For example: ("BranchOffice.$.SubBranchlist.0.Name",subBranch.SubName). Here Don't Hardcore number[index] 0 or 1 or 2. "2nd" level array more than 100 record is there.
Is there any way I can use to array index value? Please explain how to solve this probelm. Please explain me with Example.
Based on your example above, my understanding of your schema is the following:
The top-level document has a BranchOffice field
BranchOffice is an array of objects
Each object within BranchOffice has an _id, SubName and SubBranchlist field
SubBranchlist is an array of objects
Each object within SubBranchlist has a Name field
Your update statement appears to be copying the SubName field to each Name field among objects within SubBranchlist (a sibling field of SubName).
Using the property path syntax to select fields through arrays (e.g. SubBranchlist.0.Name), there is no "wildcard" index that will allow you to modify Name fields among all objects in the array.
On a somewhat related note, the $ positional operator only applies to the first-matched array element, so you cannot use that to update multiple array elements. In your case, it would not be an option anyway, since you're using the positional operator for the BranchOffice array field.
You can either issue a series of update queries (for each element in SubBranchlist), or consider using $set to modify the entire SubBranchlist array in one query. The downside with using $set is that you'll need to read and write back the entire array, which may be a problem if other, concurrent operations are also issuing updates to the array.

Resources