2017-03-02 89 views
0

我移植從舊的遺留MongoDB的司機一些代碼,使用新的驅動程序,並已觸及問題查詢派生類型的值。我有一個包含來自公共基類的多個派生類型的集合。以前,我能夠使用派生類屬性查詢集合(這是使用基類型聲明的),並只檢索派生類文檔。所以考慮到這些類:使用MongoDB的C#驅動

[BsonDiscriminator(RootClass = true)] 
[BsonKnownTypes(typeof(Cat),typeof(Dog))] 
class Animal 
{ 
    [BsonId(IdGenerator = typeof(StringObjectIdGenerator))] 
    public string Id { get; set; } 

    public string Name { get; set; } 
} 

class Cat : Animal 
{ 
    public bool LikesFish { get; set; } 
} 

class Dog : Animal 
{ 
    public string FavouriteBone { get; set; } 
} 

然後我可以這樣做:

MongoCollection<Animal> animals = db.GetCollection<Animal>("Animals"); 
var q = Query<Cat>.EQ(c => c.LikesFish, true); 
var catsThatLikeFish = animals.FindAs<Animal>(q).ToList(); 

它工作得很好。

但是現在我必須輸入濾波器,不能再編譯:

IMongoCollection<Animal> animals = db.GetCollection<Animal>("Animals"); 
var query = Builders<Cat>.Filter.Eq(c => c.LikesFish, true); 
var catsThatLikeFish = animals.FindSync(query); 

,並得到這個錯誤:可能

Error CS0411 The type arguments for method 'IMongoCollection<Animal>.FindSync<TProjection>(FilterDefinition<Animal>, FindOptions<Animal, TProjection>, CancellationToken)' cannot be inferred from the usage. Try specifying the type arguments explicitly. 

這是不再使用新的驅動程序?我們有類允許通用查詢這個集合,我現在看不到任何優雅的方法。

編輯:

可悲的是獨立的集合是我們混合過濾器表達式拉回使用相同的查詢不同類型的非首發。在「貓狗」例如從上面這樣的:

var catQuery = Query<Cat>.EQ(c => c.LikesFish, true); 
var dogQuery = Query<Dog>.EQ(c => c.FavouriteBone, "Beef"); 
var q = Query.Or(catQuery, dogQuery); 

var catsThatLikeFishOrDogsThatLikeBeef = animals.FindAs<Animal>(q).ToList(); 

我會看看「nameof」上述方法 - 可工作,但它似乎的老辦法優雅缺乏給我。 ..

任何幫助,非常感謝!

感謝,

史蒂夫

+1

除了Maksim的回答下面,在新API中有一個OfType()方法... IMongoCollection dogs = db.GetCollection (「Animals」)。OfType ()。 –

回答

3

你有貓,狗的集合togetehr並要過濾只是貓?還是你想要得到所有的狗,只有那些像魚一樣的貓?

在第一種情況下,我會建議查詢只從收集貓或只有狗:

var collectionAsCats = db.GetCollection<Cat>("Animal"); 
var collectionAsDogs = db.GetCollection<Dog>("Animal"); 

var catsDoesntlikeFish = collectionAsCats.Find(c => c.LikesFish == false).ToList(); 
var dogs = collectionAsDogs.Find(c => c.FavouriteBone == "bla").ToList(); 

或者你可以有動物之一的收集和處理字符串查詢數據:

var collectionAll = db.GetCollection<Animal>("Animal"); 
var filter = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), false); 
var catsDoesntlikeFish = collectionAll.Find(filter).As<Animal>().ToList(); 

如果您想將狗狗放在一起與貓貓,您可以擴展此過濾器:

var collectionAll = db.GetCollection<Animal>("Animal"); 
var filter = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), false); 
var exists = Builders<Animal>.Filter.Exists(nameof(Cat.LikesFish), false); 
var orFilter = Builders<Animal>.Filter.Or(filter, exists); 
var catsDoesntlikeFishAndDogs = collectionAll.Find(orFilter).ToList(); 

編輯

我這裏補充克雷格·威爾遜評論,非常感興趣的信息(感謝,克雷格):

新的API中

有一個OfType()方法...

IMongoCollection<Dog> dogs = db.GetCollection<Animal>("Animals").OfType<Dog>() 
0

OK,這似乎工作:

var catQuery = Builders<Animal>.Filter.Eq(nameof(Cat.LikesFish), true); 
var dogQuery = Builders<Animal>.Filter.Eq(nameof(Dog.FavouriteBone), "Beef"); 
var query = Builders<Animal>.Filter.Or(catQuery, dogQuery); 
var catsThatLikeFishOrDogsThatLikeBeef = animals.FindSync(query).ToList(); 

雖然我認爲它缺乏舊的驅動方法的風采。

+1

這與我向您建議的解決方案完全相同,那裏出了什麼問題? –

+0

沒有什麼是錯的,我發佈這個具體的答案作爲一個確認的解決方案,感謝您的幫助。 –