我正在尝试在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'
});
}
答案 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}
}
]
]
*/
我希望这会有所帮助;)