user348173
user348173

Reputation: 9288

C# How to get specific item from nested array

I have the following model:

public class Car
{
   public string Id {get; set;}
   public IList<Driver> Drivers {get; set;}
}

public Driver 
{
   public string Id {get; set;}
   public bool IsActive {get; set;}
}

How can I select driver that is active?

var carId = "...";
var activeDriver = await _carCollection.Find(a => a.Id == carId
            && a.Drivers.Any(e=>e.IsActive))
            .Project(a=>a.Drivers)
            .SingleOrDefaultAsync();

This code returns IList<Driver>, so all items. But I want to retrieve only one Driver that is active.

Upvotes: 4

Views: 4569

Answers (2)

The above accepted answer did not work for me. It returned nothing. You can use the following code:

var activeDriver = await _carCollection.AsQueryable().Where(a => a.Id == carId).SelectMany(a => a.Drivers).Where(e => e.IsActive).FirstOrDefault();

You can check this link

Upvotes: 0

Neil Lunn
Neil Lunn

Reputation: 151220

You basically need to include the positional $ operator in order to just return the matched array element from the query conditions given. You can do this with ElementAt(-1)

var activeDriver = await _carCollection.Find(a => a.Id == carId
        && a.Drivers.Any(e => e.IsActive))
        .Project(a => a.Drivers.ElementAt(-1))
        .SingleOrDefaultAsync();

And can also be written as:

var builder = Builders<BsonDocument>.Filter;

var activeDriver = await _carCollection.Find(
         builder.Eq("Id", carId) & builder.Eq("Drivers.IsActive", true))
        .Project(Builders<BsonDocument>.Projection.Include("Drivers.$"))
        .SingleOrDefaultAsync();

If I run either of those then I get the serialized output of what get's sent to MongoDB as:

 { 
    "find" : "cars",
    "filter" : { "_id" : "a", "Drivers" : { "$elemMatch" : { "IsActive" : true } } },
    "projection" : { "Drivers.$" : 1, "_id" : 0 },
    "limit" : 2,
    "$db" : "test"
 }

Which matches exactly what the query should be.

Upvotes: 5

Related Questions