MongoDB veritabanını nasıl yeniden adlandırırsınız?


484

Benim MongoDB veritabanı adı bir yazım hatası var ve ben veritabanını yeniden adlandırmak için arıyorum.

Bu şekilde kopyalayıp silebilirim ...

db.copyDatabase('old_name', 'new_name');
use old_name
db.dropDatabase();

Veritabanını yeniden adlandırmak için bir komut var mı?


dan Mongo'da 4.2 hatta copyDatabaseda olduğu kaldırılmış
Sumit Ramteke

Yanıtlar:


208

Hayır yok. Bkz. Https://jira.mongodb.org/browse/SERVER-701

Ne yazık ki, bu, veritabanı meta verilerinin orijinal (varsayılan) depolama motorunda saklanma şekli nedeniyle uygulamak için basit bir özellik değildir. MMAPv1 dosyalarında, her bir koleksiyonu ve dizini açıklayan ad alanının (örn: dbName.collection) veritabanı adını içerir, bu nedenle bir dizi veritabanı dosyasını yeniden adlandırmak için her ad alanı dizesinin yeniden yazılması gerekir. Bu etkiler:

  • .ns dosyası
  • koleksiyon için her numaralı dosya
  • her dizin için ad alanı
  • her koleksiyonun ve dizinin dahili benzersiz adları
  • system.namespaces ve system.indexes içeriği (veya gelecekteki eşdeğerleri)
  • eksik olabileceğim diğer yerler

Bu, tek başına bir mongod örneğinde tek bir veritabanının yeniden adlandırılmasını sağlamak içindir. Çoğaltma kümeleri için yukarıdakilerin her çoğaltma düğümünde yapılması gerekir, ayrıca her bir düğümde bu veritabanına başvuran her bir oplog girdisinin bir şekilde geçersiz kılınması veya yeniden yazılması gerekir ve daha sonra bir parçalanmış küme varsa, bunların da eklenmesi gerekir. DB parçalanırsa her kırıkta değişir, ayrıca yapılandırma sunucuları tam adlarıyla ad alanları bakımından tüm parça meta verilerine sahiptir.

Bunu canlı bir sistemde yapmanın kesinlikle bir yolu yoktur.

Çevrimdışı yapmak için, her yeni veritabanı dosyasının yeni adı alacak şekilde yeniden yazılması gerekir ve bu noktada geçerli "copydb" komutu kadar yavaş olur ...


4
Bu bilet çok uzun zamandır açık. Zaten önemsiz olan oyumu zaten uzun listeye ekledim.
DJ van Wyk

4
DB'yi inşa etme ve açıklama şekli, yeniden adlandırma imkansız görünüyor - yepyeni bir mimari gerektirebilir. Büyük bir gözetim gibi görünüyor ama hepsi sevgi, savaş ve yazılım geliştirmede adil.
serraosays

Peki MongoDB'de iki işlevi çağıran bir komut olmalı, kopyalama ve bırakma? Bu tek emir için büyük bir neden göremiyorum. Ama bazıları için iyi olabilir.
TamusJRoyce

Başlamak için veritabanını adlandırdığınızda, bu yalnızca Mongo'nun oluşturduğu bir iç ad için bir takma ad olmalıdır (genel olarak benzersiz bir adlandırma kuralı kullanarak). Bu şekilde, bir veritabanının adını değiştirmek, diğer adı değiştirmek ve kümedeki tüm düğümlere yaymak kadar basittir. Ben söylemeliyim. Olay bu değil.
Lonnie En İyi

396

Bunu yapabilirsin:

db.copyDatabase("db_to_rename","db_renamed","localhost")
use db_to_rename
db.dropDatabase();

Editoryal Not: Bu, sorunun kendisinde kullanılan aynı yaklaşımdır, ancak ne olursa olsun başkaları için yararlı olduğu kanıtlanmıştır.


38
Üçüncü argüman aslında atlanabilir ve varsayılan olarak aynı sunucuya ayarlanır.
Haakon

15
Db_to_rename ve db_renamed durumları birbirinden farklı olduğunda bunun çalışmadığını unutmayın. Bu durumda geçici bir veritabanı kullanmanız gerekir. (Ben sadece bu koştu :)
Sebastiaan M

71
OP'nin sağladığı çözümden farkı nedir?
Salvador Dali

5
bu gerçek Soru ile aynıdır, tek fark copyDatabaseyöntemdeki üçüncü argümandır
Gurbakhshish Singh

2
bu asıl soru ile aynıdır, tek fark copyDatabaseyöntemdeki üçüncü argümandır *, gereksizdir ve bu nedenle OP'nin zaten farkında olduğu daha kötü bir çözümdür. * cc @GurbakhshishSingh
Trindaz

164

