使用 C# 在 MongoDB 中查询、过滤和更新多级嵌套数组
本文关键字:更新 多级 嵌套 数组 过滤 MongoDB 查询 使用 | 更新日期: 2023-09-27 18:32:11
我有这个MongoDB文档。我正在开发一个 MVC 应用程序并尝试使用 C# 更新注释数组(注释描述为"更新后注释")。我正在使用新的mongodb版本。
{
"ProjectID":1,
"ProjectName":"Project test",
"ProjectStatus":"Active",
"ProjectTasks":[
{
"ProjectTaskID":1,
"TaskShortDescription":"short task description",
"TaskLongDescription":"long task description",
"Comments":[
{
"CommentID":1,
"CommentDescription":"comment before update",
"CreatedBy":"Mike",
"UploadDocuments":{
"TaskID":null,
"CommentID":null,
"UploadDocumentID":1,
"UploadDocumentName":"first document upload"
}
}
]
}
]
}
我尝试使用这个:
var filter = Builders<Project>.Filter.And(Builders<Project>.Filter.Eq(x => x.ProjectID, projectID), Builders<Project>.Filter.ElemMatch(x => x.ProjectTasks, x => x.ProjectTaskID == projectTaskID), Builders<Project>.Filter.ElemMatch(x => x.ProjectTasks.ElementAt(-1).Comments, x => x.CommentID == comment.CommentID));
var update = Builders<Project>.Update.Set(x => x.ProjectTasks.ElementAt(-1).Comments.ElementAt(-1).CommentDescription, comment.CommentDescription );
Collection.UpdateOneAsync(filter, update, new UpdateOptions() { IsUpsert = true });
我还尝试将过滤器更改为
var filter = Builders<Project>.Filter.And(Builders<Project>.Filter.Where(p => p.ProjectID == projectID), Builders<Project>.Filter.Eq("ProjectTasks.ProjectTaskID", projectTaskID), Builders<Project>.Filter.Eq("ProjectTasks.$.Comments.$.CommentID", comment.CommentID));
对于这两种情况,我都无法查询、过滤和更新评论。
您能告诉我如何查找和更新本文档中的评论吗?任何建议都非常感谢!
你应该使用
$[] 多个位置运算符,我会尝试编写你应该为粘贴的代码使用的内容:
var baseFilter = Builders<Project>.Filter.Eq("ProjectID": 1);
var update = Builders<Project>.Update.Set("ProjectTasks.$[i].Comments.$[j].CommentDescription", comment.CommentDescription);
var arrayFilters = new List<ArrayFilterDefinition>
{
/* change the type names here if they have different names, I just guessed */
new BsonDocumentArrayFilterDefinition<ProjectTask>(new BsonDocument("i.ProjectTaskID", projectTaskID)),
new BsonDocumentArrayFilterDefinition<Comment>(new BsonDocument("j.CommentId", commentID))
};
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
await Collection.UpdateOneAsync(baseFilter, update, updateOptions);
我遇到了类似的问题 - 我需要在嵌套集合中插入一个新项目。假设我们不能更改数据结构,这个想法是找到要更新的嵌套实体的索引。然后,该实体在更新定义中变得可访问。
在给定的上下文中,我所做的如下:
var projectTaskIndex = await _mongoContext.Projects
.Find(p => p.ProjectID == projectID)
.Project(p => p.ProjectTasks.FindIndex(t => t.ProjectTaskID == projectTaskID))
.SingleOrDefaultAsync();
var updateDefinition = new UpdateDefinitionBuilder<Project>()
.AddToSet(p => p.ProjectTasks[projectTaskIndex].Comments, comment);
await _mongoContext.Projects
.UpdateOneAsync(p=> p.ProjectID == projectID, updateDefinition);
以同样的方式,可以找到注释的索引并访问注释的属性。更新定义将如下所示:
var updateDefinition = new UpdateDefinitionBuilder<Project>()
.Set(p => p.ProjectTasks[projectTaskIndex]
.Comments[commentIndex].CommentDescription,
comment.CommentDescription);
这里非常重要的一点是确保线程安全 - ProjectTasks 和 Comments 的集合不得在获取索引和实际更新之间更改。
@Cisco,你找到解决方案了吗?如果是这样,你能分享一下吗?