【问题标题】:Meteor - How to update a document in an arrayMeteor - 如何更新数组中的文档
【发布时间】:2015-12-05 12:13:22
【问题描述】:

我在数组中有一个文档,并尝试更新文档中的值。

它已经在 Meteor 的 Mongo shell 中工作了:

$ meteor mongo
meteor:PRIMARY> db.mycollection.update({name:"test", "foo.name":"bar"}, {$set: {"foo.$.price":42}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

但是当我尝试在 Meteor 中使用以下方法时它不起作用:

MyCollection.update(
    {name:"test", "foo.name":"bar"},
    {$set: {"foo.$.price":42}}
);

如您所见:http://meteorpad.com/pad/jjazD3jYYeY7R9Bpv/DocumentArrayUpdate

这是因为您不能在客户端放置与 Id 不同的选择器(使用自动发布/不安全):

Error: Not permitted. Untrusted code may only update documents by ID. [403]

这就是我迷路的地方。我必须在服务器上运行此更新代码,但到目前为止我看到的唯一示例只是在服务器的Meteor.publish() 上执行一些.find().findOne(),然后所有更新逻辑都在Meteor.methods() 中完成是客户端和服务器端,所以在我的情况下我不能这样做。

我怎样才能做到这一点?

编辑:我有点快说:Meteor.methods() 既是客户端又是服务器端,所以就我而言,我不能这样做。它实际上适用于Meteor.methods(),我仍然不知道为什么,我认为它来自 Meteor 的 Optimistic UI 功能的工作原理......

【问题讨论】:

  • 您已经完成了 99% 的解决方案! :) 您需要在仅在服务器上定义的方法中执行此操作。有几种方法可以做到这一点,但最简单的方法是将代码添加到应用程序的 server 目录下的文件中。

标签: javascript mongodb meteor


【解决方案1】:

错误:不允许。不受信任的代码只能按 ID 更新文档。 [403]

这意味着您已经删除了不安全的包,这对生产来说是一件好事。但这意味着您不能再从客户端更新您的数据库条目,除非您通过集合的 ID 进行更新(如错误所述。

所以你有两个选择。

首先 - 糟糕的选择。来自客户:

MyCollection.update(
    {_id:"19283yhakjsdo23", "foo.name":"bar"},
    {$set: {"foo.$.price":42}}
);

这不是很糟糕,但也不是很好。

不错的选择:来自服务器。

Meteor 有一种叫做服务器端方法(a good blog post about this is available) 的东西。服务器端方法很棒,可以让您使用几乎完全相同的代码,但来自服务器,完全可以做您想做的事情。

因此,在您的server 目录中的一个名为methods.js 的文件中,您可以编写:

Meteor.methods({
    priceUpdateMethod(name, collectionkey, updateValue) {
        MyCollection.update(
            {name:name, "foo.name":"bar"},
            {$set: {collectionkey: updateValue}}
        );
    }
});

然后在您的客户端目录中,您将有一个助手或类似的功能:

Meteor.call('priceUpdateMethod',"test","foo.$.price",42)

【讨论】:

  • 我已经尝试过你的第一个例子,它不起作用,你会遇到同样的错误,因为你没有只给出 id 作为选择器。根据文档,Meteor.methods 必须放在通用代码上。但是......刚刚尝试过,它的工作原理!我认为是因为 Meteor 实际上在服务器上执行代码,并且只在客户端上模拟(他们的 Optimistic UI 东西......)
  • 在文档中他们说方法可以在任何地方定义,这可能会造成混淆。你可以在任何地方定义一个方法,你可以在任何地方调用它。这个例子定义了服务器上的方法,因为当不安全的包被删除时,只有服务器可以与你的数据库交互。很高兴你成功了。
【解决方案2】:

服务器是受信任的。客户端不受信任。

将你的流星方法更改为:

if (Meteor.isServer()) {
  MyCollection.update(
    {name:"test", "foo.name":"bar"},
    {$set: {"foo.$.price":42}}
  );
}
if (Meteor.isClient()) {
  _id = MyCollection.findOne(
    {name:"test", "foo.name":"bar"}
  )._id;
  MyCollection.update(_id, {$set: {"foo.$.price":42}});
}

正如 David 在 cmets 中提到的,您的代码将在服务器上运行。要使其也能在客户端上工作(延迟压缩),请尝试这种方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多