динамическая ссылка в mongodb не отображает имя пользователя

#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.