C# 尝试更新嵌套数组时出现Mongo错误:找不到标识符的数组筛选器
我正在尝试更新Mongo中的一个文档,该文档表示具有以下场景的社区C# 尝试更新嵌套数组时出现Mongo错误:找不到标识符的数组筛选器,c#,mongodb,mongodb-.net-driver,C#,Mongodb,Mongodb .net Driver,我正在尝试更新Mongo中的一个文档,该文档表示具有以下场景的社区 一个社区有一组街区 一个街区有许多楼层 一层楼有许多门 门具有标签名称的集合 给定必须放置在每个门中的文档Id和标签信息,我想使用MongoDb C#driver v2.10.4和mongo:latest更新嵌套列表(多个级别)。 我已经阅读了关于数组过滤器的文档,但是我不能让它工作 我创建了一个,在自述文件中有关于如何运行集成测试的说明,还创建了一个带有docker的本地MongoDB。 但作为总结,我的方法将标签分组,这
- 一个社区有一组街区
- 一个街区有许多楼层
- 一层楼有许多门
- 门具有标签名称的集合
mongo:latest
更新嵌套列表(多个级别)。
我已经阅读了关于数组过滤器的文档,但是我不能让它工作
我创建了一个,在自述文件中有关于如何运行集成测试的说明,还创建了一个带有docker的本地MongoDB。
但作为总结,我的方法将标签分组,这样我就可以在所需的门上批量放置地名,然后它迭代这些组,并在Mongo上更新特定文档,在某些级别的深嵌套对象中设置所需的值。我想不出比这更有效的方法了
上述回购协议中的所有代码
DB文件:
public class Community
{
public Guid Id { get; set; }
public IEnumerable<Block> Blocks { get; set; } = Enumerable.Empty<Block>();
}
public class Block
{
public string Name { get; set; } = string.Empty;
public IEnumerable<Floor> Floors { get; set; } = Enumerable.Empty<Floor>();
}
public class Floor
{
public string Name { get; set; } = string.Empty;
public IEnumerable<Door> Doors { get; set; } = Enumerable.Empty<Door>();
}
public class Door
{
public string Name { get; set; } = string.Empty;
public IEnumerable<string> LabelNames = Enumerable.Empty<string>();
}
下面是一个关于嵌套结构在数据库中的外观的更直观的示例。请注意,我要更新的值是LabelNames
,它是一个字符串数组。
如果我不能更改存储库的方法签名,我将非常感谢您对我的帮助,并就这是否是正确的方法提出建议
解决方案结果: 谢谢你的快速回答@mickl,它工作得很好。
结果与建议完全一致。该
$[{houseBlockName}]
需要一个标识符,该标识符充当占位符,并且在数组过滤器中定义了相应的过滤器。您似乎试图直接传递不正确的筛选器值
您的C#代码可以如下所示:
var houseBlockName = house.Key.BlockId;
var houseFloorName = house.Key.FloorId;
var houseDoorName = house.Key.DoorId;
var names = house.Select(x => x.Name).ToList();
var update = Builders<Community>.Update.Set("Blocks.$[block].Floors.$[floor].Doors.$[door].LabelNames", names);
var arrayFilters = new List<ArrayFilterDefinition>();
ArrayFilterDefinition<BsonDocument> blockFilter = new BsonDocument("block.Name", new BsonDocument("$eq", houseBlockName));
ArrayFilterDefinition<BsonDocument> floorFilter = new BsonDocument("floor.Name", new BsonDocument("$eq", houseFloorName));
ArrayFilterDefinition<BsonDocument> doorFilter = new BsonDocument("door.Name", new BsonDocument("$eq", houseDoorName));
arrayFilters.Add(blockFilter);
arrayFilters.Add(floorFilter);
arrayFilters.Add(doorFilter);
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
var result = _communities.UpdateOne(filter, update, updateOptions);
var houseBlockName=house.Key.BlockId;
var house floorName=house.Key.floorrid;
var houseDoorName=house.Key.DoorId;
var Name=house.Select(x=>x.Name.ToList();
var update=Builders.update.Set(“Blocks.$[block].Floors.$[floor].Doors.$[door].LabelNames”,name);
var arrayFilters=新列表();
ArrayFilterDefinition blockFilter=新BsonDocument(“block.Name”,新BsonDocument($eq,houseBlockName));
ArrayFilterDefinition floorFilter=新的BsonDocument(“floor.Name”,新的BsonDocument($eq,houseFloorName));
ArrayFilterDefinitionDoorFilter=新的BsonDocument(“door.Name”,新的BsonDocument($eq,houseDoorName));
arrayFilters.Add(块过滤器);
阵列过滤器。添加(地板过滤器);
阵列过滤器。添加(门过滤器);
var updateOptions=newupdateoptions{ArrayFilters=ArrayFilters};
var result=_communities.UpdateOne(过滤器、更新、更新选项);
{
var filterCompany=Builders.Filter.Eq(x=>x.Id,timekeeping.CompanyID);
var update=Builders.update.Set(“lstPersonal.$[i].Timekeeping.$[j].CheckOutDate”,DateTime.UtcNow);
var arrayFilters=新列表
{
新BsonDocumentArrayFilterDefinition(新BsonDocument(“i.MacAddress”,新BsonDocument($eq,timekeeping.MacAddress)),
新BsonDocumentArrayFilterDefinition(新BsonDocument(“j.Id”,新BsonDocument(“eq”,timeKeeping.Id)))
};
var updateOptions=newupdateoptions{ArrayFilters=ArrayFilters};
var updateResult=await_companys.UpdateOneAsync(filterCompany,update,updateOptions);
返回updateResult.ModifiedCount!=0;
}
它工作得非常好!在我的问题中添加了一个更新,只是为了链接到与您的解决方案相同的回购协议。您能否提供一些关于问题是什么以及您的代码是如何解决问题的解释?另外,由于您缺少函数名,因此不清楚代码的确切位置/它替换的是OP中的哪个函数。我找到了这个问题的解决方案:我找到了这个问题的解决方案
MongoDB.Driver.MongoWriteException with the message "A write operation resulted in an error.
No array filter found for identifier 'Block 1' in path 'Blocks.$[Block 1].Floors.$[Ground Floor].Doors.$[A].LabelNames'"
var houseBlockName = house.Key.BlockId;
var houseFloorName = house.Key.FloorId;
var houseDoorName = house.Key.DoorId;
var names = house.Select(x => x.Name).ToList();
var update = Builders<Community>.Update.Set("Blocks.$[block].Floors.$[floor].Doors.$[door].LabelNames", names);
var arrayFilters = new List<ArrayFilterDefinition>();
ArrayFilterDefinition<BsonDocument> blockFilter = new BsonDocument("block.Name", new BsonDocument("$eq", houseBlockName));
ArrayFilterDefinition<BsonDocument> floorFilter = new BsonDocument("floor.Name", new BsonDocument("$eq", houseFloorName));
ArrayFilterDefinition<BsonDocument> doorFilter = new BsonDocument("door.Name", new BsonDocument("$eq", houseDoorName));
arrayFilters.Add(blockFilter);
arrayFilters.Add(floorFilter);
arrayFilters.Add(doorFilter);
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
var result = _communities.UpdateOne(filter, update, updateOptions);
{
var filterCompany = Builders<CompanyInfo>.Filter.Eq(x => x.Id, Timekeepping.CompanyID);
var update = Builders<CompanyInfo>.Update.Set("LstPersonnel.$[i].Timekeeping.$[j].CheckOutDate", DateTime.UtcNow);
var arrayFilters = new List<ArrayFilterDefinition>
{
new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("i.MacAddress",new BsonDocument("$eq", Timekeepping.MacAddress) )),
new BsonDocumentArrayFilterDefinition<BsonDocument>(new BsonDocument("j.Id", new BsonDocument("$eq", timeKeeping.Id)))
};
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters};
var updateResult = await _companys.UpdateOneAsync(filterCompany, update, updateOptions);
return updateResult.ModifiedCount != 0;
}