文章出處

回到目錄

關于官方驅動集成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;

回到目錄

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()