文章出處

回到目錄

對于數組對象mongodb本身是支持的,不過對于數組的更新,mongodb的Csharp驅動目前只支持一級,即你的對象里包含數組,而數組又包括數組,這表示兩層,這在更新子數組時,Csharp驅動是不支持的,今天要說的就是如何讓它支持子數組的更新,下面是我給出的數據結構

在Mongodb的Csharp驅動里,一般的更新方法如下

  update = new UpdateDocument {{ "$set",       
                                  new BsonDocument("OrderList.$.UserName","占占的訂單")
                              }};
  mongoRepository.Collection.Update(query, update);

上面代碼可以很快速的將指定的二級數組OrderList里的UserName字段更新,而如果你要更新OrderDetail就沒那么容易了,Csharp驅支目前是不支持的,當然你肯定會照著葫蘆畫飄,但結果是失敗的,就像下面的代碼(失敗,只有既望新版驅動了)

  update = new UpdateDocument {{ "$set",       
                                  new BsonDocument("OrderList.$.OrderDetail.ProductName","占占")
                              }};
  mongoRepository.Collection.Update(query, update);

結果是OrderDetail的ProductName沒有發生任何變化,呵呵。

去找原因,去找資料,還好,找到了一個不錯的說法,即要想更新數組內的數組,需要將對上級數據進行定位,如OrderList.0.OrderDetail,這表示下標為0的OrderList數組元素(一個實體)下的OrderDetail數組對象,當然這個下標可不是那么輕易能得到的,

我們需要對數組進行遍歷,找到滿足條件的后,進行break即可。

var mongoRepository = new MongoDB.Data.Core.MongoOfficialRepository<Person>();
            var query = Query.EQ("OrderList._id", twoID);
            var oo = mongoRepository.Collection.Find(query).FirstOrDefault();
            var update = new UpdateDocument();
            bool isExit = false;
            for (int j = 0; j < oo.OrderList.Count; j++)
            {
                var od = oo.OrderList[j].OrderDetail;
                oo.OrderList[j].UserName = "大占占改呀";
                for (int i = 0; i < od.Count; i++)
                {
                    if (od[i].Id == threeID)
                    {
                        od[i].ProductName = "大占占修改了訂單21";

                        #region 先pull,再push
                        //update = new UpdateDocument {{ "$pull", 
                        //                                    new BsonDocument("OrderList."+j+".OrderDetail",
                        //                                    new BsonDocument("_id",threeID))
                        //                                 }};
                        //mongoRepository.Collection.Update(query1, update);
                        //update = new UpdateDocument {{ "$push", 
                        //                                 new BsonDocument("OrderList."+j+".OrderDetail",
                        //                                 new BsonDocument(od[i].ToDictionary()))
                        //                            }};
                        //mongoRepository.Collection.Update(query1, update);
                        #endregion

                        #region 直接set
                        update = new UpdateDocument {{ "$set",       
                                                         new BsonDocument("OrderList.$.UserName",oo.OrderList[j].UserName)
                                                    }};
                        mongoRepository.Collection.Update(query, update);

                        update = new UpdateDocument {{ "$set", 
                                                         new BsonDocument("OrderList."+j+".OrderDetail."+i,
                                                         new BsonDocument(od[i].ToDictionary()))
                                                    }};
                        mongoRepository.Collection.Update(query, update);
                        #endregion
                        isExit = true;
                        break;
                    }
                }
                if (isExit)
                    break;
            }

上面的代碼,我們看到了有兩種更新集合的方法,$pull和$push方法及$set方法,大家可以根據喜好進行選擇,都可以實現我們的目的,ToDictionary是我封裝的方法,意思是將類對象里的屬性轉換為字典,并做了mongodb的_id主鍵的處理,代碼如下

/// <summary>
        /// 將對象屬性轉換為字典
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static Dictionary<String, Object> ToDictionary(this object o)
        {
            Dictionary<String, Object> map = new Dictionary<string, object>();
            Type t = o.GetType();
            PropertyInfo[] pi = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo p in pi)
            {
                MethodInfo mi = p.GetGetMethod();

                if (mi != null && mi.IsPublic)
                {
                    if (p.Name == "Id")
                        map.Add("_id", mi.Invoke(o, new Object[] { }));
                    else
                        map.Add(p.Name, mi.Invoke(o, new Object[] { }));
                }
            }
            return map;
        }
    }

對于mongodb的探索,還在繼續...

回到目錄


文章列表




Avast logo

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


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

    IT工程師數位筆記本

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