db.collection nie jest funkcją w przypadku korzystania z MongoClient v3.0

140

Próbowałem samouczka W3schools na nodeJS z MongoDB.

Kiedy próbuję zaimplementować ten przykład w środowisku nodeJS i wywołać funkcję z wywołaniem AJAX, otrzymałem poniższy błąd:

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)

Poniżej znajduje się mój zaimplementowany kod:

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

Zwróć uwagę, że błąd występuje za każdym razem, gdy wykonanie trafi:

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

Zwróć też uwagę (na wypadek, gdyby miało to znaczenie), że zainstalowałem najnowszy pakiet MongoDB dla węzła JS ( npm install mongodb ), a wersja MongoDB to MongoDB Enterprise 3.4.4, ze sterownikiem MongoDB Node.js v3.0.0-rc0.

Elie Asmar
źródło
Czy upewniłeś się, że: (1) baza danych działa (zakładając, że nie było błędu, tak myślę); (2) baza danych mytestingdb istnieje (spróbuj użyć robomongo / robo3t, aby uzyskać dostęp do swojego połączenia i zobaczyć kolekcje) (3) Klienci kolekcji faktycznie istnieją; Powiedz nam również, jak nazywasz ten skrypt i jaką wersję Nodejs (jak zainstalowałeś?)
nbkhope
Baza danych i kolekcja istnieją (uzyskałem do nich dostęp za pomocą Studio 3t). Debuguję nodeJS, wywołując metodę za pomocą wywołania AJAX, w zasadzie trafiają do punktów przerwania i wszystko działa dobrze, dopóki nie otrzymam wyjątku określonego powyżej. Wersja NodeJS to 6.11.4
Elie Asmar
Następnie zastąp kod, który zaczyna się db.collection()...od, dziennikiem konsoli, aby sprawdzić, czy tam dotrze. Żaden problem.
nbkhope
Baza danych i kolekcja istnieją (uzyskałem do nich dostęp za pomocą Studio 3t). Debuguję nodeJS, wywołując metodę za pomocą wywołania AJAX, w zasadzie trafiają do punktów przerwania i wszystko działa dobrze, dopóki nie otrzymam wyjątku określonego powyżej. Wersja NodeJS to 6.11.4
Elie Asmar

Odpowiedzi:

79

Napotkałem to samo. W pliku package.json zmień wiersz mongodb na „mongodb”: „^ 2.2.33”. Będziesz musiał npm odinstalować mongodb; następnie zainstaluj npm, aby zainstalować tę wersję.

To rozwiązało problem. Wygląda na to, że jest to błąd lub dokumenty wymagają aktualizacji.

AyoO
źródło
16
sprawdzić Mikas”odpowiedź
Hartmut
68
przejście na wcześniejszą wersję nie jest tak naprawdę rozwiązaniem, po prostu oznacza, że ​​nie zawracałeś sobie głowy zmianami w API, które to spowodowały
John Culviner
3
@JohnCulviner - To był problem z synchronizacją; nie jest to kwestia lenistwa. Ten problem wystąpił, gdy byli w trakcie wydawania nowej aktualizacji. Ja (i oryginalny plakat) oczywiście nie zdawałem sobie z tego sprawy. W tym czasie dokumenty nie były jeszcze aktualizowane. Niedługo potem zostały zaktualizowane. Każdy, kto chce teraz rozwiązać ten problem, powinien postępować zgodnie z komentarzem MikaS i przejrzeć zaktualizowaną dokumentację. Zrobiłem to samo po zaktualizowaniu dokumentów i mogłem kontynuować z uaktualnioną wersją.
AyoO
1
Przechodząc przez to teraz - napotkałem ten problem i miałem zainstalowaną wersję „mongodb:” „3.0.2” w pliku package.json, czy są jakieś problemy z nową wersją?
logos_164
4
Wcale nie pomaga. Dlaczego jest oznaczona jako prawidłowa odpowiedź?
CodingNow
498

Dla osób korzystających z wersji 3.0 natywnego sterownika MongoDB NodeJS:

(Dotyczy to osób z „mongodb”: „^ 3.0.0-rc0” lub nowszą wersją w package.json, które chcą nadal używać najnowszej wersji).

W wersji 2.x natywnego sterownika MongoDB NodeJS otrzymałeś obiekt bazy danych jako argument wywołania zwrotnego connect:

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

Zgodnie z dziennikiem zmian w wersji 3.0 zamiast tego otrzymujesz obiekt klienta zawierający obiekt bazy danych:

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

close()Metoda została również przeniesiona do klienta. Kod w pytaniu można zatem przetłumaczyć na:

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();
  });
}); 
Mika Sundland
źródło
1
Czy teraz musimy za var db = client.db('mytestingdb');każdym razem pisać tę ( ) dodatkową linię zamiast po prostu pisać w ten sposób ( MongoClient.connect('mongodb://localhost:27017/mytestingdb'))? Zawsze pracuję z tą samą bazą danych. Czy jest jakieś podejście do wyeliminowania tej dodatkowej linii? To dla mnie trochę czasochłonne.
ozgrozer
7
@ozgrozer Wydaje mi się, że łączysz się z bazą danych dla każdego żądania. To zły pomysł. Możesz o tym przeczytać tutaj . Jeśli łączysz się tylko raz, dla każdej utworzonej aplikacji jest tylko jedna nowa linia.
Mika Sundland
1
@MikaS O tak. Łączyłem się z db, jak powiedziałeś. Nie wiedziałem, że możemy się połączyć raz i ponownie użyć zmiennej db. Dziękuję bardzo.
ozgrozer
1
Świetna odpowiedź; zastanawianie się, to był do dupy czas, powinienem pamiętać o RTFM
Mr.Budris
Zaimplementowałem klienta w ten sposób, ale nadal są te same problemy (db.collection nie jest funkcją) w \ node_modules \ mongodb \ lib \ gridfs-stream \ index.js:
50:27
35

