为啥 MongoDB 填充方法在此应用程序中失败?
Posted
技术标签:
【中文标题】为啥 MongoDB 填充方法在此应用程序中失败?【英文标题】:Why does MongoDB populate method fail in this application?为什么 MongoDB 填充方法在此应用程序中失败? 【发布时间】:2020-07-27 14:20:33 【问题描述】:我正在使用Express、EJS 和 MongoDB 开发 blogging application(单击链接以查看 GitHub 存储库)。
我有 Posts 和 Post Categories,每个都在自己的集合中。
类别架构:
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>
一个对象显示在 Category 列(posts 表的):
然而,我尝试使用 <%= post.category.cat_name %>
显示 类别名称 我收到此错误:
Cannot read property 'cat_name' of null
我做错了什么?
【问题讨论】:
首先,猫鼬将您的架构在内部转换为小写字母(例如“类别”=> 类别)。因此,postSchema 中的类别应引用“类别”,因此请尝试。你有没有测试过post._id
之外的其他字段是否可以成功渲染?
@rags2riches 我试过了。 t 不是那样的。
【参考方案1】:
我发现了问题所在:我删除了一个之前分配给帖子的类别。修复很简单(在视图中):
<%= post.category != null ? post.category.cat_name : 'No category assigned' %>
而不是
<%= post.category.cat_name %>
非常感谢参与提供帮助的所有人。
【讨论】:
【参考方案2】:您可以遵循此准则
您的型号名称是:类别
// 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
)
【讨论】:
你可以使用异步等待。 我该怎么做? 我发现了问题并在其中发布了 solution。感谢您的帮助。【参考方案3】:使用 async/await 运算符,因为 populate
返回一个 Query,可以等待。更多信息和代码示例可以在Mongoose官方的documentation中找到。
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...
;
【讨论】:
我发现了问题并在其中发布了 solution。如果有兴趣,请检查它。谢谢你帮助我。以上是关于为啥 MongoDB 填充方法在此应用程序中失败?的主要内容,如果未能解决你的问题,请参考以下文章
调用 findOne 并填充时,转换为 objectid 的值失败