db.collection не є функцією при використанні MongoClient v3.0


132

Я пробував навчальний посібник W3schools на nodeJS з MongoDB.

Коли я намагаюся реалізувати цей приклад у середовищі 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)

Будь ласка, знайдіть нижче мій реалізований код:

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();
  });
});

Зауважте, що помилка виникає щоразу, коли виконується виконання:

db.collection("customers").findOne({}, function(err, result) {}

Також зауважте, (якщо це має значення), що я встановив останній пакет MongoDB для вузла JS ( npm install mongodb ), а версія MongoDB - MongoDB Enterprise 3.4.4, з драйвером MongoDB Node.js v3.0.0-rc0.


Ви переконалися: (1) база даних працює (враховуючи, що помилок не було, я думаю, що так); (2) база даних mytestingdb існує (спробуйте використовувати robomongo / robo3t для доступу до свого з'єднання та перегляду колекцій) (3) Клієнти колекції фактично існують; Розкажіть також, як ви викликаєте цей скрипт і яку версію Nodejs (як ви встановили?)
nbkhope

База даних та колекція існують (я отримав доступ до них за допомогою Studio 3t). Я налагоджую nodeJS за допомогою виклику методу через AJAX-виклик, в основному потрапляють точки прориву, і все працює добре, поки не отримаю виняток, зазначений вище. Версія NodeJS
Елі Асмар

Потім замініть код, який починається з db.collection()...журналу консолі, щоб побачити, чи потрапить він, немає проблем.
nbkhope

База даних та колекція існують (я отримав доступ до них за допомогою Studio 3t). Я налагоджую nodeJS за допомогою виклику методу через AJAX-виклик, в основному потрапляють точки прориву, і все працює добре, поки не отримаю виняток, зазначений вище. Версія NodeJS
Елі Асмар

Відповіді:


80

Я зіткнувся з тим самим. У package.json змініть рядок mongodb на "mongodb": "^ 2.2.33". Вам потрібно буде npm видалити mongodb; потім встановіть npm для встановлення цієї версії.

Це вирішило для мене питання. Здається, що помилка чи документи потребують оновлення.


15
перевірити відповідь MikaS
hartmut

67
перехід на більш ранню версію насправді не є рішенням, це просто означає, що ви не
переймаєтесь переглядом

3
@JohnCulviner - це було питання про терміни; не лінь питання. Ця проблема виникла під час виходу нового оновлення. Я (і оригінальний плакат), очевидно, цього не усвідомлював. На той час документи ще не оновлювалися. Вони були оновлені незабаром після. Кожен, хто хоче вирішити цю проблему на даний момент, повинен слідувати за коментарем MikaS та переглянути оновлені документи. Я зробив те саме після оновлення документів і зміг продовжити оновлену версію.
AyoO

1
Зараз я пережив це питання - я стикався з цією проблемою і мав "mongodb:" "3.0.2", встановлений у package.json, чи є проблеми з новою версією?
logos_164

4
Не допомагає зовсім. Чому це позначено як правильну відповідь?
CodingNow

482

Для людей версії 3.0 рідного драйвера NodeJS MongoDB:

(Це стосується людей з "mongodb": "^ 3.0.0-rc0" або більш пізньої версії в package.json, які хочуть продовжувати використовувати останню версію.)

У версії 2.x рідного драйвера NodeJS MongoDB ви отримаєте об'єкт бази даних як аргумент для зворотного виклику підключення:

MongoClient.connect('mongodb://localhost:27017/mytestingdb', (err, db) => {
  // Database returned
});

Відповідно до журналу змін для 3.0, ви отримуєте замість цього об'єкт клієнта, що містить об'єкт бази даних:

MongoClient.connect('mongodb://localhost:27017', (err, client) => {
  // Client returned
  var db = client.db('mytestingdb');
});

close()Метод також був переміщений до клієнта. Код у питанні, таким чином, можна перекласти на:

MongoClient.connect('mongodb://localhost', function (err, client) {
  if (err) throw err;

  var db = client.db('mytestingdb');

  db.collection('customers').findOne({}, function (findErr, result) {
    if (findErr) throw findErr;
    console.log(result.name);
    client.close();
  });
}); 

Тепер ми повинні писати цей ( var db = client.db('mytestingdb');) додатковий рядок кожен раз, а не просто писати так ( MongoClient.connect('mongodb://localhost:27017/mytestingdb'))? Я завжди працюю з однією і тією ж базою даних. Чи є якийсь підхід до усунення цієї додаткової лінії? Це якось для мене забирає багато часу.
озгрозер

7
@ozgrozer Здається, що ви підключаєтесь до db для кожного запиту. Це вважається поганою ідеєю. Про це можна прочитати тут . Якщо ви підключаєтесь лише один раз, для кожного створеного додатку є лише один новий рядок.
Міка Сандленд

1
@MikaS О так. Я підключався до db, як ви сказали. Я не знав, що ми можемо один раз підключитися і повторно використовувати змінну db. Дуже дякую.
озгрозер

1
Чудова відповідь; Зрозумівши, що це був час смоктання, я повинен пам'ятати, що RTFM
Mr.Budris,

Я реалізував клієнт так, але все ще є ті ж проблеми (db.collection - це не функція) всередині \ node_modules \ mongodb \ lib \ gridfs-stream \ index.js: 50: 27
alex351

34

Тим, хто хоче продовжувати використовувати версію ^ 3.0.1, пам’ятайте про зміни способу використання MongoClient.connect()методу. Зворотний виклик не повертається, dbа повертається client, проти чого існує функція db(dbname), яку потрібно викликати, щоб отримати потрібний dbекземпляр.

const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');

// Connection URL
const url = 'mongodb://localhost:27017';

// Database Name
const dbName = 'myproject';

// Use connect method to connect to the server
MongoClient.connect(url, function(err, client) {
  assert.equal(null, err);
  console.log("Connected successfully to server");

  const db = client.db(dbName);

  client.close();
});

2
Ця відповідь є пізнішою і стосується версії 3 драйвера. Спасибі
Мохаммед

1
Я рекомендую це рішення, воно більше підходить для подальшої довідки.
Джеймі Ніколл-Шеллі

31
MongoClient.connect(url (err, client) => {
    if(err) throw err;

    let database = client.db('databaseName');

    database.collection('name').find()
    .toArray((err, results) => {
        if(err) throw err;

        results.forEach((value)=>{
            console.log(value.name);
        });
    })
})

Єдина проблема з вашим кодом полягає в тому, що ви отримуєте доступ до об'єкта, який містить обробник бази даних. Ви повинні отримати доступ до бази даних безпосередньо (див. Змінну бази даних вище). Цей код поверне вашу базу даних у масив, а потім прокрутить її і запише ім’я для всіх у базі даних.


Ця відповідь позначена як низька якість через свою довжину та зміст. Будь ласка, надайте більше інформації.
Вахіу Крістіанто

Це лише стільки, скільки потрібно. Ця відповідь мені допомогла.
Мануель Ернандес

1
@ManuelHernandez радий, що це допомогло :)
Дре Джексон

це правильний анс. Будь ласка, позначте це як правильний анс.
Нінад Камблі

12

Piggy backing на @MikkaS відповідь для Mongo Client v3.x, мені просто потрібен був формат async / wait, який виглядає дещо зміненим так:

const myFunc = async () => {

     // Prepping here...


    // Connect
    let client = await MongoClient.connect('mongodb://localhost');
    let db = await client.db();

    // Run the query
    let cursor = await db.collection('customers').find({});

    // Do whatever you want on the result.
}

7

Я трохи експериментував, щоб побачити, чи можу я зберегти ім’я бази даних як частину URL-адреси. Я віддаю перевагу синтаксису обіцянок, але він все одно повинен працювати для синтаксису зворотного виклику. Зауважте, що виклик client.db () викликається, не передаючи жодних параметрів.

MongoClient.connect(
    'mongodb://localhost:27017/mytestingdb', 
    { useNewUrlParser: true}
)
.then(client => {

    // The database name is part of the url.  client.db() seems 
    // to know that and works even without a parameter that 
    // relays the db name.
    let db = client.db(); 

    console.log('the current database is: ' + db.s.databaseName);
    // client.close() if you want to

})
.catch(err => console.log(err));

Мій package.json містить список monbodb ^ 3.2.5.

Опція "useNewUrlParser" не потрібна, якщо ви готові мати справу з попередженням про припинення роботи. Але розумно використовувати в цьому пункті, поки не вийде версія 4, де, мабуть, новий драйвер буде типовим і вам більше не потрібна ця опція.


5

Я легко вирішив це за допомогою цих кодів:

 npm uninstall mongodb --save

 npm install mongodb@2.2.33 --save

Щасливе кодування!


4

У мене версія оболонки MongoDB v3.6.4, внизу код використовується mongoclient. Це добре для мене:

var MongoClient = require('mongodb').MongoClient,
assert = require('assert');
var url = 'mongodb://localhost:27017/video';
MongoClient.connect(url,{ useNewUrlParser: true }, function(err, client) 
{
assert.equal(null, err);
console.log("Successfully connected to server");
var db = client.db('video');
// Find some documents in our collection
db.collection('movies').find({}).toArray(function(err, docs) {
// Print the documents returned
docs.forEach(function(doc) {
console.log(doc.title);
});
// Close the DB
client.close();
});
// Declare success
console.log("Called find()");
 });

Це питання стосується драйвера вузла, а не оболонки.
UpTheCreek

3

Якщо хтось все ще намагається вирішити цю помилку, я зробив це, як нижче.

const MongoClient = require('mongodb').MongoClient;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'mytestingdb';

const retrieveCustomers = (db, callback)=>{
    // Get the customers collection
    const collection = db.collection('customers');
    // Find some customers
    collection.find({}).toArray((err, customers) =>{
        if(err) throw err;
      console.log("Found the following records");
      console.log(customers)
      callback(customers);
    });
}

const retrieveCustomer = (db, callback)=>{
    // Get the customers collection
    const collection = db.collection('customers');
    // Find some customers
    collection.find({'name': 'mahendra'}).toArray((err, customers) =>{
        if(err) throw err;
      console.log("Found the following records");
      console.log(customers)
      callback(customers);
    });
}

const insertCustomers = (db, callback)=> {
    // Get the customers collection
    const collection = db.collection('customers');
    const dataArray = [{name : 'mahendra'}, {name :'divit'}, {name : 'aryan'} ];
    // Insert some customers
    collection.insertMany(dataArray, (err, result)=> {
        if(err) throw err;
        console.log("Inserted 3 customers into the collection");
        callback(result);
    });
}

// Use connect method to connect to the server
MongoClient.connect(url,{ useUnifiedTopology: true }, (err, client) => {
  console.log("Connected successfully to server");
  const db = client.db(dbName);
  insertCustomers(db, ()=> {
    retrieveCustomers(db, ()=> {
        retrieveCustomer(db, ()=> {
            client.close();
        });
    });
  });
});

Це рішення та @ Dre Jackson's - це ті, що працюють з вузлом станом на 07/2020. Схоже, те, що передається як аргумент зворотного дзвінка підключення, - це MongoClient, а не db, саме тому вам потрібно отримати з нього db. Крім цього, це рішення також перераховує ті useUnifiedTopology: true, які також потрібні сьогодні.
Coffee_fan

1

Запити MongoDB повертають курсор до масиву, що зберігається в пам'яті. Щоб отримати доступ до результату цього масиву, потрібно зателефонувати .toArray()в кінці запиту.

  db.collection("customers").find({}).toArray() 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.