在Meteor中,当另一个字段发生变化时,如何更新一个db字段?
一般问题:在Meteor中,实现在模型更新时触发的业务逻辑的最佳方式是什么?例如,更新依赖字段或验证或 具体示例:我想在列表集合中添加一个“slug”字段。每当列表名称更改时,slug需要自动更新 这是我得到的。。。我正在观察列表的每一个变化,看看它的slug是否需要创建/更新。这在shared models.js中(运行服务器和客户端,以获得延迟补偿的好处):在Meteor中,当另一个字段发生变化时,如何更新一个db字段?,meteor,Meteor,一般问题:在Meteor中,实现在模型更新时触发的业务逻辑的最佳方式是什么?例如,更新依赖字段或验证或 具体示例:我想在列表集合中添加一个“slug”字段。每当列表名称更改时,slug需要自动更新 这是我得到的。。。我正在观察列表的每一个变化,看看它的slug是否需要创建/更新。这在shared models.js中(运行服务器和客户端,以获得延迟补偿的好处): //列出--{name:String} 列表=新流星收藏(“列表”); var listsObserver=Lists.find().
//列出--{name:String}
列表=新流星收藏(“列表”);
var listsObserver=Lists.find().observe({
新增:updateSlug,
更改:updateSlug
});
函数updateSlug(doc,idx){
var slug=(doc.name | |').replace(/\W+/g,'-').toLowerCase();
如果(段塞!==文件段塞){
console.log(“将''+doc.name+''的slug更新为'+slug”);
更新(doc._id,{$set:{slug:slug}});
}
}
(与最初的todos示例一样,server/publish.js将所有list.find()
发布为“列表”,而client/todos.js订阅该集合。)
上面的代码似乎可以工作,但在我看来不太正确。问题:
listsObserver.stop()
来处理观察者?
如果是,什么时候(我刚刚开始使用Meteor,因此可能我对其他环境的偏见正在泄漏。这里隐含的元问题是,我是否以正确的方式思考这个问题?实现这一点的一种方法是定义自定义模板函数,并在正在更改的模板中触发它。例如: 在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>
{{custom_function_to_update}
每次模板“myTemplate”更新时,它都会调用您的方法。我在服务器代码中做了类似的事情。基本上,将此代码放在Meteor.methods()中,以及您希望对列表集合进行的任何其他检查和更新 尽管下面的代码看起来有点凌乱,而且很难理解以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}});
}
}
});
我建议使用收集挂钩包。它使用before和after钩子扩展了收集操作。这比拥有大量收集观察或观察更改要好,尤其是在收集观察开销可能非常大的服务器上 这在客户端和服务器上都有效。如果您在客户端上实现它,您将获得更新本地集合(延迟补偿)的好处,并且更改将推送到服务器,因此无需再次执行 您还可以只执行一个MongoDB操作,而不是像使用observes或observeChanges那样执行两个或更多操作 您可以这样使用它:
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);
您可以在这里找到包:但是模板代码只在客户端运行,并且只针对特定的模板,对吗?因此,在不触发业务逻辑的情况下,变更很容易滑入模型。使用todo示例,如果只有该模板负责使list.slug保持最新,那么修改list.title的任何其他代码都会留下一个不同步的slug。这也会为每个打开该模板的客户端运行一次更新,这并不理想。嗯。。。刚刚在一个关于流星数据验证的老问题中发现。它似乎说您应该实现RPC风格的Meteor.methods进行模型编辑,然后阻止客户端的minimongo模型自动同步回服务器。(希望这还不是建议。自动、实时、双向同步是Meteor最吸引人的地方之一。)Meteor怎么知道每次有人试图修改列表名称时都要运行
myupdate
?或者每个可能修改列表名称的程序员只需要知道在之后也要调用myupdate
?(我正在寻找能够自动运行并防弹的东西。)在什么情况下,您会修改列表名称?i、 e.将更改写入数据库?如果是这样的话,只需将上面的代码组合到主代码中即可。如果不让我知道,解决方案可能是使用observeChanges()将代码放入Publish()中。哇,我甚至不知道这个存在!这正是我希望在流星核心找到的。