我有一个用例,其中视图允许用户更新多个对象并立即提交,如何使这个原子化?
{_id: parent,
childrenA: [
{_id: child1, property: "update-me", property2: "leave-alone"},
{_id: child2, property: "leave-alone", property2: "update-me"}
],
propertyA: "update-me",
propertyB: "leave-alone", //someone else needs to be able to update this concurrently with this change.
childrenB:[
{property: "update-me", property2: "leave-alone"},
{property: "leave-alone", property2: "update-me"}
],
}
属性可以是也可以不是另一个嵌套对象数组。 这有可能通过编程吗?
编辑:我需要提及的是,我无法可靠地更新整个文档 在某些情况下,可以替换嵌入式文档(可能是地址)
但是,我需要汇总更改列表,例如[{"child[Id=child1].FirstName", "newName"},{"child[Id=child3].LastName", "newName"}
(不一定是该语法,而是更改字典)
答案 0 :(得分:1)
据我所知,可以有一个限制。如果我错了,请有人纠正我。这是更新命令:
db.Parents.update(
{
"_id": ObjectId("5cf7391a1c86292244c4424e"),
"ChildrenA": {
"$elemMatch": {
"_id": ObjectId("5cf7391a1c86292244c4424c")
}
}
},
{
"$set": {
"ChildrenA.$.Property": "UPDATED",
"PropertyA": "UPDATED",
"ChildrenB.0.Property": "UPDATED",
"ChildrenB.1.Property2": "UPDATED"
}
}
)
如您所见,您必须使用$elemMatch
通过ID定位嵌套的子级。而且据我所知,您在一个更新命令中只能有一个$ elemMatch(如果我错了,请纠正我)。
这是生成上述更新命令的c#代码。它使用的是MongoDB.Entities,这是我所创建的便利库。
using MongoDB.Entities;
namespace StackOverflow
{
public class Program
{
public class Parent : Entity
{
public ChildA[] ChildrenA { get; set; }
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public ChildB[] ChildrenB { get; set; }
}
public class ChildA : Entity
{
public string Property { get; set; }
public string Property2 { get; set; }
}
public class ChildB
{
public string Property { get; set; }
public string Property2 { get; set; }
}
static void Main(string[] args)
{
new DB("test");
var childA = new ChildA { Property = "update-me", Property2 = "leave-me-alone" };
var childB = new ChildA { Property = "leave-alone", Property2 = "update-me" };
childA.Save(); childB.Save();
var parent = new Parent
{
ChildrenA = new[] { childA, childB },
PropertyA = "update-me",
PropertyB = "leave-me-alone",
ChildrenB = new[] {
new ChildB{ Property = "update-me", Property2 = "leave-me-alone"},
new ChildB{ Property = "leave-alone", Property2 = "update-me"}
}
};
parent.Save();
DB.Update<Parent>()
.Match(
f => f.Eq(p => p.ID, parent.ID) &
f.ElemMatch(
x => x.ChildrenA,
x => x.ID == childA.ID))
.Modify(x => x.ChildrenA[-1].Property, "UPDATED")
.Modify(x => x.PropertyA, "UPDATED")
.Modify(x => x.ChildrenB[0].Property, "UPDATED")
.Modify(x => x.ChildrenB[1].Property2, "UPDATED")
.Execute();
}
}
}
答案 1 :(得分:1)
您可以使用以下3.4版表格
db.Collection.findAndModify({
query: { "_id" : "parent"},
update: { $set: {propertyA: "update-me" , "childrenA.$[childrenAelemnt].property" : "update-me" , "childrenB.$[childrenB2elemnt].property2" : "update-me"
},
arrayFilters: [ {"childrenAelemnt._id": "child1"},{"childrenBelemnt.property2": "leave-alone"} , {"childrenB2elemnt.property": "leave-alone"} ]})
childrenB数组中是否有一个ID字段。它将变得更容易,语法也不会保持一致