我正在尝试使用 NodeJS 中的 Mongoose 填充二维数组内的字段。
这就是我的翻译数据的结构:
{
"_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
}
翻译架构.js
const TranslationSchema = mongoose.Schema(
{
idDocument: {
type: Schema.Types.ObjectId,
ref: 'Document'
},
translation: {
type: [[TranslationCoordinateSchema]],
default: []
}
},
{
strict: true
}
);
翻译坐标架构.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'
});
}
最佳答案
您需要指定子数组的位置,然后填充其中的对象:
Translation.findById(idTranslation).populate('translation.0.idVideo')
这适用于第一个(子数组 [0]),如果你想填充其他子数组,你需要在数组内循环,我不认为 mongoose 带有任何内置位置运算符( $[] 作为在 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}
}
]
]
*/
我希望这有帮助;)
关于arrays - Mongoose - 填充二维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55878496/