Dmitry Gusarov
Dmitry Gusarov

Reputation: 1639

How to filter by descendant properties in MongoDB C# driver?

Let's say I have a class hierarchy starting from Vehicle, there are Car, Plane e.t.c. I want to retrieve 32 last vehicles, but I don't want to see special type of cars, e.g. cars on winter tires. The Car have field TireType. This is supposed to be a simple mongo query like this:

db.Vehicles.find({
    "userId" : ObjectId("5df1f2d1de064e5618be579c"),
    "tireType": {$ne: "Winter"},
}).sort({ "_id" : -1 }).limit(32)

But what can I do in C# to achieve this? I've tried lots of different things, like LINQ (Not Supported):

from v in _db.Vehicles.AsQueryable()
where v.UserId == userId
let c = v as Car
where c == null || c.TireType != "Winter"
orderby ev.Id descending
select v;

FilterBuilder (Can not convert):

using V = Builders<Vehicle>;
using C = Builders<Car>;

_db.Vehicles
.Find(V.Filter.And(C.Filter.Ne(x=>x.TireType, "Winter"), V.Filter.Eq(x=>x.UserId, userId))
.SortByDescending(x => x.Id)
.Limit(32);

I can do this with BsonDocument, but I want it to be materialized to the model classes... Can't find a good answer for this...

Upvotes: 2

Views: 951

Answers (1)

Dĵ ΝιΓΞΗΛψΚ
Dĵ ΝιΓΞΗΛψΚ

Reputation: 5679

give this a try:

    var vehicles = collection.Find(
                       Builders<Vehicle>.Filter.Eq(v => v.UserID, "xxx") &
                       Builders<Vehicle>.Filter.Ne("TireType", "winter"))
                   .SortByDescending(v=>v.Id)
                   .Limit(32)
                   .ToList();

here's a test program:

using MongoDB.Entities;
using MongoDB.Entities.Core;

namespace StackOverflow
{
    [Name("Vehicles")]
    public class Vehicle : Entity
    {
        public string Type { get; set; }
        public string UserID { get; set; }
        public string Color { get; set; }
    }

    [Name("Vehicles")]
    public class Car : Vehicle
    {
        public string TireType { get; set; }
    }

    [Name("Vehicles")]
    public class Truck : Vehicle
    {
        public string FuelType { get; set; }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            new DB("test", "localhost");

            (new Car { UserID = "xxx", Type = "car", Color = "red", TireType = "summer" }).Save();
            (new Car { UserID = "xxx", Type = "car", Color = "white", TireType = "winter" }).Save();
            (new Truck { UserID = "xxx", Type = "truck", Color = "black", FuelType = "diesel" }).Save();

            var result = DB.Find<Vehicle>()
                           .Match(f =>
                                  f.Eq(v => v.UserID, "xxx") &
                                  f.Ne("TireType", "winter"))
                           .Sort(v => v.ID, Order.Descending)
                           .Limit(32)
                           .Execute();

            //var result = DB.Collection<Vehicle>().Find(
            //                Builders<Vehicle>.Filter.Eq(v => v.UserID, "xxx") &
            //                Builders<Vehicle>.Filter.Ne("TireType", "winter"))
            //               .Limit(32)
            //               .ToList();
        }
    }
}

Upvotes: 1

Related Questions