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.
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.
Odpowiedzi:
Nie ma metody na usunięcie kolekcji z mangusty, najlepsze, co możesz zrobić, to usunąć zawartość jednej z nich:
Model.remove({}, function(err) {
console.log('collection removed')
});
Istnieje jednak sposób na uzyskanie dostępu do natywnego sterownika mongodb javascript, którego można użyć do tego
mongoose.connection.collections['collectionName'].drop( function(err) {
console.log('collection dropped');
});
Zanim spróbujesz, wykonaj kopię zapasową na wypadek, gdyby coś poszło nie tak!
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();
});
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 zwrotnym connect
, as mongoose.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
//CoffeeScript
mongoose = require "mongoose"
conn = mongoose.connect("mongodb://localhost/mydb")
conn.connection.db.dropDatabase()
//JavaScript
var conn, mongoose;
mongoose = require("mongoose");
conn = mongoose.connect("mongodb://localhost/mydb");
conn.connection.db.dropDatabase();
HTH przynajmniej zrobiło to dla mnie, więc zdecydowałem się udostępnić =)
db = mongoose.createConnection(cfg.mongo.uri, cfg.mongo.db);
mongoose.connect
rzeczywistości zwracają mongoose
. Zamiast conn = mongoose.connect(...)
pisać mongoose.connect(...)
i wtedy conn = 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 umieszczenie dropDatabase
polecenia w wywołaniu zwrotnym connect
instrukcji lub open
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.
var con = mongoose.connect('mongodb://localhost/mydatabase');
mongoose.connection.on('open', function(){
con.connection.db.dropDatabase(function(err, result){
done();
});
});
Możesz przeczytać więcej https://github.com/Automattic/mongoose/issues/1469
Zaktualizowana odpowiedź dla 4.6.0+, jeśli wolisz obietnice ( zobacz dokumentację ):
mongoose.connect('mongodb://localhost/mydb', { useMongoClient: true })
.then((connection) => {
connection.db.dropDatabase();
// alternatively:
// mongoose.connection.db.dropDatabase();
});
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ą:
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')
})
})
})
Aby opróżnić określoną kolekcję w bazie danych:
model.remove(function(err, p){
if(err){
throw err;
} else{
console.log('No Of Documents deleted:' + p);
}
});
Uwaga:
To działa dla mnie od Mongoose v4.7.0
:
mongoose.connection.dropDatabase();
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 dropDatabase
polecenia w programie open
obsługi. Ale to działa tylko w przypadku, gdy połączenie nie jest jeszcze otwarte.
Connection.prototype.dropDatabase = function(callback) {
var Promise = PromiseProvider.get();
var _this = this;
var promise = new Promise.ES6(function(resolve, reject) {
if (_this.readyState !== STATES.connected) {
_this.on('open', function() {
_this.db.dropDatabase(function(error) {
if (error) {
reject(error);
} else {
resolve();
}
});
});
} else {
_this.db.dropDatabase(function(error) {
if (error) {
reject(error);
} else {
resolve();
}
});
}
});
if (callback) {
promise.then(function() { callback(); }, callback);
}
return promise;
};
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);
}
}
Mongoose 4.6.0+:
mongoose.connect('mongodb://localhost/mydb')
mongoose.connection.once('connected', () => {
mongoose.connection.db.dropDatabase();
});
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
connect
zwraca obietnicę, więc możesz dodać .then((connection) => { ... });
ją do mongoose.connect
. Zobacz: mongoosejs.com/docs/connections.html
Ponieważ metoda remove jest zdeprecjonowana w bibliotece mongoose, możemy użyć funkcji deleteMany bez przekazanych parametrów.
Model.deleteMany();
Spowoduje to usunięcie całej zawartości tego konkretnego Modelu, a Twoja kolekcja będzie pusta.