Ci, którzy chcą nadal korzystać z wersji ^ 3.0.1, powinni pamiętać o zmianach w sposobie korzystania z MongoClient.connect()metody. Funkcja zwrotna nie zwraca, dba zamiast tego zwraca client, w stosunku do której istnieje funkcja db(dbname), którą należy wywołać, aby uzyskać dbżądaną instancję.

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();
});
ra9r
źródło
2
Ta odpowiedź jest nowsza i dotyczy wersji 3 sterownika. Dzięki
Mohammad
1
Polecam to rozwiązanie, jest bardziej odpowiednie do wykorzystania w przyszłości.
Jamie Nicholl-Shelley
34
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);
        });
    })
})

Jedynym problemem z kodem jest to, że uzyskujesz dostęp do obiektu, który zawiera procedurę obsługi bazy danych. Musisz uzyskać bezpośredni dostęp do bazy danych (patrz zmienna bazy danych powyżej). Ten kod zwróci bazę danych w tablicy, a następnie przejdzie przez nią w pętli i zapisze nazwy wszystkich osób w bazie danych.

Dre Jackson
źródło
Ta odpowiedź została oznaczona jako niskiej jakości ze względu na jej długość i treść. Podaj więcej informacji.
Wahyu Kristianto
To tylko tak długo, jak trzeba. Ta odpowiedź mi pomogła.
Manuel Hernandez
1
@ManuelHernandez cieszę się, że pomogło :)
Dre Jackson
to jest poprawna odpowiedź. Proszę oznaczyć to jako poprawną odpowiedź.
Ninad Kambli
13

Świnka na odpowiedź @MikkaS dla klienta Mongo v3.x, potrzebowałem tylko formatu async / await, który wygląda nieco zmodyfikowany tak:

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.
}
agarcian
źródło
9

Poeksperymentowałem trochę, aby zobaczyć, czy mogę zachować nazwę bazy danych jako część adresu URL. Wolę składnię obietnicy, ale powinna ona nadal działać dla składni wywołania zwrotnego. Zauważ poniżej, że client.db () jest wywoływana bez przekazywania żadnych parametrów.

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

Mój plik package.json zawiera listę monbodb ^ 3.2.5.

Opcja „useNewUrlParser” nie jest wymagana, jeśli chcesz poradzić sobie z ostrzeżeniem o wycofaniu. Ale rozsądnie jest używać w tym momencie, dopóki nie wyjdzie wersja 4, w której prawdopodobnie nowy sterownik będzie domyślny i nie będziesz już potrzebować tej opcji.

pwilcox
źródło
5

Rozwiązałem to łatwo, uruchamiając te kody:

 npm uninstall mongodb --save

 npm install mongodb@2.2.33 --save

Miłego kodowania!

Saurabh Singh
źródło
4

Mam wersję powłoki MongoDB v3.6.4, poniżej kod użyj mongoclient, to dla mnie dobre:

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()");
 });
Gianluca Mazzeo
źródło
To pytanie dotyczy sterownika węzła, a nie powłoki.
UpTheCreek
3

Jeśli ktoś nadal próbuje rozwiązać ten błąd, zrobiłem to jak poniżej.

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();
        });
    });
  });
});
Mahendra Bagul
źródło
To rozwiązanie i @Dre Jackson są tymi, które działają z node od 07/2020. Wygląda na to, że to, co jest przekazywane jako argument do wywołania zwrotnego connect, to MongoClient, a nie baza danych, dlatego musisz pobrać z niego bazę danych. Poza tym to rozwiązanie zawiera również listę useUnifiedTopology: true, która jest również potrzebna w dzisiejszych czasach.
Coffee_fan
1

Zapytania MongoDB zwracają kursor do tablicy przechowywanej w pamięci. Aby uzyskać dostęp do wyniku tej tablicy, należy wywołać .toArray()na końcu zapytania.

  db.collection("customers").find({}).toArray() 
pmpc2
źródło
1

Kiedyś działał ze starszymi wersjami klienta MongoDb ~ 2.2.33

Opcja 1: Możesz więc użyć starszej wersji

npm uninstall mongodb --save

npm install mongodb@2.2.33 --save

Opcja 2: Nadal używaj nowszej wersji (3.0 i nowszych) i trochę zmodyfikuj kod.

let MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost:27017', function(err, client){
  if(err) throw err;
  let db = client.db('myTestingDb');
  db.collection('customers').find().toArray(function(err, result){
    if(err) throw err;
    console.log(result);
    client.close();
    });
 });
Zardzewiały
źródło