Remove element from array in mongoose - arrays

i am working on nodejs/express
I want to delete element in array in mongoose
i have document in this format
{
"_id" : ObjectId("5a2e19223e50551504b316c0"),
"username" : "nikhil",
"email" : "nikhil#itradicals.com",
"password" : "$2a$10$f3NvrTywIezlzKcZLWSU0O98gn6Mc.Q8B0ZNEDG2F66f4rwyo65Yu",
"companyname" : "itr",
"role" : "vendor",
"verify" : "true",
"createddate" : ISODate("2017-12-10T18:30:00.000+0000"),
"account" : [
{
"Region" : [
"North America",
"Africa",
"Asia"
]
},
{
"Category" : [
"Group 1",
"Group 2",
"Group 3"
]
}
]
}
i want to remove only Region field using mongoose query i m getting
data dyanamically so user can delete any array either it is Region or
Category. i m getting array name which i want to delete in parameter
"field".
module.exports.setupAccount = function(id,field,callback){
var query = { _id: id};
User.findOneAndUpdate(query,{ $set: { account.Region:[] }}, callback);
}
i am new to nodejs and mongoose
thanks in advance

If you don't want to keep the empty document after removing the field you can simply $pull the entire element from the array:
module.exports.setupAccount = function(id,field,callback){
var query = { _id: id };
User.findOneAndUpdate(query, { $pull: { "account": { field: { $exists: true } } } }, callback);
}

You can use below function.
Use computed property names to dynamically pass the field to unset and query expression.
Query to verify for array existence followed by $unset to remove array.
$ positional operator to dynamically locate array based on query criteria. You can hardcode the array index if you know the array position.
module.exports.setupAccount = function(id, field, callback){
var query = { "_id": id, ['account.' + field]:{"$exists":true}};
var unset = {"$unset":{['account.$.' + field]:""}};
User.findOneAndUpdate(query, unset, callback);
}

Related

Mongoose delete an item in an array

i am a beginner in mongoose and i am trying to delete an element in array but i am facing troubles to do it
my schema is like this
name : {
type: String,
trim : true
},
pictures: {
type : Array,
required : false
},
and in my database it looks like this
{
"_id" : ObjectId("5eb67e7c74b35b205362b7f4"),
"title" : "john doe",
"pictures" : [
"img1.jpg",
"img2.png",
"img3.jpg",
"img4.jpg",
"img5.jpg"
]
}
how can i delete an item in the array of pictures?
You need $pull operator:
await Model.updateOne({"_id" : ObjectId("5eb67e7c74b35b205362b7f4")}, {$pull: { "pictures": "img1.jpg"}});

How to remove elements from array of an embedded document which are not in my array

This is my document.
{
"group_name" : "Test Group 6 (Edit)",
"created_on" : "1464367826787",
"group_id" : "group_14",
"members" : [
{
"user_id" : "user_7",
"added_on" : "1464367826787"
}
],
"is_deleted" : 0
}
I'm having list of user_ids and I need to remove user_ids which are not in the list of user_ids I have. How to remove "user_50" if input list = ["user_7"] ?
You need to use the $nin operator to select your documents, the updateMany method if you want to update multiple documents or updateOne method to update a single document.
db.users.updateMany(
{},
{ "$pull": { "members": { "user_id": { "$nin": [ "user_7" ] } } }}
)
db.users.update(
{},
{$pull:
{members:{'user_id':{$ne:"user_7"}}}}, {multi:true})

MongoDB Update Array element

I have a document structure like
{
"_id" : ObjectId("52263922f5ebf05115bf550e"),
"Fields" : [
{
"Field" : "Lot No",
"Rules" : [ ]
},
{
"Field" : "RMA No",
"Rules" : [ ]
}
]
}
I have tried to update by using the following code to push into the Rules Array which will hold objects.
db.test.update({
"Fields.Field":{$in:["Lot No"]}
}, {
$addToSet: {
"Fields.Field.$.Rules": {
"item_name": "my_item_two",
"price": 1
}
}
}, false, true);
But I get the following error:
can't append to array using string field name [Field]
How do I do the update?
You gone too deep with that wildcard $. You match for an item in the Fields array, so you get a access on that, with: Fields.$. This expression returns the first match in your Fields array, so you reach its fields by Fields.$.Field or Fields.$.Result.
Now, lets update the update:
db.test.update({
"Fields.Field": "Lot No"
}, {
$addToSet: {
"Fields.$.Rules": {
'item_name': "my_item_two",
'price':1
}
}
}, false, true);
Please note that I've shortened the query as it is equal to your expression.

Update array value vs object value

How do you update the sku value within an array as in example "B". Should I go with A over B?
Option A - Object
Scheme
"data" : {
"products" : {
235099432:{
"product_id" : 101242538,
"sku" : "",
"variant_id" : 235099432
},
]
}
Update
db.col.update({
"data.products.235099432.variant_id": 235099432
}, {
$set: {
"data.products.235099432.sku": "ITM-RED-212"
}
});
Option B - Array
Scheme
"data" : {
"products" : [
{
"product_id" : 101242538,
"sku" : "",
"variant_id" : 235099432
},
]
}
You can use the $ position operator to identify the products array element to update that matches your filter:
db.col.update({
"data.products.variant_id": 235099432
}, {
$set: {
"data.products.$.sku": "ITM-RED-212"
}
});
My vote would be option B; the use of dynamic keys in option A can get very messy.

