在Meteor中,如何在另一个字段更改时更新一个数据库字段?

时间:2012-09-17 17:38:08

标签: meteor

一般问题:在Meteor中,实现在更新模型时触发的业务逻辑的最佳方式是什么 - 例如,用于更新相关字段或验证或...

具体示例:我想在Meteor todos example中的“列表”集合中添加“slug”字段。每当更改列表名称时,slug都需要自动更新。

这就是我所拥有的......我正在观察每个对列表的更改,以查看是否需要创建/更新其slug。这是在共享 models.js(运行服务器和客户端,以获得延迟补偿的好处):

// Lists -- {name: String}
Lists = new Meteor.Collection("lists");

var listsObserver = Lists.find().observe({
    added: updateSlug,
    changed: updateSlug
});

function updateSlug(doc, idx) {
    var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();
    if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        Lists.update(doc._id, {$set: {slug: slug}});
    }
}

(和最初的todos示例一样,server / publish.js将所有Lists.find()发布为“lists”,client / todos.js订阅该集合。)

上面的代码似乎有效,但不知何故对我来说看起来不太合适。问题:

  1. 观察列表集合是否合理?这好像是 它可能效率低下 - 任何更改列表文档都会触发此代码。
  2. 我应该在客户端进行不同的(模拟)更新,还是可以让它 同样的Mongo / Minimongo更新同时运行吗?
  3. 我是否需要在某个时候致电listsObserver.stop()处置观察员? 如果是这样,何时?
  4. (我刚刚开始使用Meteor,所以也许我在其他环境中的偏见正在泄漏。这里隐含的元问题是,我是否以正确的方式思考这个问题?)

3 个答案:

答案 0 :(得分:11)

我建议使用Collection-Hooks包。它扩展了钩子前后的收集操作。这比拥有大量Observes或ObserveChanges更好,特别是在收集观察的开销可能变得非常大的服务器上。

这适用于客户端和服务器。如果您在客户端上实现它,您将获得更新本地集合(延迟补偿)的好处,并且更改将被推送到服务器,因此无需再次执行此操作。

您还可以获得仅执行一次MongoDB操作而不是两次或更多次操作的好处,就像观察或观察更改一样。

您可以这样使用它:

var beforeInsertSlug = function(userId, doc) {
    var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();
    if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        doc.slug = slug;
    }
};

var beforeUpdateSlug = function(userId, doc, fieldNames, modifier, options){
    if(modifier && modifier.$set && modifier.$set.doc && _.isString(modifier.$set.doc.name)){
        var slug = (modifier.$set.doc.name || '').replace(/\W+/g, '-').toLowerCase();
        if (slug !== doc.slug) {
            console.log("Updating slug for '" + modifier.$set.doc.name + "' to " + slug);
            modifier.$set.doc.slug = slug;
        }
    }

};

Lists.before.insert(beforeInsertSlug);

Lists.before.update(beforeUpdateSlug);

您可以在此处找到该软件包:https://atmospherejs.com/matb33/collection-hooks

答案 1 :(得分:1)

我在服务器代码中做了类似的事情。基本上将此代码放在Meteor.methods()中,以及您希望对Lists Collection进行的任何其他检查和更新。

虽然下面的代码看起来有点混乱,但用var slug开头的行肯定很难理解:

Meteor.methods({
   myupdate: function (doc) {

     var slug = (doc.name || '').replace(/\W+/g, '-').toLowerCase();

     if (slug !== doc.slug) {
        console.log("Updating slug for '" + doc.name + "' to " + slug);
        Lists.update(doc._id, {$set: {slug: slug}});
     }
   }
});

答案 2 :(得分:0)

实现此目的的一种方法是定义自定义模板函数并在正在更改的模板中触发它。例如:

在client.js

Template.myTemplate.custom_function_to_update = function() {
    // do my update code.  i.e. MyCollections.Update(...);
}

在带有模板的html文件中

<template name="myTemplate">
    <!-- Normal template code -->
    {{ custom_function_to_update }}
</template>

每次模板“myTemplate”更新时,都会调用您的方法。