【问题标题】:Replace in MongoDB With C#用 C# 在 MongoDB 中替换
【发布时间】:2018-06-15 11:48:39
【问题描述】:

我正在尝试在我的“游戏”集合中实际替换游戏类型的对象集合。

我想用全新的对象替换这些对象。我对 MongoDB 进行了一些研究,发现“UpdateMany”将用新值替换字段,但这并不是我想要的。我想替换整个对象。

作为参考,这是我的游戏类:

public class Game
{
  public Guid Id { get; set; }
  public string Title { get; set; }
  public string Developer { get; set; }
  public int ProjectId { get; set; }

  public Game()
  {
   this.Id = Guid.NewGuid();
 }
}

这是我用来尝试批量替换的方法。我传入了一个 ProjectId,因此对于参数中包含 ProjectId = 的所有游戏对象,将对象替换为新的游戏对象。

 public static void ReplaceGame(int ProjectId, IMongoDatabase Database)
 {
   IMongoCollection<Game> gameCollection = Database.GetCollection<Game>("Game");
   List<Game> gameCollectionBeforeReplacement = gameCollection.Find(g => true).ToList();
   if (gameCollectionBeforeReplacement.Count == 0)
   {
     Console.WriteLine("No Games in Collection...");
     return;
    }

    var filter = Builders<Game>.Filter.Eq(g => g.ProjectId, ProjectId);
    foreach (Game game in gameCollection.AsQueryable())
        gameCollection.ReplaceOneASync(filter, new Game() { Title = "REPLACEMENT TITLE" });
    }

这不仅会花费大量时间。我怀疑这是因为 .AsQueryable() 调用,但它也不起作用。我想知道如何用新的游戏对象实际替换过滤器拾取的所有实例。

【问题讨论】:

  • 你没有在那里等待异步调用。
  • 所以将方法更改为 public static async..然后在 foreach -> await gameCollection.ReplaceOneASync(filter, new Game() { Title = "REPLACEMENT TITLE" }; 我得到异常:应用更新后,发现(不可变)字段“_id”已更改为_id
  • 好吧,您不能更改不可变字段。我对 Mongo 不是很熟悉,但不是进行批量更新,您可以删除它们并重新插入吗?
  • 这似乎是要走的路。但是,有没有办法在删除时保持顺序?不过,排序有点费力。

标签: c# mongodb mongodb-query


【解决方案1】:

考虑以下代码:

public virtual ReplaceOneResult ReplaceOne(TDocument replacement, int projId)
{
    var filter = Builders<TDocument>.Filter.Eq(x => x.ProjectId, projId);
    var result = Collection.ReplaceOne(filter, replacement, new UpdateOptions() { IsUpsert = false }, _cancellationToken);

    return result;
}

您会发现ReplaceOneResult 有一个属性可以告诉您匹配的计数。这使您可以继续执行 ReplaceOne 调用,直到匹配计数等于 0。发生这种情况时,您知道集合中具有相应项目 ID 的所有文档都已被替换。

例子:

var result = ReplaceOne(new Game() { Title = "REPLACEMENT TITLE" }, 12);
while (result.MatchedCount > 0)
    result = ReplaceOne(new Game() { Title = "REPLACEMENT TITLE" }, 12);

这样您就不需要在开始替换之前调用数据库。

但是,如果您希望为每个现有游戏插入相同的值,我建议您执行 UpdateMany 操作。在那里,您可以使用 $set 指定所有必需的值。上面的代码根本就没有性能,每次替换调用都会去数据库。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多