我一直在使用MongoDB在nodeJS上尝试W3schools教程.
当我尝试在nodeJS环境中实现此示例并使用AJAX调用调用该函数时,我收到以下错误:
TypeError: db.collection is not a function
at c:\Users\user\Desktop\Web Project\WebService.JS:79:14
at args.push (c:\Users\user\node_modules\mongodb\lib\utils.js:431:72)
at c:\Users\user\node_modules\mongodb\lib\mongo_client.js:254:5
at connectCallback (c:\Users\user\node_modules\mongodb\lib\mongo_client.js:933:5)
at c:\Users\user\node_modules\mongodb\lib\mongo_client.js:794:11
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
Run Code Online (Sandbox Code Playgroud)
请在下面找到我实现的代码:
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/mytestingdb";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
db.collection("customers").findOne({}, function(err, result) {
if (err) throw err;
console.log(result.name);
db.close();
});
});
Run Code Online (Sandbox Code Playgroud)
请注意,只要执行命中,就会发生错误:
db.collection("customers").findOne({}, function(err, result) {}
Run Code Online (Sandbox Code Playgroud)
另外,请注意(如果重要的话)我已经为节点JS安装了最新的MongoDB软件包(npm install mongodb),而MongoDB版本是MongoDB Enterprise 3.4.4,使用MongoDB Node.js驱动程序v3.0.0-rc0.
在使用MongoDB的许多介绍性示例中,您会看到如下代码:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:port/adatabase", function(err, db)
{
/* Some operation... CRUD, etc. */
db.close();
});
Run Code Online (Sandbox Code Playgroud)
如果MongoDB与任何其他数据库系统一样,open并且close操作通常在时间上是昂贵的.
所以,我的问题是:只需执行MongoClient.connect("...一次,将返回db值分配给某个全局模块,在模块中具有各种功能进行各种与数据库相关的工作(将文档插入集合,更新文档等等)即可.当它们被应用程序的其他部分调用时(从而重新使用该db值),然后,当应用程序完成时,才会执行close.
换句话说,open并且close只完成一次 - 不是每次你都需要去做一些与数据库相关的操作.而且,当你实际完成所有与数据库相关的工作时,你不断重复使用db在初始阶段返回的对象open\connect,只在最后处理它close.
显然,由于所有的I/O都是异步的,所以在close确定最后一个数据库操作完成之后才发出close.看起来这样应该没关系,但我想仔细检查,以防万一我错过了一些东西,因为我是MongoDB的新手.谢谢!
这对我来说有点不清楚(我刚刚开始使用Node和Mongo),而且由于服务器性能和应变(我认为这是另一个问题,我真的很担心,但我会在帖子的结尾).
所以,假设我正在编写一个带有Node.js和Restify的API,其中每个API端点对应一个函数,我应该:
a)打开db连接并将其存储在全局var中,然后在每个函数中使用它?
例:
// requires and so on leave me with a db var, assume {auto_reconnect: true}
function openDB() {
db.open(function(err, db) {
// skip err handling and so on
return db;
}
}
var myOpenDB = openDB(); // use myOpenDB in every other function I have
Run Code Online (Sandbox Code Playgroud)
b)打开数据库连接,然后将所有内容放在一个巨大的闭包中?
例:
// same as above
db.open(function(err, db) {
// do everything else here, for example:
server.get('/api/dosomething', function doSomething(req, res, next) { // (server is an instance of a Restify …Run Code Online (Sandbox Code Playgroud) 我在express.js应用程序中使用mongodb-native-driver.我在数据库中有大约6个集合,所以我创建了6个js文件,每个文件都有一个集合作为javascript对象(例如function collection(){}),原型函数处理这些集合上的所有操作.我认为这将是一个很好的架构.
但我遇到的问题是如何连接到数据库?我应该在每个文件中创建一个连接并使用它们吗?我认为这将是一种矫枉过正,因为mongodb-native-driver中的连接创建了一个连接池,并且其中有几个连接不合理.
那么如何创建单个连接池并在所有collections.js文件中使用它?我希望得到像在mongoose中实现的连接.如果我在应用程序架构中的任何思维过程都是错误的,请告诉我.
使用Mongoose可以解决这些问题,但我在几个地方读过它比本机驱动程序慢,而且我更喜欢无模式模型.
编辑:我用模型创建了一个模块.每个集合都在一个文件中,它将数据库作为参数.现在在index.js文件中,我调用数据库连接并在从连接获取数据库后保留变量db.(我使用了自动重新连接功能来确保连接没有丢失).在同一个index.js文件中,我像这样导出了每个集合
exports.model1 = require('./model1').(db)
exprorts.model2 = require('./model2').(db)
Run Code Online (Sandbox Code Playgroud)
这确保了数据库的一部分,在短短一个模块处理和应用程序只需调用每个model.js文件中导出函数一样save(),fincdbyid()等(whatever you do in the function is upto you to implement).
以前我用php使用mongodb并查询我使用单例的数据库.这样我只实例化一次连接然后重用它:
class MDB{
protected static $instance;
public static function use(){
if(!self::$instance) self::$instance = new MongoClient();
$db = self::$instance->selectDB('DB_name');
return $db;
}
}
Run Code Online (Sandbox Code Playgroud)
我可以创建类Cats,并使用类似这样的方法addCat和showCats:
MDB::use->{'cats'}->insert([...]);
MDB::use->{'cats'}->find([...]);
Run Code Online (Sandbox Code Playgroud)
现在我开始使用mongodb和node.js. Mongodb教程给我看了这样的事情:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) { return console.dir(err); }
var collection = db.collection('test');
var doc1 = {'hello':'doc1'};
collection.insert(doc1);
});
Run Code Online (Sandbox Code Playgroud)
这基本上告诉我,我必须将所有节点操作设置为connect内部的回调.阅读该人提供的类似问题:
当您的应用程序启动并重用db对象时,您可以打开一次MongoClient.connect.它不是单独的连接池,每个.connect都会创建一个新的连接池.
但我无法理解我应该如何使用它(例如我的猫类)?
我在使用mongolab工作在heroku上制作node.js和mongodb时遇到了麻烦.我已经阅读了其他问题,例如如何使用MongoLab在Heroku上设置MongoDB数据库?以及如何在Node.js Web应用程序中管理MongoDB连接?但我仍然无法建立我的连接.它在日志中显示[错误:无法连接到...]
我从MONGOLAB_URI进程env获取数据库,主机和端口.我有以下代码:
var mongoUri = mongodb://heroku_app17328644:{password}@ds037518.mongolab.com //taken from process.env.MONGOLAB_URI
var host = 'mongodb://heroku_appXXXXXX:{password}@ds037518.mongolab.com';
var port = '37518';
var database = 'heroku_appXXXXXX';
Provider.db = new Db(database, new Server(host, port, { safe: true }, { auto_reconnect: true }, {}));
Provider.db.open(function(err, db){
console.log(db); //null
if (err) console.log(err);
else console.log('success');
});
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么 ?
我通过其node.js的驱动程序使用MongoDB
我通常在connect()需要执行操作时打开连接(通过方法),并close()在完成后立即关闭它(通过方法).在我的程序中,作为自然,我需要对MongoDB执行许多操作,因此我会多次打开和关闭连接.
我想知道这是一个好的做法,或者是否最好在执行第一个操作时打开连接,将其存储在变量中并使用已打开的连接进行以下操作,在程序结束时关闭它.
非常感谢任何建议.
我在 MongoDB Atlas 上看到了很多关于此警报的帖子和文章(“配置限制的连接百分比已超过 80”),但不知道如何在我的 Next.js 应用程序中解决它。
我在处理程序函数之外创建数据库连接。我使用了一个中间件withDatabase.js:
const client = new MongoClient(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
const addDbToRequest = (handler, req, res) => {
req.db = req.connection.db("MYDBNAME");
return handler(req, res);
};
const withDatabase = handler => async (req, res) => {
if (!client.isConnected()) {
await client.connect();
}
req.connection = client;
return addDbToRequest(handler, req, res);
};
export default withDatabase;
Run Code Online (Sandbox Code Playgroud)
该中间件包装了 API 端点处理程序。
现在,如果我在每个 API 处理程序完成时关闭连接,如下所示:
const { connection } = req;
if (connection) {
connection.close();
} …Run Code Online (Sandbox Code Playgroud) 在nodejs中,每个请求打开mongodb连接并在回调中关闭它是一个好习惯吗?
app.get('/some_route', function(){
MongoClient.connect(url,function(err, db){
//some db query with callback
db.collection("some_collection").findOne(doc, function(err,item){
if(err){
res.send(err);
//close db connection
db.close();
}else{
//do something with item
res.send(item);
//close db connection
db.close();
}
});
});
Run Code Online (Sandbox Code Playgroud)
有些人说没有必要在每个请求上打开/关闭mongodb连接,因为一旦打开,就可以共享一个连接池.
问题是如何维护和共享该池?猫鼬已经自动完成吗?
特别是,在mongodb超时或断开连接时,是否需要重新连接?
我发现这里有矛盾的答案,不管是否请求mongodb连接
几乎所有在线doc node都是mongodb本机驱动程序和我读过的示例代码,db.open()与回调中某处的db.close()配对.
因为如果共享连接池,可能会编码
根据christkv的回答,人们可能会编码:
var p_db=null;
var c_opt = {server:{auto_reconnect:true}};
app.get('/some_route', function(){
//pseudo code
if (!p_db){
MongoClient.connect(url, c_opt, function(err,db){
p_db = db;
p_db.collection("some_collection").findOne(doc, function(err,item){
if(err){
res.send(err);
}else{
//do something with item
res.send(item);
}
});
});
}else {
p_db.collection("some_collection").findOne(doc, function(err,item){
if(err){
res.send(err);
}else{
//do …Run Code Online (Sandbox Code Playgroud) 我使用Node-Mongo-Native并尝试设置全局连接变量,但我对两种可能的解决方案感到困惑.你能帮我解决哪一个会是好人吗?1.解决方案(这很糟糕,因为每个请求都会尝试创建新连接.)
var express = require('express');
var app = express();
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// Connection URL
var url = '[connectionString]]';
// start server on port 3000
app.listen(3000, '0.0.0.0', function() {
// print a message when the server starts listening
console.log("server starting");
});
// Use connect method to connect to the server when the page is requested
app.get('/', function(request, response) {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
db.listCollections({}).toArray(function(err, collections) {
assert.equal(null, err);
collections.forEach(function(collection) {
console.log(collection); …Run Code Online (Sandbox Code Playgroud)