Search code examples
c#filteringmongodb-.net-driver

C# MongoDB Driver filter subdocument list based on incoming array


I have the following C# model structure:

public class Box
{
    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string? Id { get; set; }

    [BsonElement("relatedJobs")]
    public List<BoxJobs> RelatedJobs { get; init; } = default!;

    //more properties

    public class BoxJobs
    {
        [BsonElement("partnerId")]
        public string PartnerId { get; init; } = null!;
        
        //more properties
    }
}

There is a need to filter all the boxes based in an incoming partnerIds array. In other words I want to retrieve every single box that has at least one relatedJob with its partnerId present in the incoming array.

I've tried the following:

var builder = Builders<Box>.Filter;
var filter = new FilterDefinitionBuilder<Box>().Empty;
filter &= !partnerIds.Any()
        ? new FilterDefinitionBuilder<Box>().Empty
        : builder.AnyIn(box => box.RelatedJobs.Select(relatedJob => relatedJob.PartnerId), partnerIds);
var cursor = Collection.Find(filter);

This results in the following error:

Unable to determine the serialization information for box => box.RelatedJobs.Select(relatedJob => relatedJob.PartnerId).

I have also tried creating a PartnerIds property in Box which returns the same Select result, and use it in the AnyIn function but it didn't help either.

How can I do this filtering?


Solution

  • As I can see you need to check that RelatedJobs contains a job pith PartnerId from partnerIds list. Fields.ElemMatch method returns the first matching element in the array specified by name.

    var builder = Builders<Box>.Filter;
    var filter = new FilterDefinitionBuilder<Box>().Empty;
    filter &= !partnerIds.Any()
            ? new FilterDefinitionBuilder<Box>().Empty
            : builder.ElemMatch(x => x.RelatedJobs, j => partnerIds.Contains(j.PartnerId));
    var cursor = Collection.Find(filter);