​回到目录​

$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));

}
}
}

对于产生的结果是我们可以接受的,可以对集合属性很方便的实现更新了。

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学习笔记~对集合属性的操作_字段

以上数据结构应该算是比较复杂的了,像实体里有子实体,然后子实体里有集合,集合里又有数组,但我封装的更新还是都适用的,这点已经做过测试,请放心使用!

MongoDB学习笔记~对集合属性的操作_字段_02

欢迎大家继续关注mongodb技术!

继续关注大叔博客!

​回到目录​

 

作者:仓储大叔,张占岭,
荣誉:微软MVP