【问题标题】:Got duplicated data when subscribe multiple times多次订阅时得到重复数据
【发布时间】:2016-03-16 10:06:38
【问题描述】:

我在流星中使用 MongoDB 聚合。多次订阅时出现重复数据。

(数据库中的数据是静态的,也就是说它们一直都是一样的。)

// 服务器端

Meteor.publish('totalNumber', function () {
  let pipeline = [
    { $unwind: '$product' },
    { $group: {
      _id: {
        code: '$product.code',
        hour: { $hour: '$timestamp' }
      },
      total: { $sum: '$product.count' },
    }}
  ];

  Products.aggregate(
    pipeline,
    Meteor.bindEnvironment((err, result) => {
        console.log('result', result);  // at here every time subscribe, no duplicated data
        _.each(result, r => {
          this.added('totalNumber',
            // I use Random.id() here, because "Meteor does not currently support objects other than ObjectID as ids"
            Random.id(), {
              code: r._id.code,
              hour: r._id.hour,
              total: r.total
          });
        });
      }
    )
  );

  this.ready();
});

// 客户端

this.subscribe('totalNumber', () => {
  // Correct result: [Object, Object] for example
  console.log(Products.find().fetch());
}, true);

this.subscribe('totalNumber', () => {
  // Wrong result: [Object, Object, Object, Object]
  console.log(Products.find().fetch());
}, true);

this.subscribe('totalNumber', () => {
  // Wrong result: [Object, Object, Object, Object, Object, Object]
  console.log(Products.find().fetch());
}, true);

所以现在基本上,新结果总是包含上次订阅数据。

我该如何解决这个问题?谢谢

【问题讨论】:

  • 每次通过管道运行的 id 是否不同?
  • @DavidWeldon which ids?
  • 您正在使用r._id 呼叫this.added。是 r._idrandomly 生成的,还是每次运行 pipline 时都会生成相同的一组 id?
  • 对不起,你是对的,我更新了我的问题,我实际上在我的代码中使用了Random.id(),所以它们是不同的。
  • 是的,那是你的问题。这就像告诉客户“我添加了{_id: 'a', total: 10}”,然后告诉它“我添加了{_id: 'b', total: 10}”,并期望只有一个对象。客户端将通过_id 字段中的值来确定唯一性,但如果它是随机的,那么您的所有文档都将看起来是唯一的。我会写这个作为答案,但如果不了解您要解决的问题,我不知道该建议什么。

标签: javascript mongodb meteor aggregation-framework


【解决方案1】:

问题是您每次调用added 时都使用随机ID,因此客户端始终认为所有文档都是唯一的。您需要设计一个一致 id 字符串生成器。使用this question 的答案,您可以想象构建一组这样的函数:

hashCode = function (s) {
  return s.split('').reduce(function (a, b) {
    a = ((a << 5) - a) + b.charCodeAt(0);return a & a;
  }, 0);
};

objectToHash = function (obj) {
  return String(hashCode(JSON.stringify(obj)));
};

因此,如果您希望 codehour 的每个组合都有一个唯一的文档,您可以这样做:

var id = objectToHash(r._id);
this.added('totalNumber', id, {...});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    相关资源
    最近更新 更多