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

wlwcrazw  于 2023-03-13  发布在  .NET
关注(0)|答案(4)|浏览(93)

编辑:不是在寻找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;
}
u59ebvdq

u59ebvdq1#

我花了一段时间才弄明白这个问题,因为它似乎没有在任何官方文档(或其他地方)中提到。然而,我确实在他们的问题跟踪器上找到了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)显然被特殊处理(实际上所有内容都〈0)并且将被位置算子$代替。
上述内容将转换为以下查询:

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

xhv8bpkk2#

谢谢,这很有帮助。我有一个补充,我已经使用了上面的数组,推到一个嵌套数组和从一个嵌套数组拉。我发现的问题是,如果我有一个int数组(所以不是一个物体,只是一个简单的int数组),PullFilter实际上没有工作-“无法确定序列化信息”,这很奇怪,因为它只是一个int数组。最后我把它变成了一个只有一个int参数的对象数组,然后一切都开始工作了。可能是一个bug,也可能是我缺乏理解。无论如何,当我努力寻找关于用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);
lfapxunr

lfapxunr3#

在较新的驱动程序中,ElementAt(-1)可能不再受支持。我有过带有(-1)的代码,在转到.NET6MongoDB Driver 2.19.0时停止工作
他们引入了ExtensionMethods来代替:

x.A.FirstMatchingElement() => "A.$"
x.A.AllElements() => "A.$[]"
x.A.AllMatchingElements("identifier") => "A.$[identifier]"
shyt4zoc

shyt4zoc4#

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

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

相关问题