Alternatif çözüm: db'nizi dökebilir ve farklı adla geri yükleyebilirsiniz. Deneyimlediğim gibi, çok daha hızlı db.copyDatabase().

$ mongodump -d old_db_name -o mongodump/
$ mongorestore -d new_db_name mongodump/old_db_name

http://docs.mongodb.org/manual/tutorial/backup-with-mongodump/


6
Bu daha hızlıdır ve "yan etki" olarak veritabanınız da sıkıştırılmıştır.
Comtaler

Bu harika! Zaten bir mongodumpyaratım vardı . Farklı bir adla geri yükleyebileceğinizi bilmiyordum. Teşekkürler!
Dushyant Bangal

5
NOT: --gzipBir arşiv kullanır ve oluşturursanız bu çalışmaz
Dushyant Bangal

9
Çünkü bu, artık tavsiye yoludur db.copyDatabase()artık önerilmemektedir
osolmaz

Hayır olduğuna dikkat ederek, --db( -d) argümanının kendisi de kullanımdan kaldırılmıştır. Görünüşe göre, verilen copyDatabasebir de yoksun bırakma partisi oldu . Notlarımla SERVER- 701'i dürttüm .
amcgregor

28

NOT: Umarım bu son sürümde değişmiştir.

MongoDB 4.0 mongod örneği (FCV değerine bakılmaksızın) ile MongoDB 3.4 ve önceki mongod örneği arasında veri kopyalayamazsınız. https://docs.mongodb.com/v4.0/reference/method/db.copyDatabase/

UYARI : Hey millet sadece farklı koleksiyonları tek bir veritabanı altında karıştırmak istemiyorsanız, veritabanını kopyalarken dikkatli olun.

Aşağıda yeniden adlandırma

> show dbs;
testing
games
movies

Yeniden adlandırmak için aşağıdaki sözdizimini kullanın

db.copyDatabase("old db name","new db name")

Misal:

db.copyDatabase('testing','newTesting')

Artık eski db'yi güvenle şu şekilde silebilirsiniz

use testing;

db.dropDatabase(); //Here the db **testing** is deleted successfully

Şimdi yeni veritabanı adını mevcut veritabanı adıyla yeniden adlandırmayı denerseniz ne olacağını düşünün

Misal:

db.copyDatabase('testing','movies'); 

Bu bağlamda, testin tüm koleksiyonları (tabloları) film veritabanına kopyalanacaktır .



@amcgregor bildirdiğiniz için teşekkürler. Aynı şey için bir yorum ekledim. Umarım bazılarına yardımcı olur.
Channaveer Hakari

8

Mongodb Veritabanını Yeniden Adlandır komutunu sağlamasa da , yalnızca koleksiyon adını değiştirmekle kalmayan, aynı zamanda veritabanı adını da değiştiren r ename Koleksiyonu komutunu sağlar .

db.adminCommand({renameCollection: "db1.test1", to: "db2.test2"})

Bu komut yalnızca meta verileri değiştirir, maliyeti çok düşüktür, yalnızca Veritabanı altındaki db1yeniden adlandırmayı sağlamak db2için yeniden adlandırılan altındaki tüm koleksiyonları geçmemiz gerekir .
bunu bu Js betiğinde yapabilirsiniz

var source = "source";
var dest = "dest";
var colls = db.getSiblingDB(source).getCollectionNames();
for (var i = 0; i < colls.length; i++) {
var from = source + "." + colls[i];
var to = dest + "." + colls[i];
db.adminCommand({renameCollection: from, to: to});
}

Dizinler ve diğer meta veriler korunur veya kaybedilir?
Udit Bhardwaj

@UDB Büyük olasılıkla korunmuş. "Koleksiyon yeniden adlandırma bir üründür" ad dönüşüm esasen adlı koleksiyonunuzu, fooiçinde barveritabanının bir ad alanı vardır bar.foo. Böylece indeks _idad alanına sahiptir bar.foo._id_. Koleksiyonu yeniden adlandırmak (ve) önek araması yapmalı ve bildiği tüm ad alanlarında, --nsFromve --nsTo seçeneklerinemongorestore benzer şekilde değiştirmelidir .
amcgregor

1
Maliyet BÜYÜK olabilir! docs.mongodb.com/manual/reference/command/renameCollection/… Hedef veritabanı kaynak veritabanı ile aynıysa, renameCollection yalnızca ad alanını değiştirir. Bu hızlı bir işlemdir. Hedef veritabanı kaynak veritabanından farklıysa, renameCollection tüm belgeleri kaynak koleksiyonundan hedef koleksiyonuna kopyalar. Koleksiyonun boyutuna bağlı olarak, bu işlemin tamamlanması daha uzun sürebilir.
nagylzs

