设置 Mongoose 模式进行身份验证后,如何使用 Mongodb 查询数据库?

Posted

技术标签:

【中文标题】设置 Mongoose 模式进行身份验证后,如何使用 Mongodb 查询数据库?【英文标题】:How do I query the database using Mongodb after I set up a Mongoose schema for authentication? 【发布时间】: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。但是,主要问题是我根本没有得到任何结果,只有错误消息,尽管在添加身份验证之前我能够执行许多涉及数据库的操作。

【问题讨论】:

【参考方案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 是 *** 贡献者制作的文档站点。

【讨论】:

以上是关于设置 Mongoose 模式进行身份验证后,如何使用 Mongodb 查询数据库?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Web API 来对 MVC 应用程序进行身份验证

如何使用 Web API 来对 MVC 应用程序进行身份验证

如何将 Mongoose/Mongodb 与 node.js- 护照身份验证一起使用

使用 Passportjs 刷新页面后保持身份验证

如何设置PassportJS进行后端身份验证?

创建 NestFactory 后如何将 mongoose 插件设置为模式