【问题标题】:Meteor: Increment DB value server side when client views pageMeteor:客户端查看页面时增加数据库值服务器端
【发布时间】:2017-05-26 19:43:21
【问题描述】:

我正在尝试做一些看似简单的事情,每次获取值时更新 MongoDB 中的视图计数器。

例如我用这种方法试过。

Meteor.methods({
    'messages.get'(messageId) {
        check(messageId, String);

        if (Meteor.isServer) {
            var message = Messages.findOne(
                {_id: messageId}
            );

            var views = message.views;

            // Increment views value
            Messages.update(
                messageId,
                { $set: { views: views++ }}
            );
        }

        return Messages.findOne(
            {_id: messageId}
        );
    },
});

但我无法让它按我想要的方式工作。例如 if(Meteor.isServer) 代码是无用的,因为它实际上并没有在服务器上执行。

在调用 findOne 后该值似乎不可用,因此它可能是异步的,但 findOne 没有回调功能。

我不希望客户端控制这部分,这就是我尝试在服务器端执行此操作的原因,但它需要在每次客户端获取值时执行。这听起来很难,因为客户端已经订阅了数据。

编辑:这是在阅读此处的答案后更新的方法。

'messages.get'(messageId) {
    check(messageId, String);

    Messages.update(
        messageId,
        { $inc: { views: 1 }}
    );

    return Messages.findOne(
        {_id: messageId}
    );
},

【问题讨论】:

    标签: mongodb meteor meteor-blaze


    【解决方案1】:

    例如 if(Meteor.isServer) 代码是无用的,因为它不是 实际在服务器上执行。

    Meteor 方法总是在服务器上执行。您可以从客户端调用它们(使用回调),但执行发生在服务器端。

    在调用 findOne 后该值似乎不可用, 所以它可能是异步的,但 findOne 没有回调功能。

    您不需要调用它两次。请看下面的代码:

    Meteor.methods({
        'messages.get'(messageId) {
            check(messageId, String);
    
            var message = Messages.findOne({_id:messageId});
            if (message) {
                // Increment views value on current doc
                message.views++;
                // Update by current doc
                Messages.update(messageId,{ $set: { views: message.views }});
            }
            // return current doc or null if not found
            return message;
        },
    });
    

    您可以通过您的客户这样称呼它:

    Meteor.call('messages.get', 'myMessageId01234', function(err, res) {
        if (err || !res) {
            // handle err, if res is empty, there is no message found
        }
        console.log(res); // your message
    });
    

    这里有两个补充:

    为了数据的可扩展性和封装,您可以将消息和视图拆分为单独的集合。如果您的发布方法不限于公共字段,那么请求消息的客户端也会收到查看计数。这可能暂时有效,但可能会在更大范围内违反某些(未来即将推出的)访问规则。

    【讨论】:

      【解决方案2】:

      views++ 表示:

      1. 使用views 的当前值,即使用当前(未修改的)值构建修饰符。
      2. 增加views 的值,这在您的情况下不再有用,因为您不会将该变量用于其他任何事情。

      如果您不清楚它们是如何工作的,请避免使用这些增量运算符。

      为什么不直接使用 mongo $inc 运算符来避免必须检索以前的值?

      【讨论】:

      • 你和@Jankapunkt 都在这里提供了帮助,但我只能标记一个答案。本质上,帮助理解 Meteor.methods 始终是服务器端的,所以我不必担心客户端不会增加值。并且使用 $inc 运算符也有帮助。我已经用我现在使用的新流星方法代码更新了我的问题。
      • 如果客户端知道方法代码(通过其名称),Meteor.methods 确实在客户端上运行(这称为simulation)。通常,如果您在客户端和服务器中导入您的方法代码。如果您不想要那种模拟,那么只需在服务器端导入代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-03
      • 2014-02-18
      • 2016-07-07
      相关资源
      最近更新 更多