繁体   English   中英

如何通过一次调用使用mongo db C#驱动程序添加嵌套元素或更新属性

[英]How can you add a nested element or update a property using mongo db C# driver with one call

我试图有一个数据库调用要么添加一个元素到嵌套数组或如果该元素已经存在增加一个计数器。 在这种情况下,我们试图查看是否存在匹配的SubDocument,如果没有找到,我们想要将该子文档添加到SubDocs列表中(如果找到一个,我们想要增加该列表中找到的SubDocument上的Count prop)。

我们正在寻找一个这样做的调用的原因是因为我们将有几个服务可能同时尝试做同样的事情。

    public class Document
    {
        [BsonId]
        [BsonIgnoreIfDefault]
        [BsonRepresentation(BsonType.ObjectId)]
        public string DocumentID { get; set; }

        public int Date { get; set; }
        public List<SubDocument> SubDocs { get; set; }
    }

    public class SubDocument
    {
        public string Count { get; set; }
        public string Name { get; set; }
    }

任何帮助将不胜感激。 我们使用的是.NET驱动程序2.8.1

我能够使用find执行此操作,如果找到它则更新计数器。 但到目前为止的测试显示,如果多个服务正在这样做,将会错过计数。

它可以使用一个bulkWrite命令来完成,该命令结合了两个更新命令,如下所示:

db.Document.bulkWrite([
    { updateOne: {
            filter: {
                "_id": ObjectId("5d455b8f2d686e2980829d1b"),
                "SubDocs": {
                    "$not": {
                        "$elemMatch": {
                            "Name": "iron man" } } } },
            update: {
                "$push": {
                    "SubDocs": {
                        "Count": NumberInt("0"),
                        "Name": "iron man" } } } }
    },
    { updateOne: {
            filter: {
                "_id": ObjectId("5d455b8f2d686e2980829d1b"),
                "SubDocs": {
                    "$elemMatch": {
                        "Name": "iron man"
                    } } },
            update: {
                "$inc": {
                    "SubDocs.$.Count": NumberInt("1")
                } } } }])

这是一个多线程测试程序,在我的开发环境中似乎没有任何并发​​问题。

 using MongoDB.Entities; // PM> Install-Package MongoDB.Entities using System.Linq; using System.Threading.Tasks; namespace StackOverflow { public class Document : Entity { public SubDocument[] SubDocs { get; set; } = new SubDocument[] { }; } public class SubDocument { public int Count { get; set; } public string Name { get; set; } } public class Program { private static void Main(string[] args) { new DB("test"); var doc = new Document(); doc.Save(); var subDoc = new SubDocument { Name = "iron man" }; Parallel.ForEach(Enumerable.Range(1, 20), _ => { var bulk = DB.Update<Document>(); bulk.Match(d => d.ID == doc.ID && !d.SubDocs.Any(s => s.Name == subDoc.Name)) .Modify(b => b.Push(d => d.SubDocs, subDoc)) .AddToQueue(); bulk.Match(d => d.ID == doc.ID && d.SubDocs.Any(s => s.Name == subDoc.Name)) .Modify(b => b.Inc(d => d.SubDocs[-1].Count, 1)) .AddToQueue(); bulk.Execute(); }); } } } 

我相信Mongo 4支持原子事务 ,因此探索的途径是尝试使用它们。

如果你想在C#端做这个,当你在检查文件是否存在/更新计数器的逻辑时,确保一次只有一个服务更新计数器的一种方法是将逻辑包装在一个关键部分(即锁定)。

有关如何执行此操作的示例,请查看https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM