#node.js #mongodb #express #mongoose
#node.js #mongodb #экспресс #мангуст
Вопрос:
Итак, у меня есть приложение, в котором пользователи могут создавать учетные записи либо локальные, либо с помощью Twitter, и могут создавать сообщения. Я хочу, чтобы имя пользователя отображалось в сообщении всякий раз, когда они его создают.
Пока у меня есть 3 схемы: LocalUser, TwitterUser и Posts. Я просмотрел документацию mongoose (mongoose docs), которая позволяет динамически ссылаться на схемы. Однако у меня это не работает.
models/Post.js
const PostsSchema = new mongoose.Schema({
postTitle: {
type: String,
required: true,
trim: true,
},
user: {
// Connects user to posts
type: mongoose.Schema.Types.ObjectId,
refPath: 'onModel',
},
onModel: {
type: String,
// required: true -> if I put this I get an error on post
enum: ['LocalUser', 'TwitterUser'],
},
});
module.exports = mongoose.model('Posts', PostsSchema);
index.js
router.get('/', async (req, res) => {
try {
const posts = await Posts.find()
.populate('onModel')
.lean();
const { user: { username, image, twitterId, googleId } = {} } = req;
res.render('index', {
username,
twitterId,
googleId,
image,
posts,
});
} catch (err) {
console.error(err);
res.render('error/500');
}
});
index.hbs
{{onModel.username}} // nothing - Note, twitter schema and local schema both have username
Я рассматривал несколько решений, и это выглядело наиболее многообещающим. Я что-то упустил? Спасибо.
Комментарии:
1.
onModel
это ссылка на имя модели, попробуйте.populate('user')
и получите доступ черезuser.username
2. Привет, Мэтт, спасибо за ответ. К сожалению, это не работает, имя пользователя по-прежнему пустое.
3. Вы получаете строку ObjectId для
user
себя? (т. Е. без.username
)
Ответ №1:
Используя следующие модели:
const mongoose = require('mongoose')
const { model, Schema } = mongoose
const postSchema = new Schema({
postTitle: { type: String, required: true },
user: {
type: Schema.Types.ObjectId,
required: true,
refPath: 'userModel'
},
userModel: {
type: String,
required: true,
enum: ['LocalUser', 'TwitterUser']
}
});
const LocalUser = model('LocalUser', new Schema({ username: String }));
const TwitterUser = model('TwitterUser', new Schema({ username: String }));
const Post = model('Post', postSchema);
С помощью этого кода настройки / запроса:
async function go(){
await mongoose.connect('mongodb://localhost:27017/so64148230', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
const luser = await LocalUser.create({ username: 'luser' })
await Post.create({ postTitle: 'aluser', userModel: 'LocalUser', user: luser })
const tweeter = await TwitterUser.create({ username: 'tweeter' })
await Post.create({ postTitle: 'atweeter', userModel: 'TwitterUser', user: tweeter })
console.log('posts', await Post.find({}).select('user').lean())
console.log('posts populate', await Post.find({}).populate('user').lean())
await mongoose.disconnect()
}
go().catch(console.error)
Создает сообщения с идентификатором объекта для user
, которые могут быть заполнены.
posts [
{ _id: 5f769b14aa0c16f83badf411, user: 5f769b14aa0c16f83badf410 },
{ _id: 5f769b14aa0c16f83badf413, user: 5f769b14aa0c16f83badf412 }
]
posts populate [
{
_id: 5f769b14aa0c16f83badf411,
postTitle: 'aluser',
userModel: 'LocalUser',
user: { _id: 5f769b14aa0c16f83badf410, username: 'luser', __v: 0 },
__v: 0
},
{
_id: 5f769b14aa0c16f83badf413,
postTitle: 'atweeter',
userModel: 'TwitterUser',
user: { _id: 5f769b14aa0c16f83badf412, username: 'tweeter', __v: 0 },
__v: 0
}
]
Оттуда проблема заключается в рендеринге шаблона.
Комментарии:
1. Я
throw new _mongoose.Error.OverwriteModelError(name); OverwriteModelError: Cannot overwrite
получаю модель локального пользователя после компиляции. ` Я думаю, что причиной этого является то, что у меня уже есть модель mongoose под названием LocalUser.