Mongo kabuğunun içinden bir alanın türünü değiştirmeye çalışıyorum.
Bunu yapıyorum ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Ama işe yaramıyor!
Mongo kabuğunun içinden bir alanın türünü değiştirmeye çalışıyorum.
Bunu yapıyorum ...
db.meta.update(
{'fields.properties.default': { $type : 1 }},
{'fields.properties.default': { $type : 2 }}
)
Ama işe yaramıyor!
Yanıtlar:
Verileri değiştirmenin tek yolu $type, verilerin doğru türde olduğu veriler üzerinde bir güncelleme yapmaktır.
Bu durumda, $type 1'i (çift) 2'ye (dize) değiştirmeye çalıştığınız anlaşılıyor .
Bu nedenle belgeyi DB'den yükleyin, cast ( new String(x)) işlemini gerçekleştirin ve ardından belgeyi tekrar kaydedin.
Bunu programlı ve tamamen kabuktan yapmanız gerekiyorsa, find(...).forEach(function(x) {})sözdizimini kullanabilirsiniz .
Aşağıdaki ikinci yoruma yanıt olarak. Alanı badbir sayıdan koleksiyondaki bir dizeye değiştirin foo.
db.foo.find( { 'bad' : { $type : 1 } } ).forEach( function (x) {
x.bad = new String(x.bad); // convert field to string
db.foo.save(x);
});
new String(x.bad)0-index-item x.baddeğerine sahip Dizeler koleksiyonu oluşturur . ""+x.badSimone tarafından açıklanan varyant istendiği gibi çalışır - Int32 yerine String değeri oluşturur
db.questions.find({_id:{$type:16}}).forEach( function (x) { db.questions.remove({_id:x._id},true); x._id = ""+x._id; db.questions.save(x); });
Dize alanını Tamsayıya Dönüştür:
db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
obj.field-name = new NumberInt(obj.field-name);
db.db-name.save(obj);
});
Tamsayı alanını Dizeye Dönüştür:
db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
obj.field-name = "" + obj.field-name;
db.db-name.save(obj);
});
NumberLong:db.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
Dizeden int'ye dönüşüm için.
db.my_collection.find().forEach( function(obj) {
obj.my_value= new NumberInt(obj.my_value);
db.my_collection.save(obj);
});
Dize - çift dönüşüm için.
obj.my_value= parseInt(obj.my_value, 10);
Şamandıra için:
obj.my_value= parseFloat(obj.my_value);
new NumberInt()
Başlangıçta Mongo 4.2, db.collection.update()bir toplama pipeline'ını kabul edebilir ve sonunda bir alanın kendi değerine göre güncellenmesine izin verebilir:
// { a: "45", b: "x" }
// { a: 53, b: "y" }
db.collection.update(
{ a : { $type: 1 } },
[{ $set: { a: { $toString: "$a" } } }],
{ multi: true }
)
// { a: "45", b: "x" }
// { a: "53", b: "y" }
İlk bölüm { a : { $type: 1 } }eşleme sorgusudur:
"a"değeri bir çift olduğunda dizeye dönüştürmek istediğimizden , bu "a", türü 1(double) türündeki öğelerle eşleşir .İkinci bölüm [{ $set: { a: { $toString: "$a" } } }], güncelleme toplama boru hattıdır:
$setMongo 4.2bu durumda bir alanı değiştiren yeni bir toplama operatörüdür ( )."$set"değerine "a"kadar "$a"dönüştürülür "$toString".Mongo 4.2, belgeyi güncellerken kendisine referans verebilmektir : için yeni değer "a", mevcut değerine dayanmaktadır "$a"."$toString", hangi yeni bir toplama operatörü olduğunu tanıttı Mongo 4.0.Unutmayın { multi: true }, aksi takdirde yalnızca eşleşen ilk belge güncellenir.
Durumda Kadronuzun değil çift gelen dizeye, sen tanıtılan farklı dönüşüm operatörleri arasında seçim var Mongo 4.0gibi $toBool, $toInt...
Hedeflediğiniz tür için özel bir dönüştürücü yoksa, { $toString: "$a" }bir $convertişlemle değiştirebilirsiniz : { $convert: { input: "$a", to: 2 } }için değeri tobu tabloda bulunabilir :
db.collection.update(
{ a : { $type: 1 } },
[{ $set: { a: { $convert: { input: "$a", to: 2 } } } }],
{ multi: true }
)
db.collection.updateMany( { a : { $type: 1 } }, [{ $set: { a: { $toString: "$a" } } }] )- multi : truekullanarak kaçınılabilirupdateMany
Şimdiye kadar tüm cevaplar, istemci tarafı tüm koleksiyon öğeleri üzerinde yineleme, forEach bazı sürümünü kullanır.
Ancak, toplam boru hattı ve $ out aşamasını kullanarak MongoDB'nin sunucu tarafı işlemesini şu şekilde kullanabilirsiniz :
$ out aşaması, atomik olarak mevcut koleksiyonu yeni sonuç koleksiyonuyla değiştirir.
misal:
db.documents.aggregate([
{
$project: {
_id: 1,
numberField: { $substr: ['$numberField', 0, -1] },
otherField: 1,
differentField: 1,
anotherfield: 1,
needolistAllFieldsHere: 1
},
},
{
$out: 'documents',
},
]);
Dize türü bir alanı tarih alanına dönüştürmek için, find()yöntemi kullanarak yöntem tarafından döndürülen imleci yinelemeniz gerekir forEach(), döngü içinde alanı bir Date nesnesine dönüştürür ve ardından $setoperatörü kullanarak alanı güncelleştirmeniz gerekir .
Daha iyi performans sunan toplu güncellemeler için Toplu API'yı kullanmanın avantajlarından yararlanın, çünkü işlemleri sunucuya 1000 gibi toplu olarak gönderirsiniz, bu da her isteği sunucuya göndermediğiniz için size daha iyi bir performans sunar 1000 istek.
Aşağıda bu yaklaşım gösterilmektedir, ilk örnek MongoDB sürümlerinde bulunan Toplu API'yı kullanmaktadır >= 2.6 and < 3.2. Tüm created_atalanları tarih alanlarına değiştirerek koleksiyondaki tüm belgeleri günceller :
var bulk = db.collection.initializeUnorderedBulkOp(),
counter = 0;
db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var newDate = new Date(doc.created_at);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "created_at": newDate}
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }
Bir sonraki örnek , Toplu API'yı kullanımdan kaldırmış ve aşağıdakileri kullanarak daha yeni bir apis seti 3.2sağlayan yeni MongoDB sürümü için geçerlidir :bulkWrite()
var bulkOps = [];
db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var newDate = new Date(doc.created_at);
bulkOps.push(
{
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "created_at": newDate } }
}
}
);
})
db.collection.bulkWrite(bulkOps, { "ordered": true });
Bir dizi oluşturmadan int32'yi mongo'da dizeye dönüştürmek için numaranıza "" ekleyin :-)
db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {
x.mynum = x.mynum + ""; // convert int32 to string
db.foo.save(x);
});
MondoDB'deki nesnenin türünü değiştirmeme gerçekten yardımcı olan şey, belki de burada daha önce de belirtildiği gibi basit bir çizgiydi ...:
db.Users.find({age: {$exists: true}}).forEach(function(obj) {
obj.age = new NumberInt(obj.age);
db.Users.save(obj);
});
Kullanıcılar benim koleksiyonumdur ve yaş, tamsayı (int32) yerine dize içeren nesnedir.
Ben koleksiyonda birden çok alanın veri türünü değiştirmek gerekiyor, bu yüzden aşağıdaki belge koleksiyonunda birden çok veri türü değişiklikleri yapmak için kullanılır. Eski bir soruya cevap verin ama başkaları için yararlı olabilir.
db.mycoll.find().forEach(function(obj) {
if (obj.hasOwnProperty('phone')) {
obj.phone = "" + obj.phone; // int or longint to string
}
if (obj.hasOwnProperty('field-name')) {
obj.field-name = new NumberInt(obj.field-name); //string to integer
}
if (obj.hasOwnProperty('cdate')) {
obj.cdate = new ISODate(obj.cdate); //string to Date
}
db.mycoll.save(obj);
});
You can easily convert the string data type to numerical data type.
Don't forget to change collectionName & FieldName.
for ex : CollectionNmae : Users & FieldName : Contactno.
Bu sorguyu deneyin ..
db.collectionName.find().forEach( function (x) {
x.FieldName = parseInt(x.FieldName);
db.collectionName.save(x);
});
demo dizgiden mongo nesnesine orta alan türünü değiştir
Post.find({}, {mid: 1,_id:1}).exec(function (err, doc) {
doc.map((item, key) => {
Post.findByIdAndUpdate({_id:item._id},{$set:{mid: mongoose.Types.ObjectId(item.mid)}}).exec((err,res)=>{
if(err) throw err;
reply(res);
});
});
});
Mongo ObjectId, bu tarzlara sadece bir başka örnektir
Sayı, dize, boole cevabının başka birine yardımcı olacağını umuyoruz.
Ben dönüşümleri kayan dize için mongodb konsolunda bu komut dosyası kullanın ...
db.documents.find({ 'fwtweaeeba' : {$exists : true}}).forEach( function(obj) {
obj.fwtweaeeba = parseFloat( obj.fwtweaeeba );
db.documents.save(obj); } );
db.documents.find({ 'versions.0.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) {
obj.versions[0].content.fwtweaeeba = parseFloat( obj.versions[0].content.fwtweaeeba );
db.documents.save(obj); } );
db.documents.find({ 'versions.1.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) {
obj.versions[1].content.fwtweaeeba = parseFloat( obj.versions[1].content.fwtweaeeba );
db.documents.save(obj); } );
db.documents.find({ 'versions.2.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) {
obj.versions[2].content.fwtweaeeba = parseFloat( obj.versions[2].content.fwtweaeeba );
db.documents.save(obj); } );
Ve php bu))))
foreach($db->documents->find(array("type" => "chair")) as $document){
$db->documents->update(
array('_id' => $document[_id]),
array(
'$set' => array(
'versions.0.content.axdducvoxb' => (float)$document['versions'][0]['content']['axdducvoxb'],
'versions.1.content.axdducvoxb' => (float)$document['versions'][1]['content']['axdducvoxb'],
'versions.2.content.axdducvoxb' => (float)$document['versions'][2]['content']['axdducvoxb'],
'axdducvoxb' => (float)$document['axdducvoxb']
)
),
array('$multi' => true)
);
}
benim durumumda aşağıdakileri kullanıyorum
function updateToSting(){
var collection = "<COLLECTION-NAME>";
db.collection(collection).find().forEach(function(obj) {
db.collection(collection).updateOne({YOUR_CONDITIONAL_FIELD:obj.YOUR_CONDITIONAL_FIELD},{$set:{YOUR_FIELD:""+obj.YOUR_FIELD}});
});
}
toStringbir belge alanına sahip olmak , yaptığım / kullandığım küçük program .