【问题标题】:How to connect from NodeJS to MongoDB using Unified Topology and Promises如何使用统一拓扑和承诺从 NodeJS 连接到 MongoDB
【发布时间】:2020-04-16 20:40:55
【问题描述】:

我是 MongoDB 新手 - 对于任何 pebkac,请提前抱歉。

根据this article,统一拓扑范式摆脱了“连接”的概念,而是简单地设置连接字符串并开始执行操作。然后每个操作会失败或成功,具体取决于驱动程序在执行该操作时是否可以到达服务器。

我正在尝试实现以下示例代码以在我的测试机器上建立与本地 MongoDB 服务器的“连接”,但它不起作用:Node 正在抛出未捕获的 Promise Reject 消息,显然是因为它在某个地方出错了大大地。

但是,示例代码并未展示如何使用 Promises 实现新范式。我假设这是主要问题,所以我尝试了下面显示的第二个代码,但仍然没有得到允许我检索记录的对象。您能否告知我做错了什么,以及在 Express 应用中执行此操作以确保其尽可能稳定的推荐/最佳方法?

第一次尝试: index.js:

async function init(){
    console.log("Starting...");
    const MongoClient = require('mongodb');
    const client = MongoClient('mongodb://test:test@localhost:27017', { useUnifiedTopology: true });
    const coll = client.db('test').collection('foo');
    await coll.insert({ test: 'document' });
    const docs = coll.find({ test: 1 }, { readPreference: 'secondary' }).toArray();
    console.dir({ docs });
    await client.close();
}


init();

错误:

Starting...
(node:15328) UnhandledPromiseRejectionWarning: TypeError: client.db is not a function
    at init (index.js:5:22)
    at Object.<anonymous> (index.js:13:1)
    at Module._compile (internal/modules/cjs/loader.js:1128:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1167:10)
    at Module.load (internal/modules/cjs/loader.js:983:32)
    at Function.Module._load (internal/modules/cjs/loader.js:891:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47
(node:15328) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:15328) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

所以很明显这是在尝试使用 Promises,但是示例并没有以这种方式实现。

这是第二次尝试:

index.js:

async function init(){
    console.log("Starting...");
    const MongoClient = require('mongodb');
    const client = MongoClient('mongodb://test:test@localhost:27017', { useUnifiedTopology: true })
        .then(async (result) => {
            console.log("Connected: result = ", result);

            const db = result('test');  // Get the 'test' database
            const coll = db.collection('foo');  // Ge the 'foo' collection
            await coll.insert( { test: 'document' });   // Create a new document
            const docs = coll.find({}, { readPreference: 'secondary'})  // Retrieve all docs
                .then((results) => {
                    const data = results.toArray();
                    console.log('Results: ', data);
                });
            await client.close();

        })
        .catch((err) => {
            console.log('Caught error: ', err);
        });
}


init();

输出:

