// backend\models\Playlist.js
const mongoose = require('mongoose');
const playlistSchema = new mongoose.Schema({
name: { type: String, required: true },
videos: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Video' }],
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
});
module.exports = mongoose.model('Playlist', playlistSchema);
// backend\models\Video.js
const mongoose = require('mongoose');
const commentSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
username: { type: String, required: true },
comment: { type: String, required: true },
date: { type: Date, default: Date.now },
});
const videoSchema = new mongoose.Schema({
title: String,
description: String,
url: String,
uploadDate: {
type: Date,
default: Date.now,
},
uploader: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
likes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
comments: [commentSchema],
cloudinary_id: { type: String, required: true },
});
module.exports = mongoose.model('Video', videoSchema);
// backend\models\User.js
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
userSchema.pre('save', async function (next) {
if (this.isModified('password')) {
this.password = await bcrypt.hash(this.password, 10);
}
next();
});
userSchema.methods.comparePassword = function (password) {
return bcrypt.compare(password, this.password);
};
module.exports = mongoose.model('User', userSchema);
播放列表模态引用了视频模态,视频模态引用了用户模态,但我只收到播放列表模态中存在的视频 ID,而不是整个视频文档。
这就是我使用 API 访问的方式:
router.get('/playlist/:id/videos', authMiddleware, async (req, res) => {
try {
const playlist = await Playlist.findById(req.params.id)
.populate({
path: 'videos',
populate: { path: 'uploader' }
});
if (playlist.userId.toString() !== req.userData.userId) {
return res.status(403).json({ message: 'Forbidden' });
}
res.json(playlist.videos);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
我尝试注意到我已经在其他 API 中实现了填充并且它工作正常,但在这里不行。
请看下面的代码。这里使用了相同的三个模式定义。然后创建一个测试播放列表。检索代码也与原始问题中使用的代码相同。请查看输出,视频文档现已填充。
请求请密切关注“设置视频参考”行的代码。这可能是根据您的代码进行检查的潜在行。如您所知,这一行设置了视频文档的引用,即播放列表文档和视频文档之间的链接。由于模式定义和 find 语句被发现工作正常,因此这一行将是最有可能审查的一行。
如果事实证明该行在您的代码中也是正确的,请使用一组新文档重复测试 - 创建一个新用户、针对新用户的新视频文档以及针对新视频的新播放列表。
// MongoDB: 7.0.2
// Mongoose : 8.3.2
// Node.js v21.6.0.
// populateissue.mjs
import mongoose, { Schema } from 'mongoose';
main().catch((err) => {
console.log(err);
});
async function main() {
await mongoose.connect('mongodb://127.0.0.1:27017/myapp');
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
password: { type: String, required: true },
});
const Usermodel = mongoose.model('User', userSchema);
await Usermodel.deleteMany();
const commentSchema = new mongoose.Schema({
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
username: { type: String, required: true },
comment: { type: String, required: true },
date: { type: Date, default: Date.now },
});
const videoSchema = new mongoose.Schema({
title: String,
description: String,
url: String,
uploadDate: {
type: Date,
default: Date.now,
},
uploader: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
likes: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
comments: [commentSchema],
cloudinary_id: { type: String, required: true },
});
const Videomodel = mongoose.model('Video', videoSchema);
await Videomodel.deleteMany();
const playlistSchema = new mongoose.Schema({
name: { type: String, required: true },
videos: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Video' }],
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
});
const Playlistmodel = mongoose.model('Playlist', playlistSchema);
await Playlistmodel.deleteMany();
const userdoc = new Usermodel({
username: 'somename',
password: 'somepassword',
});
const videodoc = new Videomodel({
title: 'someTitle',
uploader: userdoc._id,
cloudinary_id: 'someId',
});
const playlistdoc = new Playlistmodel({
name: 'someName',
videos: videodoc._id, // setting video reference
userId: userdoc._id, // kept it the same as uploader since it is a test data
});
await userdoc.save();
await videodoc.save();
await playlistdoc.save();
const playlistdocs = await Playlistmodel.findById(playlistdoc._id).populate({
path: 'videos',
populate: { path: 'uploader' },
});
console.log(playlistdocs);
console.log(playlistdocs.videos);
}
// output
{
_id: new ObjectId('6629c3f3450ae04736c1877e'),
name: 'someName',
videos: [
{
_id: new ObjectId('6629c3f3450ae04736c1877d'),
title: 'someTitle',
uploader: [Object],
likes: [],
cloudinary_id: 'someId',
uploadDate: 2024-04-25T02:46:11.929Z,
comments: [],
__v: 0
}
],
userId: new ObjectId('6629c3f3450ae04736c1877c'),
__v: 0
}
[
{
_id: new ObjectId('6629c3f3450ae04736c1877d'),
title: 'someTitle',
uploader: {
_id: new ObjectId('6629c3f3450ae04736c1877c'),
username: 'somename',
password: 'somepassword',
__v: 0
},
likes: [],
cloudinary_id: 'someId',
uploadDate: 2024-04-25T02:46:11.929Z,
comments: [],
__v: 0
}
]