Mongo更新数组元素(.NET驱动程序2.0)

时间:2015-07-16 12:05:44

标签: c# .net mongodb

编辑: 不寻找这样做的javascript方式。我正在寻找MongoDB C#2.0驱动程序的方法(我知道它可能不可能;但我希望有人知道解决方案)。

我正在尝试更新mongodb中主文档中数组中嵌入的项的值。

我正在寻找一种强有力的方式来做到这一点。我正在使用Mongodb c# 2.0 driver

我可以通过弹出元素,更新值然后重新插入来实现。这感觉不对;因为我正在覆盖可能在此期间写的内容。

这是我到目前为止所尝试的但没有运气:

private readonly IMongoCollection<TempAgenda> _collection;

void Main()
{
    var collectionName = "Agenda";
    var client = new MongoClient("mongodb://localhost:27017");
    var db = client.GetDatabase("Test");
    _collection = db.GetCollection<TempAgenda>(collectionName);
    UpdateItemTitle(1, 1, "hello");
}

public void UpdateItemTitle(string agendaId, string itemId, string title){
    var filter = Builders<TempAgenda>.Filter.Eq(x => x.AgendaId, agendaId);
    var update = Builders<TempAgenda>.Update.Set(x => x.Items.Single(p => p.Id.Equals(itemId)).Title, title);
    var result = _collection.UpdateOneAsync(filter, update).Result;
}

3 个答案:

答案 0 :(得分:46)

我花了一些时间来弄明白这一点,因为它似乎没有在任何官方文档中(或其他任何地方)提及。但我在问题跟踪器上找到了this,它解释了如何将位置运算符$与C#2.0驱动程序一起使用。

这应该做你想要的:

public void UpdateItemTitle(string agendaId, string itemId, string title){
    var filter = Builders<TempAgenda>.Filter.Where(x => x.AgendaId == agendaId && x.Items.Any(i => i.Id == itemId));
    var update = Builders<TempAgenda>.Update.Set(x => x.Items[-1].Title, title);
    var result = _collection.UpdateOneAsync(filter, update).Result;
}

请注意,您的Item.Single()子句已更改为Item.Any()并已移至过滤器定义。

[-1].ElementAt(-1)显然是专门处理的(实际上一切都是&lt; 0)并且将被位置运算符$替换。

以上内容将被翻译为此查询:

db.Agenda.update({ AgendaId: 1, Items.Id: 1 }, { $set: { Items.$.Title: "hello" } })

答案 1 :(得分:1)

谢谢,这很有帮助。我有一个补充,我已经将上面的数据用于数组,推送到嵌套数组并从中拉出。我发现的问题是,如果我有一个int数组(所以不是一个对象,只是一个简单的int数组),PullFilter实际上并没有工作 - &#34;无法确定序列化信息&#34;这很奇怪,因为它只是一组整数。我最终做的是将它作为一个只有一个int参数的对象数组,它们都开始工作了。可能是一个错误,或者可能是我缺乏理解。无论如何,由于我一直在努力寻找有关使用C#2.0驱动程序提取和推送到嵌套对象数组的信息,我认为我应该在这里发布我的发现,因为他们使用上述语法。

var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id));
var update = Builders<MessageDto>.Update.PullFilter(x => x.NestedArray.ElementAt(-1).User, Builders<User>.Filter.Eq(f => f.UserID, userID));
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update);

还有:

var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id));
var update = Builders<MessageDto>.Update.Push(x => x.NestedArray.ElementAt(-1).Users, new User { UserID = userID });
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update);

答案 2 :(得分:-2)

更新Document或子数组的正确方法如下:

var filter = Builders<Declaracion>.Filter.Where(x => x.Id == di && x.RemuneracionMensualActual.RemuneracionActIndustrial.Any(s => s.Id == oid));

        var update = Builders<Declaracion>.Update.Set(x => x.RemuneracionMensualActual.RemuneracionActIndustrial.ElementAt(-1).Ingreso, datos.ActividadIndustrial.Ingreso)
            .Set(x => x.RemuneracionMensualActual.RemuneracionActIndustrial.ElementAt(-1).RazonSocial, datos.ActividadIndustrial.RazonSocial)
            .Set(x => x.RemuneracionMensualActual.RemuneracionActIndustrial.ElementAt(-1).TipoNegocio, datos.ActividadIndustrial.TipoNegocio);