MongoDB: How do I update a single subelement in an array, referenced by the index within the array?

I'm trying to update a single subelement contained within an array in a mongodb document. I want to reference the field using its array index (elements within the array don't have any fields that I can guarantee will be unique identifiers). Seems like this should be easy to do, but I can't figure out the syntax.
Here's what I want to do in pseudo-json.
Before:
{
_id : ...,
other_stuff ... ,
my_array : [
{ ... old content A ... },
{ ... old content B ... },
{ ... old content C ... }
]
}
After:
{
_id : ...,
other_stuff ... ,
my_array : [
{ ... old content A ... },
{ ... NEW content B ... },
{ ... old content C ... }
]
}
Seems like the query should be something like this:
//pseudocode
db.my_collection.update(
{_id: ObjectId(document_id), my_array.1 : 1 },
{my_array.$.content: NEW content B }
)
But this doesn't work. I've spent way too long searching the mongodb docs, and trying different variations on this syntax (e.g. using $slice, etc.). I can't find any clear explanation of how to accomplish this kind of update in MongoDB.
As expected, the query is easy once you know how. Here's the syntax, in python:
db["my_collection"].update(
{ "_id": ObjectId(document_id) },
{ "$set": { 'documents.'+str(doc_index)+'.content' : new_content_B}}
)
Update of an array element referenced by an index (e.g. 1 ) in Mongo Shell can also be done by directly indicating the index value:
db.my_collection.update(
{_id : "document_id"},
{$set : {"my_array.1.content" : "New content B"}}
)
In mongo style, using '$' positional operator.
Check out this link for details.
db.my_collection.update(
{_id: ObjectId(document_id), my_array.1 : 1 },
{ $set: { "my_array.$.content" : "NEW content B" } }
)
When it's required to update an array element without knowing it's actual index but having a unique identifier of the element:
// Modify a comment in a bucket
db.POST_COMMENT.update(
{
"_id": ObjectId("5ec424a1ed1af85a50855964"),
"bucket.commentId": "5eaf258bb80a1f03cd97a3ad_lepf4f"
},
{
$set: {
"bucket.$.text": "Comment text changed",
"bucket.$.createdDate": ISODate("2015-12-11T14:12:00.000+0000")
}
}
)
Here "bucket.commentId" is the unique identifier of an array element.
A neat way to do it in Javascript, with backticks, is:
const index = 1;
... { $set: { [`myArray.${index}.value`]: "new content"} }, ...
db.my_collection.update(
{_id: ObjectId(document_id), my_array : { ... old content A ... } },
{ $set: { "my_array.$.content" : "NEW content B" } }
)
When it's required to update an array element without knowing it's an actual index but having a unique identifier of the element
db.getCollection('profiles').update(
{
'userId':'4360a380-1540-45d9-b902-200f2d346263',
'skills.name':'css'
},
{
$set: {'skills.$.proficiencyLevel': 5}
},
{
multi: true
}
)
If you want to update the authorName of the testimonial having _id = 60c4918d74c30165ba585c14 from the following document:
"business": {
"ownerId": "60a5ebad7432d91b853c0277",
"testimonials": [
{
"_id": "60c4912877dd5664f2201b08",
"authorName": "user1",
"authorBio": "User from 10 years",
"image": "user1/img1",
"review": "asdfiuahsdfpoiuashdpfoaspdlfkjn;alsfpuoh"
},
{
"_id": "60c4918d74c30165ba585c14",
"authorName": "user2",
"authorBio": "User from 3 years",
"image": "user/img1",
"review": "asdpfuahsfljnsadfoihsf."
}
],
"createdAt": "2021-06-11T20:12:56.666Z",
"updatedAt": "2021-06-12T11:11:56.696Z",
}
Then the following mongoose query works:
await BusinessModel.updateOne(
{
'_id': Mongoose.Types.ObjectId(businessId),
'testimonials._id': Mongoose.Types.ObjectId('60c4918d74c30165ba585c14')
},
{
$set: { 'testimonials.$.authorName' : 'new author name' }
}
);
Also refer to https://docs.mongodb.com/drivers/node/fundamentals/crud/write-operations/embedded-arrays/
You can use the updateOne function of mongoDB passing the index of the element in array, if the key of old content B is "value" per example:
[
...
"value" : "old content A"
"value" : "old content B"
"value" : "old content C"
...
]
the command should be like this:
db.collection.updateOne({"_id" : "...,"},{$set: {"my_array.1.value": "NEW content B"}})
If you have a "plain" array containing simple strings, this did the trick:
db.paintings.insertMany([
{_id: 1, colors: ["red", "blue", "green"]},
{_id: 2, colors: ["red", "yellow"]}
db.paintings.updateMany(
{colors: "red"},
{$set: {"colors.$": "magenta"}})
the positional $ operator acts as a placeholder for the first element that matches the query document
Source

Resources