25

Can you help me to run correctly "Pull (remove)" with 2.0 driver.

I have a collection like this and I want to remove first follower named as fethiye by follower field.

{
  "_id": ObjectId("554e05dfc90d3d4dfcaa2aea"),
  "username": "bodrum",
  "followerList": [
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "follower": "fethiye",
      "avatar": "fethiye.png"
    },
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "follower": "izmir",
      "avatar": "izmir.png"
    }
  ]
} 

How can I fix this query?

var filter = new BsonDocument("username", "bodrum");
var update = Builders<Person>.Update.Pull("followerList:follower", "fethiye");
Person pr = collection.FindOneAndUpdateAsync(filter, update).Result;

Thanks.

4 Answers 4

64

When using a filter to remove array elements, you need to use the PullFilter builder instead of Pull (which matches whole elements).

var collection = db.GetCollection<Person>("people");
var filter = new BsonDocument("username", "bodrum");
var update = Builders<Person>.Update.PullFilter("followerList",
    Builders<Follower>.Filter.Eq("follower", "fethiye"));
var result = collection.FindOneAndUpdateAsync(filter, update).Result;

Or somewhat more succinctly, using lambdas:

var update = Builders<Person>.Update.PullFilter(p => p.followerList,
                                                f => f.follower == "fethiye");
var result = collection
    .FindOneAndUpdateAsync(p => p.username == "bodrum", update).Result;
Sign up to request clarification or add additional context in comments.

2 Comments

What if the the document we want to pull was one level deeper? as in this question stackoverflow.com/questions/32995762/…
what is "collection" variable here, can you show me the code for that? Thanks.
6

Assuming you have a collection name Person, You can use PullFilter to remove the records from array

var filterBuilder = Builders<Person>.Filter.Eq(person => person.username, "bodrum");

var updateBuilder = Builders<Person>.Update.PullFilter(p => p.followerList,
                       Builders<Person>.Filter.Eq(per => per.follower, "fethiye"));

var updateResult = collection.UpdateOne(filterBuilder, updateBuilder);

Console.WriteLine(
            $"MatchedCount: {updateResult.MatchedCount}, ModifiedCount: {updateResult.ModifiedCount}");

If we also need to remove array of values inside a filtered document we can replace the update builder with this line

var updateBuilder = Builders<Person>.Update.PullFilter(p => p.followerList,
                   Builders<Person>.Filter.In(per => per.follower, new List<string> {"fethiye", "izmir"}));

Also to save many document, updateOne can be replace with updateMany

var updateResult = collection.UpdateMany(filterBuilder, updateBuilder);

Comments

1

This is what i use to delete a nested array object

-parentpath: followerList
-propertie: follower
-value: fethiye.png

var filter = new BsonDocument("_id", ObjectId.Parse(id));

    var updateValues = Builders<object>.Update.PullFilter(parentPath,
        Builders<object>.Filter.Eq(propertie, value));
        DatabaseCollection.FindOneAndUpdate(filter, updateValues);

Example to delete a deeper nested array object:
Let's delete the object with the name Doe

-parentPath: followerList.0.testArray
-propertie:name
-value:Doe

    {
  "_id": ObjectId("554e05dfc90d3d4dfcaa2aea"),
  "username": "bodrum",
  "followerList": [
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "follower": "fethiye",
      "testArray": [
{
"name":"John"
},
{
"name":"Doe"
},
{
"name":"Jason"
}
]
    },
    {
      "_id": ObjectId("554e0625a51586362c33c6df"),
      "follower": "izmir",
      "avatar": "izmir.png"
    }
  ]
} 

Comments

1

may i offer a much simpler solution using MongoDB.Entities. the person and followers are stored in their own collections and represents a one-to-many relationship.

using System.Linq;
using MongoDB.Entities;

namespace StackOverflow
{
    public class Person : Entity
    {
        public string Username { get; set; }
        public Many<Follower> FollowerList { get; set; }

        public Person() => this.InitOneToMany(() => FollowerList);
    }

    public class Follower : Entity
    {
        public string Name { get; set; }
        public string Avatar { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            new DB("followers");

            var person1 = new Person { Username = "bodrum"};
            person1.Save();

            var follower1 = new Follower { Name = "fethiye", Avatar= "fethiye.png" };
            follower1.Save();

            var follower2 = new Follower { Name = "izmir", Avatar = "izmir.png" };
            follower2.Save();

            person1.FollowerList.Add(follower1);
            person1.FollowerList.Add(follower2);

            var fathiye = person1.FollowerList.Collection()
                                              .Where(p => p.Name == "fethiye")
                                              .FirstOrDefault();

            person1.FollowerList.Remove(fathiye);
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.