回到目錄
關于官方驅動內建IQueryable之後的一些事,有好事也有壞事,好事就是它會将你的linq語句非常友好的翻譯成MongoDB語句,而壞事就是有一些linq語句不會被翻譯,不會被翻譯的代價就是将整個結果集裝到記憶體,然後進行linq to object的查詢,效率自然是非常低的,呵呵。
好事
最新官方驅動中,添加了對IQueryable擴充方法的支援
public static IMongoQueryable<TDocument> AsQueryable<TDocument>(this IMongoCollection<TDocument> collection);
1 它對Where完成支援
_webManageUsersRepository.GetModel().Where(i => i.LoginName == "zzl");
2 它對group完全支援
var g = _webManageUsersRepository.GetModel()
.GroupBy(i => i.DepartmentID, (i, v) => new
{
dept = i,
userCount = v.Count()
});
通過斷點我們可以看到它所生成的mongodb語句,然後可以把語句放在指令行中去執行看看具體效果
db.WebManageUsers.aggregate([{ "$group" : { "_id" : "$DepartmentID", "userCount" : { "$sum" : 1 } } }])
上面寫法是我比較喜歡的lambda表達式的方法,文法簡介,漂亮,而我不太喜歡linq寫法,但是,如果是多字段的分組,你就必須使用linq标準寫法了,因為到目前為止,mongo官方驅動還不支援多字段分組的lambda寫法,如下面的代碼,分組結果就是錯誤的
var bb = _webManageUsersRepository.GetModel()
.GroupBy(
i => new
{
i.DepartmentID,
i.Status
},
(i, v) => new
{
dept = i.DepartmentID,
status = i.Status,
userCount = v.Count()
});
它不能正确的翻譯成Mongo表達式
{aggregate([{ "$group" : { "dept" : "$DepartmentID", "status" : "$Status", "userCount" : { "$sum" : 1 }, "_id" : 0 } }])}
而使用傳統的linq寫法就可以被mongo驅動很好的翻譯
var gg = from a in _webManageUsersRepository.GetModel()
group a by new
{
dept = a.DepartmentID,
status = a.Status
} into g
select new RoleCount
{
dept = g.Key.dept,
status = g.Key.status,
userCount = g.Count()
};
下面生成的代碼是正确的
aggregate([{ "$group" : { "_id" : { "dept" : "$DepartmentID", "status" : "$Status" }, "__agg0" : { "$sum" : 1 } } }, { "$project" : { "dept" : "$_id.dept", "status" : "$_id.status", "userCount" : "$__agg0", "_id" : 0 } }])}
可以在mongo用戶端上看到正确的結果
壞事
對count()方法完成不支援,不推薦使用,如果要用到count(),建議使用mongo原生态的,而不是linq的
Stopwatch sw1 = new Stopwatch();
sw1.Restart();
var a1 = _webManageUsersRepository.Count(i => true);//性能好
sw1.Stop();
var at1 = sw1.ElapsedMilliseconds;
Stopwatch sw = new Stopwatch();
sw.Restart();
var a = _webManageUsersRepository.GetModel().Count();//性能差
sw.Stop();
var at = sw.ElapsedMilliseconds;
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!
