【问题标题】:Update/Delete a sub document in mongodb using C# driver使用 C# 驱动程序更新/删除 mongodb 中的子文档
【发布时间】:2013-01-14 05:23:49
【问题描述】:

我有 2 节课:

public class Vote
{
    public string VoteId { get; set; }
    public string Question { get; set; }
    public List<VoteAnswer> AnswerList { get; set; }
}

还有:

public class VoteOption
{
    public string OptionId { get; set; }
    public string OptionName { get; set; }
    public double VoteCount { get; set; }
}

如何在Vote 中更新/删除VoteOption,其中VoteId = voteIdOptionId = optionId?使用C#驱动。

首先我通过以下方式获得 VoteOption:

        var v = col.FindOneAs<Vote>(Query.EQ("VoteID", voteId));
        VoteOption vo = v.AnswerList.Find(x => x.OptionId == optionId);

结束给它设置一些值:

vo.OptionName = "some option chose";
vo.VoteCount = 1000;

但我不知道下一步如何将此vo 更新为Vote parent

而且,如果我想删除这个vo,请告诉我!

MongoDB 中的数据是这样的:

{
  "_id" : "460b3a7ff100",
  "Question" : "this is question?",
  "AnswerList" : [{
      "OptionId" : "1",
      "OptionName" : "Option 1",
      "VoteCount" : 0.0
    }, {
      "OptionId" : "2",
      "OptionName" : "Option 2",
      "VoteCount" : 0.0
    }, {
      "OptionId" : "3",
      "OptionName" : "Option 3",
      "VoteCount" : 0.0
    }
    }]
}

【问题讨论】:

标签: c# mongodb mongodb-.net-driver


【解决方案1】:

要更新子文档,您可以使用:

var update = Update.Set("AnswerList.$.OptionName", "new").Set("AnswerList.$.VoteCount", 5);
collection.Update(Query.And(Query.EQ("_id", new BsonObjectId("50f3c313f216ff18c01d1eb0")), Query.EQ("AnswerList.OptionId", "1")), update);

分析器:

"query" : { "_id" : ObjectId("50f3c313f216ff18c01d1eb0"), "AnswerList.OptionId" : "1" },
"updateobj" : { "$set" : { "AnswerList.$.OptionName" : "new", "AnswerList.$.VoteCount" : 5 } }

并删除:

var pull = Update<Vote>.Pull(x => x.AnswerList, builder => builder.EQ(q => q.OptionId, "2"));
collection.Update(Query.And(Query.EQ("_id", new BsonObjectId("50f3c313f216ff18c01d1eb0")), Query.EQ("AnswerList.OptionId", "2")), pull);

分析器:

"query" : { "_id" : ObjectId("50f3c313f216ff18c01d1eb0"), "AnswerList.OptionId" : "2" },
"updateobj" : { "$pull" : { "AnswerList" : { "OptionId" : "2" } } }

另一种方法是使用修改后的子集合更新父文档。

【讨论】:

  • 直接更新父级是一个不好的建议。如果“user1”正在更改子文档 optionId: 1 而另一个用户同时更改子文档 optionId: 2 怎么办?
【解决方案2】:
// Example function for update like count add like user  using c#    
public PostModel LikeComment(LikeModel like)
{
    PostModel post = new PostModel();

    _client = new MongoClient();
    _database = _client.GetDatabase("post");
    var collection = _database.GetCollection<PostModel>("post");

    var _filter = Builders<PostModel>.Filter.And(
    Builders<PostModel>.Filter.Where(x => x.PostId == like.PostId),
    Builders<PostModel>.Filter.Eq("Comments.CommentId", like.CommentId));

    var _currentLike = collection.Find(Builders<PostModel>.Filter.Eq("PostId", like.PostId)).FirstOrDefault().Comments.Find(f => f.CommentId == like.CommentId).Like;

    var update = Builders<PostModel>.Update.Set("Comments.$.Like", _currentLike + 1);
    collection.FindOneAndUpdate(_filter, update);

    var addUser = Builders<PostModel>.Update.Push("Comments.$.LikeUsers", like.UserId);
    collection.FindOneAndUpdate(_filter, addUser);

    var _findResult = collection.Find(_filter).FirstOrDefault();

    return _findResult;
}

