MongoDB學習筆記~對集合屬性的操作
阿新 • • 發佈:2018-12-30
$unset清除元素
請注意在單個數組元素上使用$unset的結果可能與你設想的不一樣。其結果只是將元素的值設定為null,而非刪除整個元素。要想徹底刪除某個陣列元素,可以用$pull 和$pop操作符。
$addToSet和$push的區別
該兩者的功能都是給陣列新增一個值。但是兩者之間有區別,$addToSet要新增的值如果不存在才進行新增操作,但是push只新增一個值;例如:
tags = [“zzl”,”dudu”]
如果執行db.collection.update({},{$push:{tag:"laozhao"}}) 結果就是 [“laozhao”,”zzl”,“dudu”]
如果執行db.collection.update({},{$addToSet:{tag:"zzl"}}) 結果不變
關於Update.Combine集合更新注意點
對於Update.Combine我們可以把需要更新的欄位合併到列表List<UpdateDefinition<T>>()中,最後一起進行更新,而這對於集合屬性來說,需要注意一下,我們需要為集合屬性元素使用PushEach進行新增,而不是Push,因為使用Push會將前一個元素覆蓋掉,而只保留最後的元素(集合裡的),所以需要使用PushEach來代替它,程式碼如下:
[TestMethod]public void Push() { var filter = Builders<Dog>.Filter.Eq(i => i.Id, "5850b0bdebb91a3184f90d3d"); //更新所需要的欄位 var updateList = new List<UpdateDefinition<Dog>>(); //更新需要集合型別的欄位 var dogHistoryList = new List<DogHistory>();//新增元素到集合屬性 dogHistoryList.Add(new DogHistory { HistoryName = "四虎子3", IsHealth = false, Adderss = new Adderss("廣東", "深圳", "沿海") }); dogHistoryList.Add(new DogHistory { HistoryName = "四虎子4", IsHealth = false, Adderss = new Adderss("廣東", "深圳", "沿海") }); //將需要更新集合物件新增到updateList裡 updateList.Add(Builders<Dog>.Update.PushEach(i => i.DogHistory, dogHistoryList)); MongoDbClient.MongoManager<Dog>.Instance.UpdateOne( filter, Builders<Dog>.Update.Combine(updateList)); }
Update倉儲的優化
大叔對於這一點,也把它封裝到了Lind.DDD.Repositories.Mongo的倉儲裡,完善了Update操作,修改了之前的遞迴處理邏輯,程式碼反而更簡潔了,原理就是使用$set直接把原資料覆蓋即可。
/// <summary> /// 版本二:遞迴構建Update操作串 /// 主要功能:實現List子屬性的push操作 /// </summary> /// <param name="fieldList"></param> /// <param name="property"></param> /// <param name="propertyValue"></param> /// <param name="item"></param> /// <param name="father"></param> private void GenerateRecursionSet( List<UpdateDefinition<TEntity>> fieldList, PropertyInfo property, object propertyValue, TEntity item, string father ) { //複雜型別 if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && propertyValue != null) { //集合 if (typeof(IList).IsAssignableFrom(propertyValue.GetType())) { var arr = propertyValue as IList; if (arr != null && arr.Count > 0) { if (string.IsNullOrWhiteSpace(father)) fieldList.Add(Builders<TEntity>.Update.Set(property.Name, arr)); else fieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, arr)); } } //實體 else { foreach (var sub in property.PropertyType.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { if (string.IsNullOrWhiteSpace(father)) GenerateRecursionSet(fieldList, sub, sub.GetValue(propertyValue), item, property.Name); else GenerateRecursionSet(fieldList, sub, sub.GetValue(propertyValue), item, father + "." + property.Name); } } } //簡單型別 else { if (property.Name != EntityKey)//更新集中不能有實體鍵_id { if (string.IsNullOrWhiteSpace(father)) fieldList.Add(Builders<TEntity>.Update.Set(property.Name, propertyValue)); else fieldList.Add(Builders<TEntity>.Update.Set(father + "." + property.Name, propertyValue)); } } }
對於產生的結果是我們可以接受的,可以對集合屬性很方便的實現更新了。
dog.Des.Worker = new string[] { "engineer", "coder" }; dog.Des.Address = new List<Adderss> { new Adderss("beijing","fangshan","liangxiang",new string[]{"zhaojiaogan","Road100","No.300"}), new Adderss("北京","大興","西紅門",new string[]{"理想城","大滿貫","4號樓"}), };
產生的結果如下
以上資料結構應該算是比較複雜的了,像實體裡有子實體,然後子實體裡有集合,集合裡又有陣列,但我封裝的更新還是都適用的,這點已經做過測試,請放心使用!
歡迎大家繼續關注mongodb技術!
繼續關注大叔部落格!