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

C# Mongo更新数组元素(.NET驱动程序2.0),c#,.net,mongodb,C#,.net,Mongodb,编辑: 而不是寻找javascript方法来实现这一点。我正在寻找MongoDB C#2.0驱动程序来实现这一点(我知道这可能不可能;但我希望有人知道解决方案) 我正在尝试更新mongodb中主文档数组中嵌入的项的值 我正在寻找一种强类型的方法来实现这一点。我正在使用 我可以通过弹出元素,更新值,然后重新插入来实现。这感觉不对;因为我正在重写可能同时写下的内容 以下是我迄今为止尝试过但没有成功的方法: private readonly IMongoCollection<TempAgenda

编辑: 而不是寻找javascript方法来实现这一点。我正在寻找MongoDB C#2.0驱动程序来实现这一点(我知道这可能不可能;但我希望有人知道解决方案)

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

我正在寻找一种强类型的方法来实现这一点。我正在使用

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

以下是我迄今为止尝试过但没有成功的方法:

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;
}
私有只读IMongoCollection\u collection;
void Main()
{
var collectionName=“议程”;
var客户端=新的MongoClient(“mongodb://localhost:27017");
var db=client.GetDatabase(“测试”);
_collection=db.GetCollection(collectionName);
UpdateItemTitle(1,1,“你好”);
}
public void UpdateItemTitle(string agendaId、string itemId、string title){
var filter=Builders.filter.Eq(x=>x.AgendaId,AgendaId);
var update=Builders.update.Set(x=>x.Items.Single(p=>p.Id.Equals(itemId)).Title,Title);
var result=\u collection.UpdateOneAsync(filter,update.result);
}

我花了一段时间才弄明白这一点,因为在任何官方文档(或其他地方)中似乎都没有提到这一点。但是,我在他们的问题跟踪器上找到了,它解释了如何在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;
}

谢谢,这很有帮助。不过我还有一个补充,我对数组使用了上面的方法,推到一个嵌套数组,然后从一个嵌套数组中取出。我发现的问题是,如果我有一个int数组(所以不是一个对象,只是一个简单的int数组),PullFilter实际上无法工作——“无法确定序列化信息”,这很奇怪,因为它只是一个int数组。我最后做的是让它成为一个只有一个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.filter.Where(x=>x.\u id==entity.ParentID&&x.NestedArray.Any(i=>i.\u id==entity;
var update=Builders.update.PullFilter(x=>x.NestedArray.ElementAt(-1).User,Builders.Filter.Eq(f=>f.UserID,UserID));
集合(currentUser).UpdateOneAsync(筛选器,更新);
而且:

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);
var filter=Builders.filter.Where(x=>x.\u id==entity.ParentID&&x.NestedArray.Any(i=>i.\u id==entity;
var update=Builders.update.Push(x=>x.NestedArray.ElementAt(-1.Users,新用户{UserID=UserID});
集合(currentUser).UpdateOneAsync(筛选器,更新);

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

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);
var filter=Builders.filter.Where(x=>x.Id==di&&x.RemuneracionMensualActual.remuneracionactionindustrial.Any(s=>s.Id==oid));
var update=Builders.update.Set(x=>x.RemuneracionMensualActual.RemuneracionActIndustrial.ElementAt(-1).Ingreo,datos.ActividIndustrial.Ingreo)
.Set(x=>x.RemuneracionMensualactal.RemuneracionActionIndustrial.ElementAt(-1).RazonSocial,datos.ActivityIndustrial.RazonSocial)
.Set(x=>x.RemuneracionMensualactal.RemuneracionActional Industrial.ElementAt(-1).TipoNegocio,datos.ActivityIndustrial.TipoNegocio);

可能重复@BlakesSeven这不是一个c#问题?这仍然是相同的原则。匹配查询部分中的数组元素,并在更新部分中使用位置
$
运算符。我不是随便从袋子里掏出的。@BlakesSeven我可以阅读mongo文档并使用纯javascript,但是,正如我在问题中所说的,我正在寻找强类型的方法来实现这一点,据我所知,在我的C#代码中嵌入javascript字符串不是强类型的。C#仍然有一个位置运算符。这不是“javascript字符串”,而是“点符号”,在所有语言中都有效。很抱歉,在接受您的答案时太慢了。效果很好。不幸的是,它们不支持多个操作选择器:对我来说似乎很奇怪,因为这可以用来更好地隔离需要完成的更新。谢谢瑟伦。我必须说,我不喜欢他们选择的语法,因为这意味着你不能使用IEnumerable或ICollection,并迫使你使用更麻烦的IList或简单的IListarray@Buvy您应该能够使用LINQ扩展方法
ElementAt(-1)
同样如此。@SørenKruse你确实是正确的,而我刚才验证的语法非常有效。与array indexer相比,它有点麻烦,但至少我不必让我的所有域类都使用IList,这正是我所追求的。我尝试了这个解决方案,代码实际上编译时没有任何错误,但在运行时查询文档时会发生什么情况,[-1]在该数组中,将启动反向索引搜索,而不是使用位置运算符。所以-1表示数组的最后一个元素,-2表示倒数第二个元素。这并不是我们想要的,索引应该是动态的,通过位置操作符。你说的是int数组,但是这个例子仍然是一个存储复杂结构的数组。显示从int数组中删除一个元素的示例。
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);