如何在MongoDB中修改文档的子数组中的子元素?我正在使用适用于MongoDB的最新C#驱动程序(C#驱动程序版本:2.5,服务器版本:3.2.0),并且已经尝试从SO(也有重复的问题)和其他各种来源的多个答案中获得解决方案。事实证明,大多数解决方案都是过时的。
以下是我的示例文档:
[{
"_id" : "69c4f77d-05ef-431d-ae17-c076c6173e04",
"title" : "Root Page",
"createdAt" : ISODate("2017-12-21T12:28:00.680+0000"),
"modifiedAt" : ISODate("2017-12-26T07:18:11.165+0000"),
"pages" : [
{
"_id" : "f449dc0b-3d1b-4a59-b622-6a42ce10b147",
"title" : "Test page 1",
"slug" : "test-page-1",
"createdAt" : ISODate("2017-12-21T12:28:00.680+0000"),
"modifiedAt" : ISODate("2017-12-21T12:28:00.680+0000")
},
{
"_id" : "3d1497d7-f74c-4d88-b15c-bf2f9c736374",
"title" : "Test page 2",
"slug" : "test-page-2",
"createdAt" : ISODate("2017-12-25T11:27:55.006+0000"),
"modifiedAt" : ISODate("2017-12-25T11:27:55.006+0000")
},
{
"_id" : "6e827e2a-5a25-4343-b646-885816bb8cc4",
"title" : "Test page 3",
"slug" : "test-page-3",
"createdAt" : ISODate("2017-12-25T11:31:16.516+0000"),
"modifiedAt" : ISODate("2017-12-25T11:31:16.516+0000")
}]
},
...,
...
]
文档结构:根文档包含一个子文档数组,该子文档具有元数据和页面列表(数组)
内子文件-我试图更新的标题和塞一个的子页面内对象的页面数组,但与最新的驱动程序有没有运气这么远。
我正在使用以下过滤器和更新查询:
var filter = Builders<SubDocument>.Filter.And(Builders<SubDocument>.Filter.Eq("_id", "xxx"), Builders<SubDocument>.Filter.ElemMatch(x => x.Pages, p => p.Id == "xxx"));
var update = Builders<SubDocument>.Update
.Set("pages.$.title", "changed title")
.Set("pages.$.slug", "changed-title")
.Set("pages.$.modifiedAt", DateTime.UtcNow);
_mongoDb.Documents.UpdateOne(filter, update);
现在-此查询返回一个错误:
无效的BSON字段名称页面。$。title
我最近几个小时来的引用都说使用“ $”运算符,但它在最新的驱动程序中引发错误。
[编辑1]这是我的模型:
public class SubDocument
{
public SubDocument()
{
Id = Guid.NewGuid().ToString();
CreatedAt = DateTime.UtcNow;
ModifiedAt = DateTime.UtcNow;
Pages = new List<Page>();
}
[BsonId]
public string Id { get; set; }
[BsonElement("title")]
public string Title { get; set; }
[BsonElement("createdAt")]
public DateTime CreatedAt { get; set; }
[BsonElement("modifiedAt")]
public DateTime ModifiedAt { get; set; }
[BsonElement("pages")]
public List<Page> Pages { get; set; }
}
public class Page
{
[BsonId]
public string Id { get; set; }
[BsonElement("title")]
public string Title { get; set; }
[BsonElement("slug")]
public string Slug { get; set; }
[BsonElement("createdAt")]
public DateTime CreatedAt { get; set; }
[BsonElement("modifiedAt")]
public DateTime ModifiedAt { get; set; }
}
任何人?提前致谢!
您的代码实际上适用于mongod v3.4和驱动程序v2.5。
正如Evk在注释中所建议的那样,这是代码的强类型版本,可重构。
var filter = Builders<SubDocument>.Filter
.And(
Builders<SubDocument>.Filter.Eq(d => d.Id, "69c4f77d-05ef-431d-ae17-c076c6173e04"),
Builders<SubDocument>.Filter.ElemMatch(x => x.Pages, p => p.Id == "3d1497d7-f74c-4d88-b15c-bf2f9c736374"));
var update = Builders<SubDocument>.Update
.Set(c => c.Pages[-1].Title, "changed title")
.Set(c => c.Pages[-1].Slug, "changed slug")
.Set(c => c.Pages[-1].ModifiedAt, DateTime.UtcNow);
subDocumentsCollection.UpdateOne(filter, update);
另一种方法可能将您的子文档实体视为一个整体(面向文档的数据库鼓励采用这种方法),因此始终要完全更新该实体,并避免进行细粒度的更新(在R-DBMS的情况下更有可能)。在这种情况下,您可能会编写如下内容。
var document = subDocumentsCollection
.Find(d => d.Id == "69c4f77d-05ef-431d-ae17-c076c6173e04")
.Single();
var page = document.Pages.Single(p => p.Id == "3d1497d7-f74c-4d88-b15c-bf2f9c736374");
page.Title = "changed title";
page.Slug = "changed slug";
page.ModifiedAt = DateTime.UtcNow;
subDocumentsCollection.ReplaceOne(d => d.Id == document.Id, document);
第二种方法具有以下优点和缺点。
考虑到过早的优化是编程(这里)中所有邪恶(或至少是大多数邪恶)的根源,通常我会选择第二种方法,只有在对性能的要求非常严格或较低的情况下才退回到第一种方法。网络带宽。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句