15

I am new in the MongoDB world and now I am struggling of how can I delete, update element in a nested array field of a document. Here is my sample document:

{
    "_id" : ObjectId("55f354533dd61e5004ca5208"),
    "Name" : "Hand made products for real!",
    "Description" : "Products all made by hand",
    "Products" : [ 
        {
            "Identifier" : "170220151653",
            "Price" : 20.5,
            "Name" : "Leather bracelet",
            "Description" : "The bracelet was made by hand",
            "ImageUrl" : "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQii6JCvXtx0iJGWgpvSl-KrdZONKYzDwS0U8uDvUunjO6BO9Aj"
        }
    ]
} 

In my method, I get the id of the document and the id(Identifier) of the Product that I want to delete. Can anyone tell me how can I delete from the Products field the element having Identifier: 170220151653?

I tried:

var query = Query.And(Query.EQ("_id", categoryId), Query.EQ("Products.Identifier", productId));
var update = Update.Pull("Products", new BsonDocument() { { "Identifier", productId } });
myDb.Applications().Update(query, update);

as suggested here: MongoDB remove a subdocument document from a subdocument

But I get an error at

myDb.Applications()

It just can't be found.

SOLVED:

var pull = Update<Category>.Pull(x => x.Products, builder => builder.EQ(q => q.Identifier, productId));
collection.Update(Query.And(Query.EQ("_id", ObjectId.Parse(categoryId)), Query.EQ("Products.Identifier", productId)), pull);
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
mathinvalidnik
  • 1,566
  • 10
  • 35
  • 57

6 Answers6

15

You are calling method Pull(string name, MongoDB.Bson.BsonValue value) and according to the docs it

Removes all values from the named array element that are equal to some value (see $pull)

and you provide { "Identifier", productId } as the value. I guess that mongo does not find that exact value.

Try to use the second overload of Pull with query-condition instead of exact value

Removes all values from the named array element that match some query (see $pull).

var update = Update.Pull("Products", Query.EQ("Identifier", productId));

UPDATE

Since you mention Category entity so I can suggest using lambda instead of Query.EQ:

var pull = Update<Category>.Pull(x => x.Products, builder =>
builder.Where(q => q.Identifier == productId));
neleus
  • 2,230
  • 21
  • 36
  • `Update` hmmm, you didn't mention that you have `Category` type... Anyway this is the _strongly-typed_ case of my solution, please dont forget to mark the answer. – neleus Feb 18 '15 at 14:43
10

Solution with C# MongoDB Driver. Delete a single nested element.

var filter = Builders<YourModel>.Filter.Where(ym => ym.Id == ymId);
var update = Builders<YourModel>.Update.PullFilter(ym => ym.NestedItems, Builders<NestedModel>.Filter.Where(nm => nm.Id == nestedItemId));
_repository.Update(filter, update);
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
  • 1
    thank you, been trying to do this for two days. – Roman Sterlin Aug 21 '21 at 09:16
  • Is using the Builder in the 2nd argument of PullFilter necessary? A lambda automatically infers the NestedModel type, so it'd be `nm => nm.Id == nestedItemId` instead of `Builders.Filter ...` –  Oct 04 '21 at 19:29
3

I was also facing the same problem and then finally after doing lot of R&D, I came to know that, you have to use PullFilter instead of Pull when you want to delete using filter.

Binod Mahto
  • 340
  • 2
  • 13
2

I had the same of deleting elements from the nested array but after research, I found this piece of working code.

var update = Builders<Category>.Update.PullFilter(y => y.Products, builder => builder.Identifier== productId);
var result = await _context.Category.UpdateOneAsync(filter, update);
return result.IsAcknowledged && result.ModifiedCount > 0;
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
Deepak
  • 1,510
  • 1
  • 14
  • 27
0

Hi as per my understanding you want to remove whole matched elements of given id and identifier so below query will solve your problem but I don't know how to convert this into C#, here mongo $pull method used.

db.collectionName.update({"_id" : ObjectId("55f354533dd61e5004ca5208")}, {"$pull":{"Products":{"Identifier":"170220151653"}}})
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
Neo-coder
  • 7,715
  • 4
  • 33
  • 52
0

Solution for C# MongoDB Driver. You can set empty [] the nested array.

var filter = Builders<MyUser>.Filter.Where(mu => mu.Id == "my user id");
var update = Builders<MyUser>.Update.Set(mu => mu.Phones, new List<Phone>());
_repository.Update(filter, update);
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88