【发布时间】:2021-05-31 01:50:34
【问题描述】:
我成功地为我的应用程序设置了身份验证,这是一个 node.js (Express) 应用程序。我使用了 Passport-local,也使用了 Mongoose 模式。
文件夹结构是这样的:
app
- app.js
- config
- auth.js
- keys.js
- passport.js
- models
- User.js
- node_modules
- package-lock.json
- package.json
- routes
- index.js
- users.js
“models”文件夹内是 User.js 文件,它包含以下架构:
const mongoose=require("mongoose");
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
min: 4,
max: 255
},
email: {
type: String,
required: true,
min: 6,
max: 255
},
password: {
type: String,
required: true,
min: 6,
max: 1024
},
group: {
type: Number
},
score: {
type: Number
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model("User", UserSchema);
module.exports = User;
app.js(主文件)包含以下代码。顺便说一句,我并没有展示所有内容。连接字符串在 keys.js 文件中。
const mongoose=require("mongoose");
const db = require('./config/keys').mongoURI;
const app = express();
mongoose
.connect(
db,
{ useNewUrlParser: true ,useUnifiedTopology: true}
)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
对于不需要数据库的操作,比如打开一个.ejs文件,使用“GET”是没有问题的。我能做到。
我可以注册并登录一个用户,该用户出现在名为“users”的 Mongodb 集合中,并显示了正确的字段。在我使用 Web 应用程序中的注册和登录表单添加用户之前,此集合不存在。
现在我想在数据库中使用相同的集合(“用户”)来测试 CRUD 操作。所以我尝试了这个:
app.get("/leaderboard", function(req, res) {
db.collection("users")
.find({}, { projection: { _id: 0, username: 1, score: 1 } })
.sort({score:-1})
.limit(1)
.toArray(function(err, result) {
if (err)
res.send({ status: false, msg: "failed to retrieve players" });
console.log(Array.from(result));
res.send({ status: true, msg: result });
})
});
在向 api 添加身份验证之前,我能够毫无问题地获得此查询的结果以及对数据库的所有其他查询。
虽然集合名称不同,但我为数据库使用了不同的连接脚本。下面是这样的。 MONGO_URI 作为字符串存储在 dotenv 文件中。我也没有猫鼬模式。我只有 index.js 文件;没有其他文件夹。
// Database Connection Info
const MongoClient = require('mongodb').MongoClient;
const uri = process.env.MONGO_URI;
let db;
// Connect to the database with uri
(async () => {
let client = await MongoClient.connect(
uri,
{ useNewUrlParser: true, useUnifiedTopology: true }
);
db = client.db('name');
app.listen(PORT, async function() {
console.log('Listening on Port ${PORT}');
if (db) {
console.log('Database is Connected!');
}
});
})();
过去,我使用异步函数来获取排行榜结果。它使用不同的集合(“myCollection”)但使用相同的数据库。
app.get("/leaderboard", async function(req, res) {
try {
await db.collection("myCollection")
.find({}, { projection: { _id: 0, username: 1, score: 1 } })
.sort({score:-1})
.limit(1)
.toArray(function(err, result) {
if (err)
res.send({ status: false, msg: "failed to retrieve players" });
console.log(Array.from(result));
res.send({ status: true, msg: result });
})
} catch(err) {console.log("It failed")}
});
但即使在我添加身份验证和添加 Mongoose 模型之前,上述方法运行良好,但我现在无法显示排行榜结果。在终端中输入“节点应用程序”后,我在控制台上收到“MongoDB 已连接”消息,但没有收到任何错误消息。这是在我尝试获取排行榜之前。
我尝试获取排行榜后在控制台上收到的错误消息是:
TypeError: db.collection is not a function
我也试过下面的脚本没有成功:
app.get("/leaderboard", function(req, res) {
User
.find({}, { projection: { _id: 0, username: 1, score: 1 } })
.sort({score:-1})
.limit(1)
.toArray(function(err, result) {
if (err)
res.send({ status: false, msg: "failed to retrieve players" });
console.log(Array.from(result));
res.send({ status: true, msg: result });
})
});
我想对数据库查询使用异步函数,但找不到适用于我的新连接方式的连接脚本:“mongoose.connect”。
我觉得我必须使用“mongoose.connect”连接方式而不是“const uri = process.env.MONGO_URI;”方式,因为我使用猫鼬模式进行身份验证。这个模式会自动创建注册用户的集合。 (我没有任何真正的用户;我正在使用假用户配置文件来测试该过程。)我还假设 mongoose 和 mongodb 之间存在差异。
如果我可以使用旧方法,那将是最好的,因为我可以在脚本中使用 async/await。但是,主要问题是我根本没有得到任何结果,只有错误消息,尽管在添加身份验证之前我能够执行许多涉及数据库的操作。
【问题讨论】:
标签: javascript node.js mongodb express mongoose