簡體   English   中英

使用節點獲取mongodb集合

[英]Get mongodb collection with node

我對表達/ mongo堆棧很陌生,所以問題很簡單,在stackoverflow上找不到任何可以解決我問題的東西,所以這里是:

我有一個index.js文件,看起來或多或少像這樣:

var mongoose = require('mongoose');

// Connections
var developmentDb = 'mongodb://localhost/admin';
var usedDb;

// If we're in development...
if (process.env.NODE_ENV === 'development') {
    // set our database to the development one
    usedDb = developmentDb;
    // connect to it via mongoose
    mongoose.connect(usedDb);
}

// get an instance of our connection to our database
var db = mongoose.connection;

db.once('open', function callback () {
    console.log('Databsae Connection Successfully Opened at ' + usedDb);
});

module.exports = db;

然后,我在這樣的快速路線中要求它:

var express = require('express');
var router = express.Router();
var db = require('../../database');

/* GET users listing. */
router.get('/', function(req, res) {
    var users = db.collection('users');
    var test = users.find();
    res.send(test);
});

module.exports = router;

我正在發送請求,得到的結果是“未定義”,因此后端未返回任何內容。

DB連接是100%正確並且可以正常工作。

我不能完全確定,我是否必須在快速方面有一個架構定義,還是可以在不了解該架構的情況下查詢任何數據?

您在這里所缺少的是一些“貓鼬魔術”,實際上是在“幕后”發生的。 這也是node.js中大多數操作的基本概念,即這些操作(尤其是在涉及IO的情況下)實際上本質上是異步的,因此您通常使用的是在操作完成時觸發的回調。

采取您的清單的此部分:

// get an instance of our connection to our database
var db = mongoose.connection;

db.once('open', function callback () {
    console.log('Databsae Connection Successfully Opened at ' + usedDb);
});

module.exports = db;

因此,盡管您可能已經按順序進行了編碼,但是事件的實際順序並不像您想象的那樣。 盡管您可以從mongoose.connection調用db對象mongoose.connection ( and actually this is a connection object and not the底層驅動程序實現mongoose.connection ( and actually this is a connection object and not the Db`對象),但不能保證此時數據庫實際上已連接。 實際上,事實並非如此。

這里的排序點是,數據庫連接實際上是從模塊中導出變量之后而不是之前進行的。 它不等待上一行完成,也不能這樣做。

貓鼬本身更具有“模型”的概念來表示數據庫中的集合。 因此,通常的方法是定義這些模型對象並將其用於訪問數據:

var Model = mongoose.model( 'Model', modelSchema, 'optionalCollectionName' );

Model.find({}, function(err,data) { 
   // do stuff in the callback
});

造成這種情況的部分原因(除了附帶的模式定義以外)實際上是在進行與連接有關的其他操作。 這些對象實際上具有內部邏輯,僅在與數據庫的連接可用時才處理綁定的“集合”對象上的操作。 因此,這里發生了一個“內部回調”函數,其中實際使用了內部連接對象。

這是一些簡單的代碼,它們“重寫”內部方法的使用,以僅嘗試從驅動程序中獲取基礎集合對象。 它將失敗:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema

mongoose.connect('mongodb://localhost/test');

var modelSchema = new Schema({},{ strict: false });
var Model = mongoose.model( 'Model', modelSchema, 'optionalCollectionName' );

Model.collection.find({}, function(err,data) { 
   // do stuff in the callback
});

由於這要求返回在底層驅動程序中實現的集合對象,並要求使用該對象的本機.find()方法,因此出現了尚未實際連接數據庫的問題。 因此,為了使此工作正常進行,您需要將調用包裝在事件處理程序中,該事件處理程序僅在真正連接數據庫時才觸發。 否則,請確保在調用之前已建立連接:

mongoose.connection.on('open',function(err,conn) {

    // Now we know we are connected.
    Model.collection.find({}, function(err,data) { 
       // do stuff in the callback
    });
});

因此,模型對象實際上是在為您執行此操作,並提供了它們自己的標准方法(例如“查找”,“更新”等)的實現。

如果您不想進行這種包裝,並且模型的定義似乎工作量很大,甚至使用此處的{ strict: false }修飾符,它可以放寬對模式的約束以有效地允許任何數據,然后您最好使用基本驅動程序而不是貓鼬。

但是,當然,您需要比將所有代碼包裝在連接的回調中更聰明的方法。 這是一種定義對象的方法,可用於為您“獲取”數據庫連接,並確保在建立該連接之前不執行任何操作:

var async = require('async'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient;


var Model = (function() {

  var _db,
      conlock;
  return {
    getDb: function(callback) {
      var err = null;
      if ( _db == null && conlock == null ) {
        conlock = 1;
        MongoClient.connect('mongodb://localhost/test',function(err,db) {
          _db = db;
          conlock == null;
          if (!err) {
            console.log("Connected")
          }
          callback(err,_db);
        });
      } else if ( conlock != null ) {
        var count = 0;
        async.whilst(
          function() { return ( _db == null ) && (count < 5) },
          function(callback) {
            count++
            setTimeout(callback,500);
          },
          function(err) {
            if ( count == 5 )
              err = new Error("connect wait exceeded");
            callback(err,_db);
          }
        );
      } else {
        callback(err,_db);
      }
    }
  };

})();


async.parallel(
  [
    function(callback) {
      console.log("call model");
      Model.getDb(function(err,db) {
        if (err) throw err;
        if (db != undefined)
          console.log("db is defined");
        callback();
      });
    },
    function(callback) {
      console.log("call model again");
      Model.getDb(function(err,db) {
        if (err) throw err;
        if (db != undefined)
          console.log("db is defined here as well");
        callback();
      });
    }
  ],
  function(err) {
    Model.getDb(function(err,db) {
      db.close();
    });
  }
);

這基本上是通過.getDb()的單個方法包裝了一個在這里稱為“模型”的對象。 該方法只接受一個回調,即存在您要用來訪問數據庫的實際代碼段,該代碼進而從連接中公開Db對象。

Db對象內部存儲在該對象中,因此它基本上是單例,僅一次連接到數據庫。 但是,由於您的邏輯是通過回調函數傳遞的,因此它要么只是傳遞現有的存儲對象,要么等到建立連接后再傳遞代碼。

樣本用法的輸出應為:

通話模型
再次調用模型
連接的
db已定義
db也在這里定義

這表明了事件的順序以及它們如何實際發生。

因此,有不同的處理方式。 貓鼬模型為您“抽象”了很多。 當然,您可以按照示例中的說明使用基本驅動程序進行基本處理,也可以更進一步實現自己的連接系統,包括覆蓋的方法,這些方法執行的功能與貓鼬在下面做的很多事情相同。 還有其他包裝器庫已經執行了此操作,而沒有貓鼬通常固有的架構概念。

不過,基本上,基本驅動程序之上的每個更高級別的庫都與上述操作大致相同,其中方法周圍都有包裝程序,以確保存在連接,而無需將所有代碼都嵌入到檢查該事件的偵聽器中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM