cs.kali
cs.kali

Reputation: 308

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?

Upvotes: 3

Views: 209

Answers (1)

Vadim Martynov
Vadim Martynov

Reputation: 8892

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);

Upvotes: 1

Related Questions