猫鼬-填充在二维数组上

时间:2019-04-27 07:59:32

标签: arrays node.js mongoose nested populate

我正在尝试在NodeJS中用猫鼬填充二维数组中的字段。

这是我的翻译数据的结构形式:

{
  "_id" : ObjectId("5cc3fa08c2d98a3ac8e4889a"),
  "translation" : [
         [
                 {
                         "x" : "999",
                         "y" : "999",
                         "width" : "555",
                         "height" : "555",
                         "idVideo" : ObjectId("5cc401f319bac9285ce0a235")
                  },
                  {
                         "x" : "111",
                         "y" : "111",
                         "width" : "666",
                         "height" : "666",
                         "idVideo" : ObjectId("5cc401f319bac9285ce0a235")
                  }
         ]
   ],
  "__v" : 2
}

TranslationSchema.js

const TranslationSchema = mongoose.Schema(
  {
    idDocument: {
      type: Schema.Types.ObjectId,
      ref: 'Document'
    },
    translation: {
      type: [[TranslationCoordinateSchema]],
      default: []
    }
  },
  {
    strict: true
  }
);

TranslationCoordinateSchema.js

const TranslationCoordinateSchema = mongoose.Schema({
  x: {
    type: String
  },
  y: {
    type: String
  },
  width: {
    type: String
  },
  height: {
    type: String
  },
  idVideo: {
    type: Schema.Types.ObjectId,
    ref: 'TranslationVideo'
  },
  _id: false
});

我尝试了很多事情,但是我不知道如何构造路径,因为它是一个二维数组。 例如,我尝试过:

Translation.findById(idTranslation).populate({
        path: 'translation.idVideo',
        model: 'TranslationVideo'
    });

Translation.findById(idTranslation).populate({
        path: 'translation.translation.idVideo',
        model: 'TranslationVideo'
    });

也许

Translation.findById(idTranslation).populate({
        path: 'translation..idVideo',
        model: 'TranslationVideo'
    });

我希望填充idVideo,因此我可以返回所有包含的数据,但是我却拥有:

"data": [
    {
       "type": "translations",
        "id": "5cc3fa08c2d98a3ac8e4889a",
        "translation": [
            [
                {
                   "x": "999",
                   "y": "999",
                   "width": "555",
                   "height": "555",
                   "idVideo": "5cc401f319bac9285ce0a235"
                 },
                 {
                    "x": "111",
                    "y": "111",
                    "width": "666",
                    "height": "666",
                    "idVideo": "5cc401f319bac9285ce0a235"
                 }
            ]
        ],
    }
]

解决方案

感谢Moad Ennagi提供的解决方案。 我刚刚编辑了他的解决方案,使其可以与ASYNC / AWAIT一起使用。

  static async findByIdAndPopulateVideos(idTranslation) {
    let count;
    let arr = [];

    if (!(count = await Translation.findById(idTranslation))) {
      return;
    }
    for (let i = 0; i < count.translation.length; i++) {
      arr.push(`translation.${i}.idVideo `); // Don't delete the last space !
    }
    return await Translation.findById(idTranslation).populate({
      path: arr.join(''),
      model: 'TranslationVideo'
    });
  }

1 个答案:

答案 0 :(得分:1)

您需要指定子数组的位置,然后在其中填充对象:

Translation.findById(idTranslation).populate('translation.0.idVideo')

这适用于第一个(子数组[0]),如果要填充其他子数组,则需要在数组内循环,我不认为猫鼬自带任何内置位置运算符({{3} },如mongoDB本机客户端)。
带有循环的示例
这是一个完整的工作示例,我试图模仿您的架构:

const fooSchema = new mongoose.Schema({
    name: String
  });
const Foo = mongoose.model('Foo', fooSchema);
const barSchema = new mongoose.Schema({
    x: String,
    y: String,
    fooId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Foo'
    }
  });
const Bar = mongoose.model('Bar', barSchema);
const totoSchema = new mongoose.Schema({
    bar: [[barSchema]]
  });
const Toto = mongoose.model('Toto', totoSchema);

// seeds
let foo = new Foo({name: 'foo'});
let bar, bar2;
foo.save().then(val => {
  bar = new Bar({x: '1', y: '1', fooId: val._id});
  bar2 = new Bar({x: '2', y: '2', fooId: val._id});
  toto = new Toto({bar: [[bar, bar2], [bar, bar2]]}).save(); // pushing the same objects(bar and bar2) out of lazyness
});

// A find query with a loop to construct paths to be populated
  Toto.findById(/* totoId */)
    .exec()
    .then(toto => {
      let arr = [];
      for(let i = 0; i <= toto.bar.length; i++) { // length of the array (1st dimension)
        arr.push(`bar.${i}.fooId `); // constrtucting the path
      }
      toto.populate(arr.join(''), (err, doc) => {
        if(err) throw err;
        else console.log(toto.bar);
      });
    })
    .catch(err => console.log(err));

/* Output
[
  [
    {
      "_id":"5cc472cd90014b60f28e6cb4",
      "x":"1",
      "y":"1",
      "fooId":{"_id":"5cc472ca90014b60f28e6cb3","name":"foo","__v":0}
    }, 
    {
      "_id":"5cc472cd90014b60f28e6cb5",
      "x":"2",
      "y":"2",
      "fooId": {"_id":"5cc472ca90014b60f28e6cb3","name":"foo","__v":0}
    }
  ], 
  [
    {
      "_id":"5cc472cd90014b60f28e6cb4",
      "x":"1",
      "y":"1",
      "fooId": {"_id":"5cc472ca90014b60f28e6cb3","name":"foo","__v":0}
    }, 
    {
      "_id":"5cc472cd90014b60f28e6cb5",
      "x":"2",
      "y":"2",
      "fooId": {"_id":"5cc472ca90014b60f28e6cb3","name":"foo","__v":0}
    }
  ]
]

*/

我希望这会有所帮助;)

相关问题