Starting...
Connected: result =  MongoClient {
  _events: [Object: null prototype] { newListener: [Function (anonymous)] },
  _eventsCount: 1,
  _maxListeners: undefined,
  s: {
    url: 'mongodb://test:test@localhost:27017',
    options: {
      servers: [Array],
      caseTranslate: true,
      useUnifiedTopology: true,
      checkServerIdentity: true,
      sslValidate: true,
      auth: [Object],
      authSource: 'admin',
      dbName: 'test',
      socketTimeoutMS: 360000,
      connectTimeoutMS: 30000,
      retryWrites: true,
      useRecoveryToken: true,
      readPreference: [ReadPreference],
      credentials: [MongoCredentials],
      promiseLibrary: [Function: Promise]
    },
    promiseLibrary: [Function: Promise],
    dbCache: Map {},
    sessions: Set {},
    writeConcern: undefined,
    namespace: MongoDBNamespace { db: 'admin', collection: undefined }
  },
  topology: NativeTopology {
    _events: [Object: null prototype] {
      authenticated: [Function (anonymous)],
      error: [Function (anonymous)],
      timeout: [Function (anonymous)],
      close: [Function (anonymous)],
      parseError: [Function (anonymous)],
      fullsetup: [Function],
      all: [Function],
      reconnect: [Function (anonymous)],
      serverOpening: [Function (anonymous)],
      serverDescriptionChanged: [Function (anonymous)],
      serverHeartbeatStarted: [Function (anonymous)],
      serverHeartbeatSucceeded: [Function (anonymous)],
      serverHeartbeatFailed: [Function (anonymous)],
      serverClosed: [Function (anonymous)],
      topologyOpening: [Function (anonymous)],
      topologyClosed: [Function (anonymous)],
      topologyDescriptionChanged: [Function (anonymous)],
      commandStarted: [Function (anonymous)],
      commandSucceeded: [Function (anonymous)],
      commandFailed: [Function (anonymous)],
      joined: [Function (anonymous)],
      left: [Function (anonymous)],
      ping: [Function (anonymous)],
      ha: [Function (anonymous)]
    },
    _eventsCount: 24,
    _maxListeners: Infinity,
    s: {
      id: 0,
      options: [Object],
      seedlist: [Array],
      state: 'connected',
      description: [TopologyDescription],
      serverSelectionTimeoutMS: 30000,
      heartbeatFrequencyMS: 10000,
      minHeartbeatFrequencyMS: 500,
      Cursor: [Function: Cursor],
      bson: BSON {},
      servers: [Map],
      sessionPool: [ServerSessionPool],
      sessions: Set {},
      promiseLibrary: [Function: Promise],
      credentials: [MongoCredentials],
      clusterTime: null,
      iterationTimers: Set {},
      connectionTimers: Set {},
      clientInfo: [Object]
    }
  }
}

Caught error:  TypeError: result is not a function
    at index.js:8:15
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

【问题讨论】:

  • 你为什么不用猫鼬?
  • @MaheshBhatnagar 是 Mongoose 的行业最佳实践吗?我真的不想要一个完整的 ORM,只想要基本的 CRUD 访问。
  • 好的,我们可以连接 gmail hangout 吗??
  • 好的,你的联系方式是什么
  • 感谢@MaheshBhatnagar,我在第二个例子中搞砸了一行:const db = result('test'); // Get the 'test' database 应该是const db = result.db('test'); // Get the 'test' database

标签: javascript node.js mongodb database-connection


【解决方案1】:

这是使用统一拓扑范例从 Node.JS 连接到 MongoDB 数据库的完整示例(没有明确的 connect 命令)。感谢@MaheshBhatnagar 指出我的错误。

此示例使用 Promises,并在建立连接后,开始以每 5 秒插入一条的频率插入记录。如果您禁用或断开 MongoDB 数据库,它将缓存插入,直到其中之一(a. 超时,默认为 30 秒,或 b. 连接恢复)。如果超时,插入会丢失,但如果服务器恢复在线,后续请求将得到妥善处理。

如果我做错了,或者有任何建议,请告诉我。

index.js:

const url = 'mongodb://test:test@localhost:27017';


async function init(){
    console.log("init...");
    const MongoClient = require('mongodb');

    return MongoClient(url, { useUnifiedTopology: true}); // Return a Promise
}


async function go(db_result) {
    // Do an insert and output the last-inserted document.
    console.log("Go...");

    const db = db_result.db('test');  // Get the 'test' database
    const coll = db.collection('foo');  // Ge the 'foo' collection
    // Create a new document:
    await coll.insertOne({ test: 'document' }, (err, response) => {
        if (err) {
            console.log("Error inserting", err);
        }
        else
        {
            console.log("New record: ", response.ops[0])  // Output newly inserted record (thanks to https://stackoverflow.com/questions/40766654)
        }
    });   


}

// Sleep for a specified time:
function sleep(ms) {
    return new Promise( resolve => {
        setTimeout(resolve,ms)
    })
}


init()  // Set up connection, then start doing inserts.
    .then( async (db_result) => {
        // When MongoClient is instantiated:
        while(true) {
            console.log("Going...")
            go(db_result)
            console.log("Sleeping")
            await sleep(5000);
        }
    })
    .catch((err) => {
        console.log("Caught error: ", err)
    })

【讨论】:

  • init 没有理由成为async// Return a Promise 评论具有误导性,因为 MongoClient() 返回... MongoClient;由于async 关键字,您只会得到Promise
猜你喜欢
  • 2020-04-15
  • 2021-06-21
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
相关资源
最近更新 更多