Search code examples
c#mongodbmongodb-querymongodb-.net-drivermongodb-csharp-2.0

MongoDB .Net Driver - Filter Builder throwing an exception


I am trying to fetch a Document from MongoDB using the C# MongoDB driver.

public class Record
{
    [BsonId]
    public ObjectId Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Data { get; set; }
}

public class Name
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

var Names = new List<Names>;
Names.Add(new Name(FirstName = "abc", LastName = "xyz"));
Names.Add(new Name(FirstName = "123", LastName = "789"));
Names.Add(new Name(FirstName = "a1b2", LastName = "c7d8"));

I tried the below query to filter and fetch the required document. But this query is failing and throwing an exception.

FilterDefinition<Record> patentFilter = Builders<Record>.Filter.Where(y => Names.Any(x=> x.Name == y.Name && x.LastName == y.LastName));

Exception:

System.ArgumentException: 'Unsupported filter: Any(value(Name]).Where((({document}{FirstName} == {document}{FirstName}) AndAlso ({document}{LastName} == {document}{LastName})))).'


Solution

  • Late for the answer.

    Would suggest:

    1. Generate nameFilters.

      Each nameFilter must meet equal ($eq) for both FirstName and ($and) LastName.

    2. Parent filter (filter) chains the nameFilters with $or.

      Any document that fulfills the nameFilter will be returned.

    var names = new List<Name>();
    names.Add(new Name { FirstName = "abc", LastName = "xyz" });
    names.Add(new Name { FirstName = "123", LastName = "789" });
    names.Add(new Name { FirstName = "a1b2", LastName = "c7d8" });
    
    List<FilterDefinition<Record>> namefilters = new List<FilterDefinition<Record>>();
    
    foreach (var name in names)
    {
        FilterDefinition<Record> namefilter = Builders<Record>.Filter.And(
            Builders<Record>.Filter.Eq(x => x.FirstName, name.FirstName),
            Builders<Record>.Filter.Eq(x => x.LastName, name.LastName)
        );
    
        namefilters.Add(namefilter);
    }
    
    FilterDefinition<Record> filter = Builders<Record>.Filter.Or(namefilters);
    
    var filteredRecords = _collection.Find(filter)
        .ToList();
    

    MongoDB query

    db.collection.find({
      $expr: {
        $or: [
          {
            $and: [
              {
                $eq: [
                  "$FirstName",
                  "abc"
                ]
              },
              {
                $eq: [
                  "$LastName",
                  "xyz"
                ]
              }
            ]
          },
          // Other name filters
        ]
      }
    })
    

    Sample Mongo Playground