【讨论】:

    【解决方案3】:
    //Delete comment
    public PostModel delcomment(int postId, int commentId)
    {
        _client = new MongoClient();
        _database = _client.GetDatabase("post");
        var collection = _database.GetCollection<PostModel>("post");
    
        var filter = Builders<PostModel>.Filter.Eq("PostId", postId);
    
        var update = Builders<PostModel>.Update.PullFilter("Comments",
        Builders<Comments>.Filter.Eq("CommentId", commentId));
    
        collection.FindOneAndUpdate(filter, update);
    
        var _findResult = collection.Find(filter).FirstOrDefault();
        return _findResult;
    }
    

    【讨论】:

      【解决方案4】:

      迟到的答案,但这是你在没有字符串的情况下如何做到的。如果您修改您的属性代码将无法编译。第一次在生产代码中使用表达式尝试!他们太棒了!

      型号:

      class Phone
      {
        public string _id { get; set; }
        public string Name { get; set; }
        public DateTime DateCreated { get; set; }
      
                  // Contain multiple lines as subdocument
        public List<Line> Lines { get; set; }
      }
      
      class Line
      {
         public string Name { get; set; }
         public string PhoneNumber { get; set; }
      }
      

      代码:这是我在不依赖字符串的情况下创建更新语句的方式。

      var update = new UpdateDocument<Phone>();
      
      // set filter
      update.SetFilter(x => x._id == "123456789");
      
      update.AddValueToUpdate(p => p.Name, "New Name");
      update.AddValueToUpdate(p => p.Lines[0].Name, "Line 1");
      update.AddValueToUpdate(p => p.Lines[1].Name, "Line 2");
      update.AddValueToUpdate(p => p.DateCreated, DateTime.UtcNow);
      
      
      var updateQuery = update.Build();
      

      这创造了这个!这就是您需要传递给 mondo 才能进行更新的内容

      { "_id" : "123456789" },
      {$set:
        {"Name":"New Name","Lines.0.Name":"Line 1","Lines.1.Name":"Line 2","DateCreated":ISODate("2021-04-30T16:04:59.332Z")}
      }
      

      如果您希望该代码在此处工作,请使用辅助类:

      
      using MongoDB.Bson;
      using System.Linq.Expressions;
      using MongoDB.Bson.Serialization;
      
      class UpdateDocument<T>
      {
          /// <summary>
          ///     _id of document to update. 
          /// </summary>
          private string _filter;
      
          /// <summary>
          ///     Example:
          ///     FirstName, Antonio
          ///     Education.Elementary.Year, 2004
          /// </summary>
          private List<KeyValuePair<string, object>> _valuesToUpdate { get; set; } = new List<KeyValuePair<string, object>>();
      
          public void SetFilter(Expression<Func<T, bool>> filterDefinition)
          {
              var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<T>();
              var where = Builders<T>.Filter.Where(filterDefinition).Render(documentSerializer, BsonSerializer.SerializerRegistry);
              _filter = where.ToJson();
          }
      
          public void AddValueToUpdate(string name, object value)
          {
              _valuesToUpdate.Add(new KeyValuePair<string, object>(name, value));
          }
      
          public void AddValueToUpdate(Expression<Func<T, object>> name, object value)
          {
              var memberExpression = name.Body as MemberExpression;
              if (memberExpression == null)
              {
                  var unaryExpression = name.Body as UnaryExpression;
                  if (unaryExpression != null && unaryExpression.NodeType == ExpressionType.Convert)
                      memberExpression = unaryExpression.Operand as MemberExpression;
              }
      
              var result = memberExpression.ToString();
              result = result.Substring(result.IndexOf('.') + 1);
      
              if (result.Contains("get_Item"))
                  result = Regex.Replace(result, @"(?x) get_Item \( (\d+) \)", m => $"{m.Groups[1].Value}");
      
              AddValueToUpdate(result, value);
          }
      
          public string Build()
          {
              if (_valuesToUpdate.Any() == false)
              {
                  // nothing to update
                  return null;
              }
      
              /*
      update({ 
      _id: 7, 
      "comments._id": ObjectId("4da4e7d1590295d4eb81c0c7")
      },{
      $set: {"comments.$.type": abc}
      }, false, true
      );
                  */
      
              StringBuilder sb = new StringBuilder();
      
              sb.Append(_filter);
              sb.Append(',');
      
              sb.Append("{");
              {
                  sb.Append("$set:{");
                  foreach (var item in _valuesToUpdate)
                  {
                      sb.Append('"');
                      sb.Append(item.Key);
                      sb.Append('"');
                      sb.Append(':');
      
                      var value = BsonExtensionMethods.ToJson(item.Value);
                      sb.Append(value);
                      sb.Append(',');
                  }
                  // remove last comma
                  sb.Length--;
                  sb.Append('}');
              }
              sb.Append("}");
      
              return sb.ToString();
      
      
      
      
          }
      
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-02
        • 2021-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多