[英]mongoose post.save failing on heroku, works on localhost
我试图通过节点、快递、mongoose 和 heroku 简单地发布到我的 MongoDB Atlas db。 一个 Postman POST 请求,带有正文的原始 JSON:
{
"title": "heroku post",
"description": "post me plsssss"
}
使用这个确切的代码在本地主机上工作,但是当通过 heroku 上传时,try/catch 块在post.save()
失败,因为响应是错误。
{
"error": "there's an error",
"message": {}
}
但是错误是空的,我不确定如何调试它。 我已经输入了mongoose.set('debug', true);
在app.js
中,我修改了我的 package.json: "start": "node app.js DEBUG=mquery",
但那些没有额外的 Z78E6221F6393D1356681DB398F14CE6 看到。 有没有其他方法可以知道为什么 post.save() 会引发错误,一些我没有使用的日志..以及如何查看这些日志? 或者,如果您只知道问题所在?
应用程序.js
//use dotenv to store secret keys
require("dotenv").config();
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const cors = require('cors');
//connect to DB
mongoose.connect("mongodb+srv://grushevskiy:intercom@cluster-rest.4luv0.mongodb.net/cluster-rest?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, dbName: "cluster-rest" }, () => {
console.log('connected to DB!')
})
mongoose.set('debug', true);
const db = mongoose.connection;
db.once('open', () => {
console.log('connection opened')
});
//import routes for middleware
const postsRoute = require('./routes/posts');
//midleware routes
app.use('/posts', postsRoute)
//ROUTES
app.get('/', (req,res) => {
res.send('we are on home')
})
//MIDDLEWARES
//cors
app.use(cors());
//decode url special characters
app.use(express.urlencoded({ extended: true }));
//parse json POSTs
app.use(express.json());
//How do we start listening to the server
app.listen( process.env.PORT || 3000);
帖子.js
const express = require ('express')
const router = express.Router();
const Post = require('../models/Post')
//SUBMIT A POST
router.post('/', async (req,res) => {
const post = new Post({
title: req.body.title,
description: req.body.description
});
console.log(post)
try {
const savedPost = await post.save();
res.json(savedPost);
console.log(savedPost)
} catch (err) {
res.json({ error: "there's an error", message: err, })
}
})
module.exports = router;
Post.js Model
const mongoose = require('mongoose')
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
})
module.exports = mongoose.model('Post', PostSchema)
当我输入heroku logs --tail
时没有错误,最初也是“连接到数据库”。 消息来得有点晚。? 我想知道这是否是异步/等待的问题。 我的 package:json:
{
"name": "22-npmexpressrestapi",
"version": "1.0.0",
"engines": {
"node": "14.15.3",
"npm": "6.14.9"
},
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js DEBUG=mquery",
"start:dev": "node app.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"express": "^4.17.1",
"nodemon": "^2.0.7"
},
"dependencies": {
"dotenv": "^8.2.0",
"express": "4.17.1",
"cors": "^2.8.5",
"mongoose": "^5.11.11"
}
}
仔细阅读您的问题后,我有一些建议,我认为您可能想尝试一下。 首先,让我解释一下自己:
In my experience, when one learns how to build REST APIs with Node.js, using mongoose to communicate with a MongoDB cluster, this is what the sequence of events of their index.js
file looks like:
当应用程序和数据库足够简单时,这就像一个魅力。 我已经使用这些相同的步骤构建了多个服务并将它们投入生产,而没有注意到 mongoose 和应用程序之间存在任何错误通信。 但是,如果您检查您提供的 App.js 代码,您会发现您的情况有所不同:您只有在设置应用程序、它的中间件和它的路由之后才连接到您的 Mongo 集群。 如果其中任何一个依赖于 mongoose 实例或要运行的模型,则很有可能当 Heroku 的编译器到达您的路由需要连接到数据库的地步时,它根本没有实现该连接(意味着尚未运行 mongoose.connect() 部分)喷射。
我认为 Heroku 运行整个代码的时间比本地机器长一点。 此外,如果您的本地版本连接到本地存储的 MongoDB,则很有可能比在云服务中运行得更快。 你的陈述
'连接到数据库! 消息来的有点晚
给了我希望,情况可能就是这样。 如果是这样,那我猜那是移动
mongoose.connect("mongodb+srv://xxxxx:xxxxx@cluster-rest.4luv0.mongodb.net/cluster-rest?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, dbName: "cluster-rest" }, () => {console.log('connected to DB;')});
到App.js
的第二行,在你调用 Dotenv 之后,就可以了。 您的 mongoose 实例将 go 进入已经与数据库和 App 将要使用的模型连接的 App。
即使我之前写的内容解决了您的问题,我也想扩展解释,因为根据我的经验,该版本的解决方案也不正确。 我在这个答案开头暴露的做事方式是好的......只要你保持你的 MongoDB 集群和你的 mongoose 实例简单。 不久前,我不得不实现一个涉及更复杂数据库模式的服务,同一个 App 使用多个不同的数据库,并且它的许多路由直接取决于这些数据库的模型。
当我尝试使用我之前描述的逻辑来解决这样一个问题时,涉及到大量填充的数据库和 mongoose 实例中包含的几个模型,我意识到与连接到 mongoose 相比,Node 构建应用程序、它的中间件和它的路由要少得多并加载同一个应用程序运行所需的所有模型。 这意味着在实际连接数据库之前,我的Server connected to PORT ****
消息。 这造成了麻烦。
这让我意识到,正确做事的唯一方法是确保异步性,只有在所有数据库和模型都加载到 mongoose 实例中并为其提供相同的实例后,才强制 App 运行。 这样,我最终得到了一个如下所示的index.js
:
const Dotenv = require("dotenv").config(); const { connectMongoose } = require("./server/db/mongoose"); const wrappedApp = require("./app"); connectMongoose().then((mongoose) => { const App = wrappedApp(mongoose); App.listen(process.env.PORT, () => { console.log( `Hello, I'm your server and I'm working on port ${process.env.PORT}` ); }); });
一个包含多个函数的文件,用于管理与我的数据库和模型的连接,名为mongoose.js
。 以正确顺序实现所有连接的 function 看起来是:
const connectMongoose = async (mongoose = require("mongoose")) => { try { // Close any previous connections await mongoose.disconnect(); // Connect the Main database console.log( "--> Loading databases and models from MongoDB. Please don't use our server jet. <--" ); mongoose = await connectMother(mongoose); // Connect all the client databases mongoose = await connectChildren(mongoose); console.log( "--> All databases and models loaded correctly. You can work now. <--" ); return mongoose; } catch (e) { console.error(e); } }; module.exports = { connectMongoose };
有了这个,文件app.js
会返回一个 function ,需要为它提供一个 mongoose 实例并设置所有 Express 环境:
module.exports = (Mongoose) => { const Express = require("express"); //Enrouting // Other required packages go here // EXPRESS SETTINGS const App = Express(); App.set("port", process.env.PORT || 3000); //Use port from cloud server // All the middleware App needs App.use(Flash()); // Routing: load your routes // Return fully formed App return App; };
只有使用这种模式,我才能确保事件链有意义:
如果您的数据库不是很大,那么答案的第一部分可能会起作用。 但了解整个故事总是有用的。
当我添加错误的连接字符串时,我可以使用您的代码获得一个空的错误消息。
此回调中的 console.log 不正确:
mongoose.connect("mongodb+srv://xxxxx:xxxxx@cluster-rest.4luv0.mongodb.net/cluster-rest?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, dbName: "cluster-rest" }, () => {
console.log('connected to DB!')
})
如果您想知道您是否已连接到 db,请使用以下命令:
mongoose.connect("mongodb+srv://xxxxx:xxxxx@cluster-rest.4luv0.mongodb.net/cluster-rest?retryWrites=true&w=majority", { useNewUrlParser: true, useUnifiedTopology: true, dbName: "cluster-rest" });
const db = mongoose.connection;
db.once('open', () => {
console.log('connection opened')
});
我注意到您正在使用dotenv ,也许您没有向 heroku 主机添加变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.