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

时间:2014-11-04 19:50:17

标签: mongodb mongodb-.net-driver

我知道之前已经问过这个问题,但我还没有找到一个有效的解决方案。我正在使用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 个答案:

答案 0 :(得分:2)

您的代码应该稍作改动:

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

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

答案 1 :(得分: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;
    }
}