gpt4 book ai didi

javascript - 使用 Node 获取mongodb集合

转载 作者:行者123 更新时间:2023-12-03 11:32:53 25 4
gpt4 key购买 nike

我对表达/ 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;


因此,尽管您可能已经按顺序进行了编码,但是事件的实际顺序并不像您想象的那样。尽管您可以通过基础驱动程序实现的 db Db`对象调用 mongoose.connection ( and actually this is a connection object and not the对象,但不能保证此时数据库实际上已连接。实际上,事实并非如此。

这里的排序点是,数据库连接实际上是在从模块中导出变量之后而不是之前进行的。它不等待上一行完成,也不能这样做。

猫鼬本身更具有“模型”的概念来表示数据库中的集合。因此,通常的方法是定义这些模型对象并将其用于访问数据:

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也在这里定义


这表明了事件的顺序以及它们如何实际发生。

因此,有不同的处理方式。猫鼬模型为您“抽象”了很多。当然,您可以按照示例中的说明使用基本驱动程序进行基本处理,也可以更进一步实现自己的连接系统,包括覆盖的方法,这些方法执行的功能与猫鼬在下面做的很多事情相同。还有其他包装器库已经执行了此操作,而没有猫鼬通常固有的架构概念。

不过,基本上,基本驱动程序之上的每个更高级别的库都与上述操作大致相同,其中方法周围都有包装程序,以确保存在连接,而无需将所有代码都嵌入到检查该事件的侦听器中。

关于javascript - 使用 Node 获取mongodb集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26665256/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com