首页 文章

更新MongoDB中的多个复杂数组元素

提问于
浏览
0

我知道之前已经问过这个问题,但我还没有找到一个有效的解决方案 . 我正在使用MongoDB C#驱动程序,尽管这是关于MongoDB操作的一般问题 .

我有一个文档结构,看起来像这样:

field1: value1
field2: value2
...
users: [ {...user 1 subdocument...}, {...user 2 subdocument...}, ... ]

一些事实:

  • 每个用户子文档包含更多子数组和子文档(因此它们相当复杂) .

  • 普通用户数组只包含大约5个元素,但在最坏的情况下可以超过100个 .

  • 在该系统中,每天可以对多个用户进行数千次更新操作,每次一次在一个文档上 . 由于数据大小较大,较大的阵列将接收更频繁的更新 .

我试图弄清楚如何有效地做到这一点 . 从我所听到的,你不能一次性将几个数组元素直接设置为新值,所以我不得不尝试别的东西 .

我尝试使用$ pullAll / $ AddToSet $每个操作来删除旧数组并用修改后的数组替换它 . 我知道$ pullall只能删除我需要的元素,但我想保留元素的顺序 .

C#代码:

try
{
    WriteConcernResult wcr = collection.Update(query,
    Update.Combine(Update.PullAll("users"),
    Update.AddToSetEach("users", newUsers.ToArray())));
}
catch (WriteConcernException wce)
{
    return wce.Message;
}

在这种情况下,newUsers是 List<BsonValue> 转换为数组 . 但是我收到以下异常消息:

无法同时更新“用户”和“用户”

从它的外观来看,我不能在同一个写操作中的同一个字段上使用两个更新语句 .

我也尝试了 Update.Set("users", newUsers.ToArray()) ,但显然Set语句不适用于数组,只是基本值:

参数2:无法从'MongoDB.Bson.BsonValue []'转换为'MongoDB.Bson.BsonValue'

那么我尝试将该数组转换为BsonDocument:

Update.Set("users", newUsers.ToArray().ToBsonDocument());

得到了这个:

无法将Array值写入BSON文档的根级别 .

我可以尝试替换整个文档,但这似乎有点矫枉过正,并且效率肯定不高 .

所以我现在唯一能想到的就是运行两个单独的写操作:一个用于删除不需要的旧用户,另一个用新版本替换它们:

WriteConcernResult wcr = collection.Update(query, Update.PullAll("users"));
WriteConcernResult wcr = collection.Update(query, Update.AddToSetEach("users", newUsers.ToArray()));

这是我最好的选择吗?或者还有另一种更好的方法吗?

2 回答

  • 2

    您的代码应该稍有改动:

    Update.Set("users", new BsonArray(newUsers));
    

    BsonArray是一个BsonValue,其中一个文档数组不是,我们不像我们做其他原始值那样隐式转换数组 .

  • 0

    这个扩展方法解决了我的问题:

    public static class MongoExtension
    {
        public static BsonArray ToBsonArray(this IEnumerable list)
        {
            var array = new BsonArray();
            foreach (var item in list)
                array.Add((BsonValue) item);
    
            return array;
        }
    }
    

相关问题