4

我有这个 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));

对于这两种情况,我都无法查询、过滤和更新评论。

您能告诉我如何查找和更新本文档中的评论吗?任何建议都非常感谢!

4

2 回答 2

5

您应该使用 $[] 多个位置运算符,我将尝试为您粘贴的代码编写您应该使用的内容:

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);
于 2019-01-15T12:21:38.853 回答
4

我遇到了类似的问题 - 我需要在嵌套集合中插入一个新项目。假设我们无法更改数据结构,想法是找到要更新的嵌套实体的索引。然后实体在更新定义中变得可访问。

在给定的上下文中,我所做的如下:

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,您找到解决方案了吗?如果是这样,你能分享一下吗?

于 2016-02-15T23:07:00.407 回答