8

How can i make filter and add/update third, fourth level child of a mongodb document using C#. I can add/Update till second level but not further. Please provide me a solution or any kind reference from where can get help. Is there any other way to do it except builders..Elemmatch.

Here is my classes and code:

namespace CrudWithMultilvelNestedDoc
{
    public class Channel
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Episode[] Episodes { get; set; }
    }

    public class Episode
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Track[] Tracks { get; set; }
    }

    public class Track
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
        public Like[] Likes { get; set; }
    }

    public class Like
    {
        [BsonId]
        [BsonRepresentation(BsonType.String)]
        public string Id { get; set; }
        public string Name { get; set; }
    }
}

    //First Method
    //var filter = Builders<Channel>.Filter.And(Builders<Channel>
    //                              .Filter.Where(x => x.Id == "5e4606e6ae7b090688671416"), // OR &
    //             Builders<Channel>.Filter.ElemMatch(e => e.Episodes, Builders<Episode>
    //                              .Filter.Eq(e => e.Id, "5e460851d29c1b3df4d27b7d")));

    //Second Method
    //var filter = Builders<Channel>.Filter.Eq(e => e.Id, "5e4606e6ae7b090688671416") 
    //           & Builders<Channel>.Filter.ElemMatch(e => e.Episodes, Builders<Episode>.Filter.Eq(e => e.Id, "5e46071d385a672b0cea0f86"));

    //Third Method
    var filter = channelFilter.ElemMatch(e => e.Episodes, episodeFilter.ElemMatch(e=> e.Tracks, trackFilter.Eq(e => e.Id, "5e460dbe2bc5e70c9cfeac21")));
    var data = collection.Find(filter);         
    //Update Filter
    var update = Builders<Channel>.Update.Push("Episodes[-1].Tracks[-1].Likes", like);
    var result = collection.UpdateOne(filter, update);
//Data 
    {"_id":"5e4606e6ae7b090688671416","Name":"Channel 1","Episodes":[{"_id":"5e46071d385a672b0cea0f86","Name":"Episode 1","Tracks":[{"_id":"5e460dbe2bc5e70c9cfeac21","Name":"Trak 1","Likes":[]},{"_id":"5e4612d60747a2121870c815","Name":"Trak 2","Likes":[]}]},{"_id":"5e460851d29c1b3df4d27b7d","Name":"Episode 2","Tracks":[{"_id":"5e460e307ca6843758ce814e","Name":"Trak 1","Likes":[]}]}]}

enter image description here

1 Answer 1

6

As per documentation:

The positional $ operator cannot be used for queries which traverse more than one array

So using -1 is not a way forward here. The approach you should take is the $ positional filtered operator.

There's no strongly-typed representation in C# so your code can look like below:

var filter = Builders<Channel>.Filter.Eq(x => x.Id, "5e4606e6ae7b090688671416");

var like = new Like() {Name = "new like", Id = "1"};
var episodeId = "5e46071d385a672b0cea0f86";
var trackId = "5e460dbe2bc5e70c9cfeac21";

var update = Builders<Channel>.Update.Push("Episodes.$[e].Tracks.$[t].Likes", like);

var arrayFilters = new List<ArrayFilterDefinition>();
ArrayFilterDefinition<BsonDocument> episodesFilter = new BsonDocument("e._id", new BsonDocument("$eq", episodeId));
ArrayFilterDefinition<BsonDocument> tracksFilter = new BsonDocument("t._id", new BsonDocument("$eq", trackId));
arrayFilters.Add(episodesFilter);
arrayFilters.Add(tracksFilter);

var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };

var result = mongoDBCollection.UpdateOne(filter, update, updateOptions);
Sign up to request clarification or add additional context in comments.

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.