Mongoose `findOne` 操作在 10000 毫秒后超时

Posted

技术标签:

【中文标题】Mongoose `findOne` 操作在 10000 毫秒后超时【英文标题】:Mongoose `findOne` operation times out after 10000ms 【发布时间】:2021-05-28 13:45:17 【问题描述】:

这个错误真的很令人沮丧,特别是因为它是间歇性的(它来来去去)。我正在使用带有 express 和 typescript 的猫鼬,并且正在连接到 MongoDB atlas 上的数据库。这会导致糟糕的用户体验,而且并不是很酷。显示的错误消息为Operation wallets.findOne() buffering timed out after 10000ms。有时应用程序运行良好并按预期执行所有操作,但此错误会在某个时候突然出现。下面是我的代码,如果你通读它,你会看到我正在使用异步等待。

import mongoose from "mongoose";
import  Wallet  from "../../core/interfaces";
import  Tokenizers  from "../../core/utils";

export class WalletModel 
  model: mongoose.Model<any>;

  constructor() 
    this.define();
  

  private define() 
    this.model = mongoose.model(
      "Wallet",
      new mongoose.Schema(
        encryptedPrivateKey: String,
        encryptedWallet: 
          type: String,
          required: true
        
      )
    );
  

  async create(wallet: Wallet, privateKey: string): Promise<Wallet> 
    const encryptedWallet = Tokenizers.encryptWallet(wallet);
    const walletModel: any = await this.model.create(
      encryptedPrivateKey: Tokenizers.encryptPrivateKey(
        privateKey,
        wallet.publicKey
      ),
      encryptedWallet
    );
    const decryptedWallet: Wallet = Tokenizers.decryptWallet(
      walletModel.encryptedWallet,
      wallet.privateKey
    );
    return Promise.resolve(decryptedWallet);
  

  async getWallet(privateKey: string, publicKey: string): Promise<Wallet> 
    const encPrivateKey: string = Tokenizers.encryptPrivateKey(
      privateKey,
      publicKey
    );
    // Below find utilizes the indexing created on encryptedPrivateKey field
    // and is way faster than linear search on whole collection
    const encWallet: mongoose.Document & 
      encryptedPrivateKey: string;
      encryptedWallet: string;
     = (await this.model
      .findOne(
        encryptedPrivateKey: encPrivateKey
      )
      .lean()) as mongoose.Document & 
      encryptedPrivateKey: string;
      encryptedWallet: string;
    ;
    const encryptedWallet: string = encWallet.encryptedWallet;
    const decryptedWallet: Wallet = Tokenizers.decryptWallet(
      encryptedWallet,
      privateKey
    );
    return Promise.resolve(decryptedWallet);
  

  async findByPrivateKey(privateKey: string): Promise<Wallet> 
    let wallet: Wallet = null;
    const allWallets = (await this.model.find().lean()) as any;

    for (const doc of allWallets) 
      const pk = Tokenizers.decryptPrivateKey(doc.encryptedPrivateKey);
      if (pk === privateKey)
        wallet = Tokenizers.decryptWallet(doc.encryptedWallet, privateKey);
    

    return Promise.resolve(wallet);
  

  async updateWallet(privateKey: string, newWallet: Wallet): Promise<Wallet> 
    // const allWallets = await this.model.find();
    let w: Wallet = null;
    const updatedWallet = (await this.model
      .findOneAndUpdate(
        
          encryptedPrivateKey: Tokenizers.encryptPrivateKey(
            privateKey,
            newWallet.publicKey
          )
        ,
        
          encryptedWallet: Tokenizers.encryptWallet(newWallet)
        ,
        
          new: true
        
      )
      .lean()) as mongoose.Document & 
      encryptedWallet: string;
      encryptedPrivateKey: string;
    ;
    w = Tokenizers.decryptWallet(updatedWallet.encryptedWallet, privateKey);
    return Promise.resolve(w);
  

这是我启动所有服务器并建立连接的 index.ts 文件的内容:

import express from "express";
import mongoose from "mongoose";
import config from "./config";
import  Environment  from "./env";

let app: express.Application = express();
const port = process.env.PORT || 7890;

app = config(app);

app.listen(port, async () => 
  console.log(`Server listening on port $port in $process.env.NODE_ENV`);
  const mongo = await mongoose.connect(
    Environment.MONGO_URI[process.env.NODE_ENV],
    
      useNewUrlParser: true,
      useFindAndModify: false,
      useCreateIndex: true
    
  );
  if (mongo) console.log("Connected to mongodb");
);

// Export app for tests
export default app;

【问题讨论】:

【参考方案1】:

尝试在您的猫鼬模型中添加 index: true 。如果数据库记录很大,也会发生这种情况,因此建立索引有助于快速找到文档。

【讨论】:

以上是关于Mongoose `findOne` 操作在 10000 毫秒后超时的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose.js findOne 返回查询元数据

Mongoose findOne as : Array = [FindOne , FindOne, FindOne ,FindOne, FindOne...] ,使用 ExpressJs

如何使用猫鼬 findOne

mongoose.findOne() 返回 null

如何使用mongoose findOne

mongoose.findOne() 后数组被清除