【问题标题】:How do I query the database using Mongodb after I set up a Mongoose schema for authentication?设置 Mongoose 模式进行身份验证后,如何使用 Mongodb 查询数据库?
【发布时间】: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


    【解决方案1】:

    我可以通过像这样编写到 mongodb 的连接来解决这个问题:

    const MONGO_URI="mongodb+srv://<username>:<password>@<insert string><database>?retryWrites=true&w=majority";
    mongoose
     .connect(MONGO_URI, {useNewUrlParser: true, useUnifiedTopology: true})
     .then(console.log(`MongoDB connected ${MONGO_URI}`))
     .catch(err=>console.log(err));
    

    然后我这样写查询:

    app.get("/leaderboard", async function(req, res) {
     const client = await mongoose.connect(MONGO_URI, function (err, db){
      if (err) throw new Error(err); 
      db.collection("users").find({}, { projection: { _id: 0, username: 1, score: 1 } })
      .sort({score:-1}).limit(2)
      .toArray(function(err, result) {
        if (err)  throw new Error(err); 
        console.log(Array.from(result));
        res.send({ status: true, msg: result });
        db.close(); //I think I can omit this line. 
       }); 
     });   
    });
    

    在我使函数异步之前,我收到了一个错误报告:

    Error: MongoError: Cannot use a session that has ended
    

    我必须使这些脚本异步。

    我保留了 mongoose 模式。我仍然能够对用户进行身份验证,并将他们添加到数据库中。

    此链接SO Documentation: Node.js Mongodb integration 帮助了我。 SO 是 StackOverflow 贡献者制作的文档站点。

    【讨论】:

      猜你喜欢
      • 2021-04-28
      • 2017-03-24
      • 2018-04-25
      • 2012-06-05
      • 2019-02-12
      • 2012-01-13
      相关资源
      最近更新 更多