Przygotowuję skrypt do tworzenia bazy danych w Node.js i Mongoose. Jak mogę sprawdzić, czy baza danych już istnieje, a jeśli tak, upuść (usuń) ją za pomocą Mongoose?
Nie mogłem znaleźć sposobu, żeby upuścić to z Mongoose.
kiedy próbuję skorzystać z drugiej opcji, otrzymuję komunikat „nie można odczytać właściwości 'nazwa_kolekcji' niezdefiniowanej”
Yaron Naveh
1
Ponieważ wszystkie kolekcje znajdują się w hash mongoose.connection.collections, możesz po prostu wymienić je dla (collection in mongoose.connection.collections) {mongoose.connection.collections [kolekcja] .drop} ...
smth
3
Masz literówkę - dodatkowy przecinek po funkcji (błąd) ... powinien wyglądać następująco: mongoose.connection.collections ['nazwa_kolekcji']. Drop (funkcja (błąd) {console.log ('kolekcja porzucona') ;});
arxpoetica
3
Czy tylko ja zdałem sobie sprawę, że ta odpowiedź nie dotyczy kwestii usuwania bazy danych. To nie jest prośba o upuszczenie kolekcji, ale prośba o usunięcie bazy danych ...
Joseph Persie
3
„Nie ma metody na usunięcie kolekcji z mangusty”, po pierwsze OP chce usunąć bazę danych, a nie zestawienie, po drugie, odpowiedź @hellslam poniżej działa dobrze.
SCBuergel.eth
79
Mongoose utworzy bazę danych, jeśli jeszcze nie istnieje w połączeniu, więc po nawiązaniu połączenia możesz po prostu zapytać ją, czy coś w niej jest.
Możesz usunąć dowolną bazę danych, z którą jesteś połączony:
var mongoose = require('mongoose');/* Connect to the DB */
mongoose.connect('mongodb://localhost/mydatabase',function(){/* Drop the DB */
mongoose.connection.db.dropDatabase();});
Próbowałem, mongoose.connection.db.dropDatabase()ale okazało się, że db nadal tam jest? Czy coś mi brakuje?
Freewind
Jeśli później połączysz się z nim, zostanie odtworzony, choć pusty. Czy były w nim jakieś kolekcje po tym, jak go upuściłeś?
hellslam
Czy używasz tego samego połączenia przez cały czas, czy tworzysz wiele połączeń?
hellslam
12
Odkryłem, że dropDatabasewywołanie powinno być umieszczone w wywołaniu zwrotnym connect, as mongoose.connect('...', function() { ...dropDatabase()}).
Freewind
1
dropDatabase wydaje się nie działać w niektórych przypadkach, ale bezpośrednie polecenie mongo nadal może być używane mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
farincz
14
Jeśli zmodyfikujesz rozwiązanie @ hellslam w ten sposób, zadziała
Używam tej techniki do usuwania bazy danych po moich testach integracji
czy można upuścić db z tym? db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
chovy
2
To było pomocne, dzięki! Jednak nazwy zmiennych są trochę mylące ... w mongoose.connectrzeczywistości zwracają mongoose. Zamiast conn = mongoose.connect(...)pisać mongoose.connect(...)i wtedy conn = mongooose.connection.
płatny kujon
Nie sądzę, aby ten kod zawsze działał, ponieważ connectjest asynchroniczny. Jeśli więc połączenie nie nastąpi natychmiast, polecenie dropDatabase () nie powiedzie się. Dlatego też inne powyższe rozwiązania zalecały umieszczenie dropDatabasepolecenia w wywołaniu zwrotnym connectinstrukcji lub openmodule obsługi zdarzenia.
Mark Stosberg,
8
Wypróbowałem odpowiedzi @ hellslam i @ silverfighter. Stwierdziłem, że stan wyścigu wstrzymuje moje testy. W moim przypadku przeprowadzam testy mokki, aw funkcji przed testem chcę usunąć całą bazę danych. Oto, co działa w moim przypadku.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open',function(){
con.connection.db.dropDatabase(function(err, result){
done();});});
Przetestowałem ten kod we własnym kodzie, używając mongoose 4.13.6. Zwróć także uwagę na użycie tej useMongoClientopcji ( patrz dokumentacja ). Dokumenty wskazują:
Domyślna logika połączenia Mongoose jest przestarzała od wersji 4.11.0. Wybierz nową logikę połączeń, korzystając z opcji useMongoClient, ale pamiętaj, aby najpierw przetestować połączenia, jeśli aktualizujesz istniejącą bazę kodu!
Problem z innymi rozwiązaniami polega na tym, że polegają one na ponownym uruchomieniu aplikacji, jeśli chcesz, aby indeksy znów działały.
Na moje potrzeby (tj. Możliwość przeprowadzenia testu jednostkowego nuków wszystkich kolekcji, a następnie odtworzenia ich wraz z ich indeksami), w końcu zaimplementowałem to rozwiązanie:
Opiera się to na bibliotekach underscore.js i async.js w celu zebrania indeksów w parellel. Jeśli jesteś przeciwko tej bibliotece, może to zostać cofnięte , ale zostawiam to jako ćwiczenie dla programisty.
mongoose.connection.db.executeDbCommand({dropDatabase:1},function(err, result){var mongoPath = mongoose.connections[0].host +':'+ mongoose.connections[0].port +'/'+ mongoose.connections[0].name
//Kill the current connection, then re-establish it
mongoose.connection.close()
mongoose.connect('mongodb://'+ mongoPath,function(err){var asyncFunctions =[]//Loop through all the known schemas, and execute an ensureIndex to make sure we're clean
_.each(mongoose.connections[0].base.modelSchemas,function(schema, key){
asyncFunctions.push(function(cb){
mongoose.model(key, schema).ensureIndexes(function(){return cb()})})})async.parallel(asyncFunctions,function(err){
console.log('Done dumping all collections and recreating indexes')})})})
Najlepszy sposób na upuszczenie bazy danych w Mongoose zależy od używanej wersji Mongoose. Jeśli używasz wersji Mongoose w wersji 4.6.4 lub nowszej, ta metoda dodana w tej wersji prawdopodobnie będzie działać dobrze:
mongoose.connection.dropDatabase();
W starszych wersjach ta metoda nie istniała. Zamiast tego miałeś użyć bezpośredniego połączenia z MongoDB:
mongoose.connection.db.dropDatabase();
Jeśli jednak zostanie to uruchomione zaraz po utworzeniu połączenia z bazą danych, prawdopodobnie po cichu zakończy się niepowodzeniem. Jest to związane z faktem, że połączenie jest w rzeczywistości asynchroniczne i nie jest jeszcze konfigurowane w momencie wykonania polecenia. Zwykle nie stanowi to problemu w przypadku innych wywołań Mongoose, takich jak .find()kolejka do momentu otwarcia połączenia, a następnie uruchomienia.
Jeśli spojrzysz na kod źródłowy dropDatabase()dodanego skrótu, zobaczysz, że został on zaprojektowany, aby rozwiązać dokładnie ten problem. Sprawdza, czy połączenie jest otwarte i gotowe. Jeśli tak, natychmiast uruchamia polecenie. Jeśli nie, rejestruje polecenie do uruchomienia po otwarciu połączenia z bazą danych.
Niektóre z powyższych sugestii zalecają zawsze umieszczanie dropDatabasepolecenia w programie openobsługi. Ale to działa tylko w przypadku, gdy połączenie nie jest jeszcze otwarte.
Oto prosta wersja powyższej logiki, której można używać we wcześniejszych wersjach Mongoose:
// This shim is backported from Mongoose 4.6.4 to reliably drop a database// http://stackoverflow.com/a/42860208/254318// The first arg should be "mongoose.connection"function dropDatabase (connection, callback){// readyState 1 === 'connected'if(connection.readyState !==1){
connection.on('open',function(){
connection.db.dropDatabase(callback);});}else{
connection.db.dropDatabase(callback);}}
beforeEach((done)=>{
mongoose.connection.dropCollection('products',(error ,result)=>{if(error){
console.log('Products Collection is not dropped')}else{
console.log(result)}
done()})})
Odpowiedzi:
Nie ma metody na usunięcie kolekcji z mangusty, najlepsze, co możesz zrobić, to usunąć zawartość jednej z nich:
Istnieje jednak sposób na uzyskanie dostępu do natywnego sterownika mongodb javascript, którego można użyć do tego
Ostrzeżenie
Zanim spróbujesz, wykonaj kopię zapasową na wypadek, gdyby coś poszło nie tak!
źródło
Mongoose utworzy bazę danych, jeśli jeszcze nie istnieje w połączeniu, więc po nawiązaniu połączenia możesz po prostu zapytać ją, czy coś w niej jest.
Możesz usunąć dowolną bazę danych, z którą jesteś połączony:
źródło
mongoose.connection.db.dropDatabase()
ale okazało się, że db nadal tam jest? Czy coś mi brakuje?dropDatabase
wywołanie powinno być umieszczone w wywołaniu zwrotnymconnect
, asmongoose.connect('...', function() { ...dropDatabase()})
.mongoose.connection.db.executeDbCommand( {dropDatabase:1}, function(err, result) { if (err) { console.log(err); } done(); });
Jeśli zmodyfikujesz rozwiązanie @ hellslam w ten sposób, zadziała
Używam tej techniki do usuwania bazy danych po moich testach integracji
HTH przynajmniej zrobiło to dla mnie, więc zdecydowałem się udostępnić =)
źródło
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
rzeczywistości zwracająmongoose
. Zamiastconn = mongoose.connect(...)
pisaćmongoose.connect(...)
i wtedyconn = mongooose.connection
.connect
jest asynchroniczny. Jeśli więc połączenie nie nastąpi natychmiast, polecenie dropDatabase () nie powiedzie się. Dlatego też inne powyższe rozwiązania zalecały umieszczeniedropDatabase
polecenia w wywołaniu zwrotnymconnect
instrukcji lubopen
module obsługi zdarzenia.Wypróbowałem odpowiedzi @ hellslam i @ silverfighter. Stwierdziłem, że stan wyścigu wstrzymuje moje testy. W moim przypadku przeprowadzam testy mokki, aw funkcji przed testem chcę usunąć całą bazę danych. Oto, co działa w moim przypadku.
Możesz przeczytać więcej https://github.com/Automattic/mongoose/issues/1469
źródło
Zaktualizowana odpowiedź dla 4.6.0+, jeśli wolisz obietnice ( zobacz dokumentację ):
Przetestowałem ten kod we własnym kodzie, używając mongoose 4.13.6. Zwróć także uwagę na użycie tej
useMongoClient
opcji ( patrz dokumentacja ). Dokumenty wskazują:źródło
Problem z innymi rozwiązaniami polega na tym, że polegają one na ponownym uruchomieniu aplikacji, jeśli chcesz, aby indeksy znów działały.
Na moje potrzeby (tj. Możliwość przeprowadzenia testu jednostkowego nuków wszystkich kolekcji, a następnie odtworzenia ich wraz z ich indeksami), w końcu zaimplementowałem to rozwiązanie:
Opiera się to na bibliotekach underscore.js i async.js w celu zebrania indeksów w parellel. Jeśli jesteś przeciwko tej bibliotece, może to zostać cofnięte , ale zostawiam to jako ćwiczenie dla programisty.
źródło
Aby opróżnić określoną kolekcję w bazie danych:
Uwaga:
źródło
To działa dla mnie od Mongoose
v4.7.0
:źródło
Najlepszy sposób na upuszczenie bazy danych w Mongoose zależy od używanej wersji Mongoose. Jeśli używasz wersji Mongoose w wersji 4.6.4 lub nowszej, ta metoda dodana w tej wersji prawdopodobnie będzie działać dobrze:
W starszych wersjach ta metoda nie istniała. Zamiast tego miałeś użyć bezpośredniego połączenia z MongoDB:
Jeśli jednak zostanie to uruchomione zaraz po utworzeniu połączenia z bazą danych, prawdopodobnie po cichu zakończy się niepowodzeniem. Jest to związane z faktem, że połączenie jest w rzeczywistości asynchroniczne i nie jest jeszcze konfigurowane w momencie wykonania polecenia. Zwykle nie stanowi to problemu w przypadku innych wywołań Mongoose, takich jak
.find()
kolejka do momentu otwarcia połączenia, a następnie uruchomienia.Jeśli spojrzysz na kod źródłowy
dropDatabase()
dodanego skrótu, zobaczysz, że został on zaprojektowany, aby rozwiązać dokładnie ten problem. Sprawdza, czy połączenie jest otwarte i gotowe. Jeśli tak, natychmiast uruchamia polecenie. Jeśli nie, rejestruje polecenie do uruchomienia po otwarciu połączenia z bazą danych.Niektóre z powyższych sugestii zalecają zawsze umieszczanie
dropDatabase
polecenia w programieopen
obsługi. Ale to działa tylko w przypadku, gdy połączenie nie jest jeszcze otwarte.Oto prosta wersja powyższej logiki, której można używać we wcześniejszych wersjach Mongoose:
źródło
Mongoose 4.6.0+:
Przekazywanie oddzwonienia do połączenia nie będzie już działać:
TypeError: nie można odczytać właściwości „commandsTakeWriteConcern” o wartości null
źródło
connect
zwraca obietnicę, więc możesz dodać.then((connection) => { ... });
ją domongoose.connect
. Zobacz: mongoosejs.com/docs/connections.htmlźródło
Ponieważ metoda remove jest zdeprecjonowana w bibliotece mongoose, możemy użyć funkcji deleteMany bez przekazanych parametrów.
Spowoduje to usunięcie całej zawartości tego konkretnego Modelu, a Twoja kolekcja będzie pusta.
źródło
Aby upuścić wszystkie dokumenty w kolekcji:
Ta odpowiedź jest oparta na pliku mongoose index.d.ts:
źródło
Aby usunąć wszystkie dokumenty w kolekcji:
jak widać w testach
źródło