Express.js 博客应用程序错误:按类别过滤帖子引发 "Cast to ObjectId failed" 失败错误
Express.js blogging application bug: filtering posts by category throws "Cast to ObjectId failed" failed error
我正在研究 blogging application (click the link to see the GitHub repo) with Express, EJS 和 MongoDB。
我有 Posts,它们被分为 类别,每个类别都有自己的集合。
我 运行 在尝试按类别过滤 post 时遇到了问题。要按类别 url 获取 post,我将类别名称变成一个 slug 并这样使用:
Posted in <a href="/<%= post.category.cat_name.replace(/\s+/g, '-').toLowerCase(); %>"><%= post.category.cat_name %></a>
在 public 路由文件中我有:
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;
Post型号:
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);
在 Posts 控制器中,我将 slug 变回类别名称以按类别名称posts 过滤 :
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
而不是类别名称。
我做错了什么?
category
在您的 post
-schema 中是 $ref
到 category
-schema,这就是它持有 objectId
的原因。为了在使用 .find()
时引用并实际查询您的 category
-schema,您需要先填充它:
Post.
find({}).
populate({
path: 'category',
match: { cat_name: postCategory}
}).
exec((err, posts) => {
// ...
});
$ref/populate()
的 mongoose 文档有点隐藏 here,以防您想了解更多。
如果我没看错的话,res 应该是 json 对。
我猜你的 post.reverse()
没有以 json 格式输出。
首先 - 看看你问 DB 的那一刻 - 你需要等待答案,所以你应该在你的路线中使用 Promise.than()
或 async/await
...
另一个来自请求你得到 STRING 作为参数 - 但在 mongo 模式中你有 Object...
所以你应该收到像 "CastError: Cast to ObjectId failed..."
这样的东西,
这取决于你的视野,你可以:首先 select category from category.db =>
所以你收到 category Object 然后你可以使用这个对象搜索帖子......,或者你可以先按类别填充帖子的结果(获取普通类别字段)并进行进一步搜索...
感谢 Lilian Baxan,这是 controllers\front-end\posts.js
中正确的 getPostsByCategory
方法:
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');
};
我正在研究 blogging application (click the link to see the GitHub repo) with Express, EJS 和 MongoDB。
我有 Posts,它们被分为 类别,每个类别都有自己的集合。
我 运行 在尝试按类别过滤 post 时遇到了问题。要按类别 url 获取 post,我将类别名称变成一个 slug 并这样使用:
Posted in <a href="/<%= post.category.cat_name.replace(/\s+/g, '-').toLowerCase(); %>"><%= post.category.cat_name %></a>
在 public 路由文件中我有:
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;
Post型号:
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);
在 Posts 控制器中,我将 slug 变回类别名称以按类别名称posts 过滤 :
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
而不是类别名称。
我做错了什么?
category
在您的 post
-schema 中是 $ref
到 category
-schema,这就是它持有 objectId
的原因。为了在使用 .find()
时引用并实际查询您的 category
-schema,您需要先填充它:
Post.
find({}).
populate({
path: 'category',
match: { cat_name: postCategory}
}).
exec((err, posts) => {
// ...
});
$ref/populate()
的 mongoose 文档有点隐藏 here,以防您想了解更多。
如果我没看错的话,res 应该是 json 对。
我猜你的 post.reverse()
没有以 json 格式输出。
首先 - 看看你问 DB 的那一刻 - 你需要等待答案,所以你应该在你的路线中使用 Promise.than()
或 async/await
...
另一个来自请求你得到 STRING 作为参数 - 但在 mongo 模式中你有 Object...
所以你应该收到像 "CastError: Cast to ObjectId failed..."
这样的东西,
这取决于你的视野,你可以:首先 select category from category.db =>
所以你收到 category Object 然后你可以使用这个对象搜索帖子......,或者你可以先按类别填充帖子的结果(获取普通类别字段)并进行进一步搜索...
感谢 Lilian Baxan,这是 controllers\front-end\posts.js
中正确的 getPostsByCategory
方法:
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');
};