Xavier W.
Xavier W.

Reputation: 1360

Mongodb C# driver update all subarray elements

I want to update a document and set a value to an array of subdocument. Using the documentation I have to use the $[] operator.

Following this link it is now possible to do stuff like this :

db.coll.update({}, {$set: {“a.$[].b”: 2}})
Input: {a: [{b: 0}, {b: 1}]}
Output: {a: [{b: 2}, {b: 2}]}

For example this request will do the job in my case :

db.collection.update(
   { "History": { "$elemMatch": { "status": { "$ne": "PROCESSED" } } } }, 
   { "$set": { "History.$[].flag": false } },
   { "multi": true }
)

But I do not find the way to do the $[] operator in C# with the driver. And the driver documentation does not contain the information.

Can someone please provide me a C# sample.

Upvotes: 3

Views: 1139

Answers (2)

Dĵ ΝιΓΞΗΛψΚ
Dĵ ΝιΓΞΗΛψΚ

Reputation: 5669

you can achieve it like this:

            collection.UpdateMany(
                x => x.History.Any(h => h.status != "PROCESSED"),
                Builders<YourType>.Update.Set("History.$[].flag", false));

here's an alternative strongly-typed solution:

using MongoDB.Entities;
using MongoDB.Entities.Core;
using System.Linq;

namespace StackOverflow
{
    public class Test : Entity
    {
        public Event[] History { get; set; }
    }

    public class Event
    {
        public bool flag { get; set; }
        public string status { get; set; }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            new DB("test", "localhost");

            (new[] {
                new Test { History = new[]{
                    new Event { flag = true, status = "PROCESSED" } } },

                new Test { History = new[]{
                    new Event { flag = true, status = "NOT-PROCESSED" },
                    new Event { flag = true, status = "NOT-PROCESSED" }
                }}
            }).Save();

            var field = Prop.PosAll<Test>(t => t.History[0].flag);

            DB.Update<Test>()
              .Match(t => t.History.Any(h => h.status != "PROCESSED"))
              .Modify(b => b.Set(field, false))
              .Execute();
        }
    }
}

Upvotes: 3

Stefan Popovski
Stefan Popovski

Reputation: 516

Let's suppose that you have an object called History:

public class History : MongoDocument
{
   // here you have some other properties, and you have a list of objects
   public Guid Guid { get; private set; }
   public List<SOME_OBJECT> NAME_OF_THE_ARRAY { get; set; }
}

And SOME_OBJECT:

public class SOME_OBJECT
{
  // here you have other properties
  public bool Flag { get; set; }
  public string Name { get; set; }
}

And you want to update all objects into NAME_OF_THE_ARRAY:

public async Task<bool> Update_NAME_OF_THE_ARRAY(string id)
{
  var filter = Builders<History>.Filter.Eq("_id", ObjectId.Parse(id));
  var update = Builders<History>.Update.Combine(
    Builders<History>.Update.Set(x => x.NAME_OF_THE_ARRAY[-1].Name, "test")
    Builders<History>.Update.Set(x => x.NAME_OF_THE_ARRAY[-1].Flag, false);
  var result = await _historyCollection.UpdateOneAsync(filter, update);
  return result.ModifiedCount > 0;
}

Upvotes: -1

Related Questions