Mongodb对更新与替换的影响

时间:2017-09-05 19:06:12

标签: c# mongodb replace updates

我已阅读this related question,但下面的内容有所不同。 mongodb c#驱动程序在文档集合类上有一个ReplaceOne方法(和一个异步对应方法),可用于替换适合filter参数的文档的整个内容。另一种方法是使用UpdateOneUpdateMany方法(或异步对应方法),这需要构建UpdateDefinition<TDocument>

我的问题与选择其中一种方法相对于另一种方法(替换vs更新)的影响有关,如果您有足够的输入数据来选择实现相同的结果。换句话说,如果我有整个原始文档,并且只希望更新其中的一小部分内容。

我能想到的第一个因素是发送到数据库服务器的有效负载。虽然我没有读过任何mongodb c#驱动程序源,但找不到任何文件来验证这一点,但似乎ReplaceOne可能需要通过更新操作发送更多字节,特别是对于较大的文档。 Update...方法似乎只需要为需要修改的文档片段发送更新元数据(除了两种方法都必须发送的过滤条件),它们可以通过较小的有效负载逃脱。任何人都可以验证这是否是一个准确的假设?

同事提出的另一个因素是方法的选择(更新与替换)也可能影响文档索引。这里的假设是使用ReplaceOne有可能导致数据库重建正在更新的文档的所有索引,而Update...方法有足够的更改元数据信息,以避免在非字段上重建索引更新定义中的部分元数据。任何人都可以验证mongodb是否在内部处理文档索引构建方式,具体取决于是否使用replace和update修改了文档?

关于AddToSet类的PullFilterUpdate<TDefinition>方法,我们已经多次提出了第三个因素。似乎Update...方法不允许您通过向其添加项目和同时从中删除项目来修改文档中的集合(如json数组);这些操作必须单独发送,使用2个单独的Update...方法调用以及单独的Update<TDefinition>实例(尽管使用相同的过滤器参数)。在这种情况下,ReplaceOne方法似乎是在单个“事务”中进行此类文档更改的唯一方法,至少在使用C#驱动程序时是这样。我们目前正在使用Update...而不是ReplaceOne,因为我们不确定替代方案是否会对索引产生负面影响。

除了这些之外,还有什么其他影响可能导致人们在ReplaceOne家族中选择Update...系列方法,反之亦然?同样,这假设你有足够的输入数据(即所有文档数据)来实现两种方法相同的结果,不介意直接改变状态(通过替换),并且不介意构建mongo定义(通过更新)

2 个答案:

答案 0 :(得分:0)

由于mongo数据是非结构化的,因此replaceOne vs Update的主要优点是保证您删除所有字段并替换为新文档,使您的查询更简单

1)是的,但是你的问题最少,搜索标准在两者中都是相同的,但是replaceOne将要求在查询中传递整个文档,当你拥有全新的Doc并希望是确定它会以那种方式结束

2)重新索引替换 - &gt;是的,replaceOne替换整个文档而不是更新现有文档,如果更新索引上的元素,索引将需要重新调整到更改,但是使用replace它将始终需要重新调整。 _id索引不受两个操作的影响(我认为)

3)如果您已经拥有了想要的值,那么您不需要替换整个文档来更改单个字段,使其被所有字段重新编入索引,您应该使用$ set操作那,您可以将其视为单个字段的ReplaceOne而不是整个文档

https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/index.html https://docs.mongodb.com/manual/reference/operator/update/set/

答案 1 :(得分:0)

如果合并到REST服务中,replaceOne方法将与PUT操作很好地对齐,您可以在其中发送请求正文中的整个对象以及对象标识符,然后可以将其整体保存在数据库中。 PUT操作的区别特征是它是幂等的(你可以重复运行它)。 replaceOne采用upsert选项,默认为false,但如果将其设置为true(并且搜索条件位于唯一索引字段上),则无论文档是否独立,都会使操作可重复除去。

更新操作更类似于POST操作,因为它只是更新文档的一部分而不是完全替换它。它还需要upsert选项,但如果文档被另一个进程删除,则生成的文档可能格式错误,更新可能会失败。