Search code examples
c#mongodbmongodb-.net-driver

MongoDB FilterDefinition and interfaces in C#


I have a MongoDB collection contains differents entity with same interface IDocument.

public class BarDocument: IDocument
{
    public string BarField { get; set; }
}

Now I need to find inside this collection doing something like this:

var fooDoc = new FooDocument() { FooField = "test Foo Field" };
var barDoc = new BarDocument() { BarField = "test Bar Field" };
var barDoc1 = new BarDocument() { BarField = "test Bar Field 2" };

await _documentsCollection.InsertManyAsync(new List<IDocument>() { fooDoc, barDoc, barDoc1 });



var filterBar = Builders<BarDocument>.Filter.Where(x => x.BarField.Contains("Bar")) ;

var result = await _documentsCollection.Find(filterBar).ToListAsync();

But this Find statement ends in a compilation error:

Error   CS1503  Argument 2: cannot convert from 'MongoDB.Driver.FilterDefinition<WebApi.Models.Entities.Documents.BarDocument>' to 'System.Linq.Expressions.Expression<System.Func<WebApi.Models.Entities.Documents.IDocument, bool>>'

Can someone give me a hint?


Solution

  • The _documentsCollection variable is defined as ICollection<IDocument>>, thus you can insert documents that are defined both as FooDocument and BarDocument and it works - MongoDB knows how to store them in one collection and preserve their original type (_t field).

    Once they're inserted to the same collection, you're trying to query ICollection<IDocument>> using filter that is defined on the derived type, which won't be allowed by the compiler, since BarField is unknown to IDocument.

    What you can do is to define another variable which targers BarDocument specifically and then run your query on such collection:

    var barCollection = database.GetCollection<BarDocument>("yourcol");
    var filterBar = Builders<BarDocument>.Filter.
                                         Where(x => x.BarField.Contains("Bar"));
    
    var result = await barCollection.Find(filterBar).ToListAsync();
    

    This should work as long as your query returns only instances of BarDocument class.