Почему метод заполнения MongoDB не работает в этом приложении?

Я работаю над приложением для ведения блога (нажмите на ссылку, чтобы увидеть < strong>репозиторий GitHub) с Express, EJS и MongoDB.

У меня есть записи и категории записей, каждая из которых находится в отдельной коллекции.

Схема категорий:

const mongoose = require('mongoose');

const categorySchema = new mongoose.Schema({
    cat_name: {
        type: String,
        required: true
    },
    updated_at: {
        type: Date,
        default: Date.now()
    },
    created_at: {
        type: Date,
        default: Date.now()
    }
});

module.exports = mongoose.model('Category', categorySchema);

Схема сообщений:

const mongoose = require('mongoose');

const postSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true
    },
    short_description: {
        type: String,
        required: true
    },
    full_text: {
        type: String,
        required: true
    },
    category: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'category'
    },
    post_image: {
        type: String,
        required: false
    },
    updated_at: {
        type: Date,
        default: Date.now()
    },
    created_at: {
        type: Date,
        default: Date.now()
    }
});

module.exports = mongoose.model('Post', postSchema);

метод контроллера, который отображает сообщения:

exports.displayDashboard = (req, res, next) => {
    const posts = Post.find({}, (err, posts) => {
        if(err){
            console.log('Error: ', err);
        } else {
            res.render('admin/index', {
              layout: 'admin/layout',
              website_name: 'MEAN Blog',
              page_heading: 'Dashboard',
              posts: posts
            });
        }
    }).populate({ path: 'category', model: Category })
};

Если в представлении у меня есть:

<table class="table table-striped table-sm mb-0">
    <thead>
        <tr class="d-flex">
            <th class="col-1 pl-2">#</th>
            <th class="col-2">Title</th>
            <th class="col-2">Category</th>
            <th class="col-2">Created</th>
            <th class="col-2">Updated</th>
            <th class="col-3 pr-2 text-right">Actions</th>
        </tr>
    </thead>
    <tbody>
        <% if (posts) { %>
            <% posts.forEach(function(post, index) { %>
                <tr data-id="<%= post._id %>" class="d-flex">
                    <td class="col-1 pl-2">
                        <%= index + 1 %>
                    </td>
                    <td class="col-2">
                        <a href="/<%= post._id %>" class="text-dark">
                            <%= post.title %>
                        </a>
                    </td>
                    <td class="col-2">
                        <%= post.category %>
                    </td>
                    <td class="col-2">
                        <%= post.created_at.toDateString(); %>
                    </td>
                    <td class="col-2">
                        <%= post.updated_at.toDateString(); %>
                    </td>
                    <td class="col-3 text-right pr-2">
                        <div class="btn-group">
                            <a href="../dashboard/post/edit/<%= post._id %>" class="btn btn-sm btn-success">Edit</a>
                            <a href="#" class="btn btn-sm btn-danger delete-post" data-id="<%= post._id %>">Delete</a>
                        </div>
                    </td>
                </tr>
                <% }); %>
                <% } else { %>
                <tr>
                  <td colspan="5">There are no posts</td>
                </tr>
                <% } %>
    </tbody>
</table>

объект отображается в столбце Категория (таблицы сообщений):

введите здесь описание изображения

Тем не менее, когда я пытаюсь отобразить название категории с помощью <%= post.category.cat_name %>, я получаю эту ошибку:

Cannot read property 'cat_name' of null

Что я делаю не так?


person Razvan Zamfir    schedule 14.04.2020    source источник
comment
Прежде всего, mongoose преобразует вашу схему в строчные буквы (например, Категория => категории). Поэтому категория внутри postSchema должна ссылаться на категории, так что попробуйте. Вы проверяли, можете ли вы успешно отображать любое другое поле помимо post._id?   -  person rags2riches    schedule 14.04.2020
comment
@ rags2riches Я пробовал. т это не то.   -  person Razvan Zamfir    schedule 14.04.2020


Ответы (3)


Используйте операторы async/await, так как populate возвращает запрос, который можно ожидать. Дополнительную информацию и примеры кода можно найти в официальной документации от Mongoose.

async function yourAwesomeFunction (req, res, next) {
   try {
      const posts = await Post
         .find({ })
         .populate({ path: 'category' });

      res.render('path/to/layout', { posts: posts });
   } catch (e) {
      // TODO: handle possible errors...
   }
};
person federico-dondi    schedule 14.04.2020
comment
Я нашел проблему и опубликовал для нее решение. Проверьте, если интересно. Спасибо за помощь. - person Razvan Zamfir; 16.04.2020

Вы можете следовать этому коду

Название вашей модели: Категория

// Please Define post Schema
category: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Category'
    }

// Your Controller
exports.displayDashboard =async (req, res, next) => {
    const posts =await Post.find().populate('category')
    if(posts){
      res.render('admin/index', {
              layout: 'admin/layout',
              website_name: 'MEAN Blog',
              page_heading: 'Dashboard',
              posts: posts
            })
}
}
person Shuvro    schedule 15.04.2020
comment
Вы можете использовать асинхронное ожидание. - person Shuvro; 15.04.2020
comment
Как мне это сделать? - person Razvan Zamfir; 15.04.2020
comment
Я нашел проблему и опубликовал для нее решение. Спасибо за помощь. - person Razvan Zamfir; 16.04.2020

Я выяснил, в чем проблема: я удалил категорию, ранее назначенную сообщению. Исправление простое (в представлении):

<%= post.category != null ? post.category.cat_name : 'No category assigned' %>

вместо

<%= post.category.cat_name %>

Большое спасибо всем, кто принял участие за помощь.

person Razvan Zamfir    schedule 16.04.2020