Метеор: как автоматически заполнить поле длиной массива, хранящегося в другом поле в коллекции?

У меня есть коллекция, определенная с помощью SimpleSchema/Collection2, например:

Schema.Stuff = new SimpleSchema({
    pieces: {
        type: [Boolean],
    },
    num_pieces: {
        type: Number,
    },

Как я могу получить num_pieces автоматически заполняется длиной pieces массив, когда есть изменение?

Я открыт для использования SimpleSchema autoValue или же matb33:collection-hooks, pieces потенциально может быть изменено с помощью нескольких операторов, таких как $push, $pull, $setи, вероятно, больше, что Монго может предложить, и я понятия не имел, как справиться с этими возможностями. В идеале можно просто посмотреть на значение pieces после обновления, но как вы можете сделать это и внести изменения, не вдаваясь в бесконечный цикл на хуке сбора?

2 ответа

Решение

Вот пример того, как вы бы выполняли ловушку для коллекции "после обновления", которая предотвращает бесконечный цикл:

Stuff.after.update(function (userId, doc, fieldNames, modifier, options) {
  if( (!this.previous.pieces && doc.pieces) || (this.previous.pieces.length !== doc.pieces.length ) {
    // Two cases to be in here:
    // 1. We didn't have pieces before, but we do now.
    // 2. We had pieces previous and now, but the values are different.
    Stuff.update({ _id: doc._id }, { $set: { num_pieces: doc.pieces.length } });
  }
});

Обратите внимание, что this.previous дает вам доступ к предыдущему документу, и doc это текущий документ. Это должно дать вам достаточно, чтобы закончить остальные дела.

Вы также можете сделать это прямо в схеме

Schema.Stuff = new SimpleSchema({
  pieces: {
    type: [Boolean],
  },
  num_pieces: {
    type: Number,
    autoValue() {
      const pieces = this.field('pieces');
      if (pieces.isSet) {
        return pieces.value.length
      } else {
        this.unset();
      }
    }    
  },
});
Другие вопросы по тегам