Express. js Ошибка приложения блогов: ошибка фильтрации сообщений по категориям. Ошибка приведения к объектному идентификатору. - PullRequest
1 голос
/ 30 апреля 2020

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

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

Я столкнулся с проблемой, пытаясь отфильтровать сообщения по категориям. Чтобы получить пост по URL категории, я превращаю название категории в слаг и использую его следующим образом:

Posted in <a href="/<%= post.category.cat_name.replace(/\s+/g, '-').toLowerCase(); %>"><%= post.category.cat_name %></a>

В файле маршрутов publi c у меня есть:

const express = require('express');
const postsController = require('../../controllers/front-end/posts');

// Express router
const router = express.Router();

// Get Posts
router.get('/', postsController.getPosts);

// Get Single Post
router.get('/:id', postsController.getSinglePost);

// Get Posts by Category
router.get('/:catname', postsController.getPostsByCategory);

module.exports = router;

Пост модель:

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);

Категория модель:

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);

В контроллере сообщений я превращаю слаг обратно в категорию имя для фильтрации сообщений по названию категории :

exports.getPostsByCategory = (req, res, next) => {

    function titleize(slug) {
            var words = slug.split("-");
            return words.map(function(word) {
                //return word;
                return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
            }).join(' ');
        }

    const postCategory = titleize(req.params.catname);

   const posts = Post.find({ cat_name: postCategory }, (err, posts) => {
        console.log('Category: ', postCategory);
        if(err){
            console.log('Error: ', err);
        } else {
            res.render('default/index', {
                moment: moment,
                layout: 'default/layout',
                website_name: 'MEAN Blog',
                page_heading: 'XPress News',
                page_subheading: 'A MEAN Stack Blogging Application',
                posts: posts.reverse(),
            });
        }
    }).populate('category');
};

Строка console.log('Category: ', postCategory) выводит Category: Favicon.ico вместо названия категории .

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

Ответы [ 4 ]

1 голос
/ 01 мая 2020

, если я правильно прочитал, res - это ожидаемое json пар.

Я предполагаю, что ваш post.reverse() не выводит в формате json.

1 голос
/ 05 мая 2020

в первую очередь - посмотрите на момент, когда вы спрашиваете DB - вам нужно дождаться ответа, поэтому вы должны использовать Promise.than() или async/await в ваших маршрутах ... Еще один из запроса, вы получаете STRING в качестве параметра - но в схеме mon go у вас есть Object ...

Таким образом, вы должны получить что-то вроде "CastError: Cast to ObjectId failed...", в зависимости от вашего видения вы можете: сначала выберите категорию из category.db =>, чтобы вы получили категорию Object после что вы можете искать сообщения, используя этот объект ..., или вы можете сначала заполнить результаты сообщений по категориям (получить простые поля категории) и выполнить дальнейший поиск ...

1 голос
/ 30 апреля 2020

category в вашей post -схеме - от $ref до category -схемы, поэтому она имеет objectId. Чтобы ссылаться и действительно запрашивать вашу category -схему при использовании .find(), вам необходимо сначала заполнить ее:

Post.
  find({}).
  populate({
    path: 'category',
    match: { cat_name: postCategory}
  }).
  exec((err, posts) => {
    // ...
  });

Документация mon goose для $ref/populate() немного скрыта здесь , если вы хотите узнать больше об этом.

0 голосов
/ 05 мая 2020

Благодаря Лилиан Баксан, вот правильный getPostsByCategory метод в controllers\front-end\posts.js:

const Category = require('../../models/categories');
//more code here

exports.getPostsByCategory = async (req, res, next) => {

    function titleize(slug) {
        var words = slug.split("-");
        return words.map(function(word) {
            //return word;
            return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase();
        }).join(' ');
    }

    const postCategory = titleize(req.params.catname);

    const singleCategory = await Category.findOne({cat_name:postCategory})

    const posts = await Post.find({ category : singleCategory }, (err, posts) => {
        if (err) {
            console.log('Error: ', err);
        } else {
            res.render('default/index', {
                moment: moment,
                layout: 'default/layout',
                website_name: 'MEAN Blog',
                page_heading: 'XPress News',
                page_subheading: 'A MEAN Stack Blogging Application',
                posts: posts.reverse(),
            });
        }
    }).populate('category');
};
...