[英]Unable to get data from new collection on mongodb on node.js using mongoose
[英]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.