嵌套文档的填充返回null

时间:2018-11-21 11:09:42

标签: node.js mongodb mongoose

使用Document.populate()方法填充字段(放置在数组内)后,生成的文档将返回null,应将子文档放置在该位置。使问题难以解决的原因是,这种行为是意外的,因为它仅在相同集合的某些文档中发生。如您所见,我的模型有点复杂,所以也许我们的问题就是因为这个原因。

主要型号:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
const moment = require('moment');

var ActuacioSchema = new Schema({
  activa: Boolean,
  tancada: Boolean,
  ambit: [ { espai: String, idAlias: String, item: { type: Schema.Types.ObjectId, refPath: 'ambit.espai' } } ],
  // ... IMPORTANT PART BELOW
  persones: [
    {
      item: { type: Schema.Types.ObjectId, refPath: 'persones.col' },
      col: String,
      rol: String,
      convocat: Boolean,
      confirmat: Boolean,
      validat: Boolean,
    }
  ],
  // ... IMPORTANT PART ABOVE
  metadata: {
    editors: [ { type: Schema.Types.ObjectId, ref: 'usuaries' } ],
    ultimCanvi: {
      tmp: { type: Date, default: Date.now},
      usu: { type: Schema.Types.ObjectId, ref: 'usuaries' }
    },
    creacio: {
      tmp: { type: Date, default: Date.now},
      usu: { type: Schema.Types.ObjectId, ref: 'usuaries' }
    }
  }
});

module.exports = mongoose.model('actuacions', ActuacioSchema);

如您所见,我有一个要填充的子文档数组,并且我知道基于每个col字段值的集合。

现在让我们看一下我们子填充的子文档的示例(如您所见,它们都有一个共同的部分,我们需要子填充):

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var MonitoraSchema = new Schema({
  idUsuaria: { type: Schema.Types.ObjectId, ref: 'usuaries', required: true }, // <-- Important 
  idGrup: { type: Schema.Types.ObjectId, ref: 'grups' }, // <-- Important
  idEsplai: { type: Schema.Types.ObjectId, ref: 'esplais' }, // <-- Important
  admin: { type: Boolean, required: true },
  activa: { type: Boolean, required: true },
  cursos: [Number],
  tasques: [String],
  // ...
});

module.exports = mongoose.model('monitores', MonitoraSchema);

在另一个模型中,我们看到需要为之前进行的每个人口子化的字段。就像我说的那样,它们都不是相同的架构(它们来自不同的集合),但是它们具有一些我们需要填充的共同字段,例如idUsuaria。它们还具有一些特定于我们将要填充的每种模式的字段,并且仅当子文档属于该特定类型时才可以访问,例如idGrupidEsplai

最后,让我向您展示执行所有这些过程的逻辑控制器:

// newDoc is the base document of Model 'Actuacio', without populating
    _.each(newDoc.persones, (u, i) => {
      if(!u.dataCache.valid || dm(u.dataCache.expire).isSameOrBefore()) {
        // Here we populate some elements of the array based on a condition.
        // We populate first the element in the array, and then the subdocument again with those specific fields
        newDoc.populate({ path: `persones.${i}.item`, populate: { path: 'idUsuaria idGrup idEsplai idSector idComissio', select: 'desc' } });
      }
    })

    newDoc.execPopulate().then(
      function(docPersones) {

        _.each(docPersones.persones, (v, j) => {
          if(docPersones.populated(`persones.${j}.item`)) {
            // IMPORTANT PART: Here we iterate through the array that we populated
            v.dataCache.data.nom = v.item.idUsuaria.nomComplet;
            if(v.item.idEsplai) v.dataCache.data.esplai = v.item.idEsplai.desc.nom || "";
            if(v.item.idGrup) v.dataCache.data.grup = v.item.idGrup.desc.nom || "";
            // ....

因此,在最后一部分,我们进行迭代的时间是问题发生的时间。我们检查数组中的每个项目是否被填充以执行某些操作。事实是,对于我们之前指示的项目,它返回true(因此populate()调用本身可以工作),但是当我们尝试访问person [i] .item(或v.item)时,它只是 null ,或者ObjectID都不是子文档。

我仔细检查了数据库上的引用,它们都是正确的。

关于如何解决此问题的任何想法?

0 个答案:

没有答案