gpt4 book ai didi

c# - 如何使用 C# 驱动程序更新 MongoDB 数组中的子文档

转载 作者:太空宇宙 更新时间:2023-11-03 20:58:33 24 4
gpt4 key购买 nike

如何在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")
}]
},
...,
...
]

文件结构:根文档包含一个子文档数组,其中包含元数据和页面列表(数组)

在子文档内 - 我正在尝试更新 pages< 内的 child page 对象的 titleslug/strong> 阵列,但到目前为止,最新的驱动程序还没有运气。

我正在使用以下过滤器和更新查询:

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

现在 - 这个查询返回一个错误:

Invalid BSON field name pages.$.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);

第二种方法具有以下优点和缺点。

优点

  • 更新发生在域层(可能通过非常合适的方法),从而允许执行所有域规则并防止脏数据进入数据库;因此它更面向对象
  • 由于代码是面向领域的,所以它更简单并且不依赖于数据库内部。

缺点

  • 此方法需要对数据库进行两次点击(一次用于读取,一次用于更新);
  • 如果您的实体很大,网络必须传输比严格需要更多的数据。

考虑到过早的优化是编程中万恶之源(或至少是万恶之源)(here),通常我会选择第二种方法,回到第一个仅在非常严格的性能要求或低网络带宽的情况下。

关于c# - 如何使用 C# 驱动程序更新 MongoDB 数组中的子文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47977175/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com