Lütfen cevabınızı değiştirin. Cevabınız faydalıdır, çünkü bu komutu kullanarak bir koleksiyonu başka bir veritabanına taşımak mümkündür. Ancak bu yanlıştır ve başkalarını yanlış yönlendirebilir.
nagylzs

6

Yukarıdaki işlem yavaştır, aşağıdaki yöntemi kullanabilirsiniz, ancak koleksiyonu koleksiyona göre başka bir db'ye taşımanız gerekir.

use admin
db.runCommand({renameCollection: "[db_old_name].[collection_name]", to: "[db_new_name].[collection_name]"})

Mükemmel öneri IMHO. Ancak, bunun orijinal DB'deki alanı boşaltmayacağını, ancak yeniden adlandırma verilerinin kopyalanmasından çok daha hızlı olması gerektiğini belirtmek gerekir.
sirfz

1
Scratch, yine de bir kopya yapar (alanı kaldırmaz, gerçekten basit bir yeniden adlandırma değildir), bu nedenle bu yöntemin kopyalama ve bırakma üzerinde gerçek bir avantajı yoktur.
sirfz

5

Veritabanlarını yeniden adlandıracak bir mekanizma yoktur. Yazı sırasında şu anda kabul cevap olgusal doğru olduğunu ve bahane yukan olarak teklifler bazı ilginç arka plan detay ama davranışı çoğaltmak için teklifler hiçbir öneri. Diğer yanıtlar , işlevsellik 4.0'da kaldırıldığı içincopyDatabase artık bir seçenek değil . Ben güncelledik notlarımı SUNUCU-701 ve kuşkuyla. 🙃

Eşdeğer davranış, bir dansı içerir mongodumpve mongorestorebiraz dansı içerir:

  1. Kullanımdaki "ad alanlarını" not ederek verilerinizi dışa aktarın. Örneğin, veri kümelerimden birinde, ad alanı olan bir koleksiyonum var - bir sonraki adımda byzmcbehoomrfjcs9vlj.Analyticsbu önek ( aslında veritabanı adı ) gerekli olacak.

  2. Verilerinizi, tedarikinizi --nsFromve --nsTobağımsız değişkenlerinizi içe aktarın . ( Belgeleme. ) Yukarıdaki varsayımsal (ve son derece okunamayan) örneğimle devam ederek, daha duygusal bir isme geri dönmek için:

mongorestore --archive=backup.agz --gzip --drop \
    --nsFrom 'byzmcbehoomrfjcs9vlj.*' --nsTo 'rita.*'

Bazıları da --dbmongorestore argümanına işaret edebilir, ancak bu da kullanımdan kaldırılmıştır ve tamamen hatalı bir öneri " use --nsInclude instead" olan BSON olmayan klasör yedeklemelerinde kullanıma karşı bir uyarı tetikler . Yukarıdaki ad alanı çevirisi, --dbseçeneğin kullanımına eşdeğerdir ve geri yüklenenleri filtrelemeye çalışmadığımızdan kullanılacak doğru ad alanı düzenleme kurulumudur.


1
--nsFromve --nsTobenim için çalıştı. Teşekkür ederim!
Bhargav Shah

nsFrom / To ile mongodump 2020 itibariyle resmi cevaptır
PaoloC

4

Yapmaya çalıştım.

db.copyDatabase('DB_toBeRenamed','Db_newName','host') 

ve yedek oluşturmuş veya DB adını değiştirmiş olmasına rağmen mongo topluluğu tarafından kullanımdan kaldırılmış olduğunu öğrendi.

WARNING: db.copyDatabase is deprecated. See http://dochub.mongodb.org/core/copydb-clone-deprecation
{
        "note" : "Support for the copydb command has been deprecated. See 
        http://dochub.mongodb.org/core/copydb-clone-deprecation",
        "ok" : 1
}

Bu yüzden yukarıdaki yaklaşımla ikna olmadım, aşağıdaki komutu kullanarak yerel dökümü almak zorunda kaldım

mongodump --host --db DB_TobeRenamed --out E://FileName/

Db'ye bağlı.

use DB_TobeRenamed

sonra

db.dropDatabase()

daha sonra DB komutuyla geri yüklendi.

mongorestore -host hostName -d Db_NewName E://FileName/

2

Tüm verilerinizi yönetici veritabanına koyduğunuzda (yapmamalısınız), db.copyDatabase()kullanıcınızın muhtemelen vermek istemeyeceğiniz çok fazla ayrıcalık gerektirdiğinden işe yaramayacağını fark edeceksiniz . İşte veritabanını manuel olarak kopyalamak için bir komut dosyası:

use old_db
db.getCollectionNames().forEach(function(collName) {
    db[collName].find().forEach(function(d){
        db.getSiblingDB('new_db')[collName].insert(d); 
    }) 
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.