MongoDB的条件更新(流星)

时间:2015-07-30 16:46:45

标签: mongodb meteor

TLDR:有没有办法可以有条件地更新集合中的Meteor Mongo记录,这样如果我使用id作为选择器,我想更新是否匹配,只有当版本号大于已经如果没有id匹配,则存在,还是执行upsert?

我遇到了服务器端Meteor Mongo集合更新的问题,看起来观察者中的added()函数回调是在upsert上触发的。

这就是我想要简单地做的事情。

  • 我的meteor js应用程序启动,然后连接到端点,获取数据,然后将其插入到集合中。

    collection.update({'sys.id': item.sys.id}, item, {upsert: true});
    
  • ' sys.id'选择器检查该项是否存在,然后更新它是否存在,如果不存在则更新。

  • 我有一个观察员监视上面的集合,然后在项目被添加/更新到集合时起作用。

    collection.find({})。observeChanges({     补充:this.itemAdded.bind(this),     已更改:this.itemChanged.bind(this),     删除:this.itemRemoved.bind(this) });

  • 令我困惑的第一件事是,当应用程序关闭然后再次启动时,'添加()'观察集合时会触发回调。我希望发生的是change()回调被触发。

回到我原来的更新 - 在Mongo中是否有可能有条件地更新某些东西,所以你有选择器,然后是项目,但只在满足另一个条件时才执行更新?

// Incoming item 
var item = {
    sys: {
       id: 1,
       revision: 5
    }
};

collection.update({'sys.id': item.sys.id, 'sys.revision': {$gt: item.sys.revision}, item, {upsert: true});

如果你看一下上面的代码,那要做的是尝试匹配sys.id,这很好,但是修订当然会有所不同,这意味着更新功能会将它看作一个不同的文档然后执行新的插入,从而创建重复的数据。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

对于你的主要问题:

您想要的是findAndModify。首先,查找符合规范的文档,然后相应地更新。这是一个非常强大的想法,因为如果您在2个查询中执行此操作,则在更新之前可能会删除/更新您找到的文档。幸运的是,有人制作了一个包(我真的希望一年前存在!)https://github.com/fongandrew/meteor-find-and-modify

如果您在不使用findAndModify的情况下执行此操作,则必须使用javascript查找文档,查看它是否符合您的条件,然后进行更新。在你的用例中,这可能会起作用,但总会有这样的情况,如果"在你的脑海里。

关于observeChanges,每当本地minimongo收到一个文档时,就会调用添加的文件(它只是读取DDP告诉它的内容)。由于刷新会删除您的本地集合,因此您必须逐个添加这些文档。你可以做的是等到所有added回调都被触发,然后运行你的服务器方法。在这样做的过程中,你会获得大量的补充,之后会有更多的变化。

答案 1 :(得分:2)

正如Matt K所说,你想要findAndModify。有一些问题需要注意:

  • findAndModify比查找后跟更新慢约100倍。发现+修改显然不是原子的,所以不会做你需要的,但要注意速度命中。 (这是基于MongoDB v2.4的经验,所以运行一些基准来确认你自己的版本。)
  • 如果您的查询与多个项目匹配,则findAndModify将仅对第一个项目执行操作。在这种情况下,您需要查询唯一ID,但请注意该问题以备将来使用。
  • findAndModify将在执行此操作后返回文档,但默认情况下会返回预修改版本。如果你想要修改后的那个,你需要传递' new:true'在您的查询中。