Die einzige Möglichkeit, $typedie Daten zu ändern, besteht darin, eine Aktualisierung der Daten durchzuführen, bei denen die Daten den richtigen Typ haben.
Gibt es eine Chance für ein Beispiel - das Ändern eines Feldtyps von int in string (oder umgekehrt) aus der Shell?
Alister Bulman
30
Im Fall Int32-> String wird new String(x.bad)eine Sammlung von Strings mit dem x.badWert 0-index-item erstellt . Die ""+x.badvon Simone beschriebene Variante funktioniert wie gewünscht - erstellt einen String-Wert anstelle von Int32
Dao
Der obige Code konvertiert die Felddaten von double in array anstelle von double in string. Meine tatsächlichen Daten waren in diesem Format: 3.1, während Simone-Code für mich gut funktioniert
Pankaj Khurana
2
Hatte eine Situation, in der ich das _id-Feld konvertieren musste und nicht mit anderen Indizes in Konflikt stand:db.questions.find({_id:{$type:16}}).forEach( function (x) { db.questions.remove({_id:x._id},true); x._id = ""+x._id; db.questions.save(x); });
Matt Molnar
@ SundarBons Ja, Sie schreiben ein Feld in Ihrer Datenbank neu. Dies ist eine große Sache, egal wie Sie es tun. Wenn Sie SQL verwenden und dies eine große Tabelle ist, müssten Sie wahrscheinlich einige Ausfallzeiten in Anspruch nehmen.
Das ist großartig - wissen Sie, wie Sie eine Zeichenfolge (denken Sie an eine Währung wie '1.23') in die Ganzzahl 123 konvertieren würden? Ich gehe davon aus, dass Sie es als Gleitkomma- oder Dezimalzahl analysieren, mit 100 multiplizieren und dann als Ganzzahl speichern müssen, aber ich kann nicht die richtigen Dokumente finden, um dies zu tun. Vielen Dank!
Brian Armstrong
Eigentlich ist das gut. Aber ich habe eine Anwendung, die mit Mongoid 2.4.0-Stable ausgeführt wird und Felder wie Feld: customer_count, Typ: Integer und eine Validierung als validates_numericality_of: customer_count enthält, die einwandfrei funktioniert hat. Wenn ich jetzt ein Upgrade auf Mongoid auf 3.0.16 durchführe und einen Zeichenfolgenwert zuweise, wird dieser automatisch ohne Fehler in 0 konvertiert. Ich möchte einen Fehler bei falscher Datenzuweisung auslösen. Dieses Verhalten ist für mich seltsam.
Swapnil Chincholkar
4
Ich habe dies ausgeführt und den Fehler erhalten: Fehler: String konnte nicht in Integer (Shell) konvertiert werden: 1
Mittenchops
Und wenn Sie Zeichenfolge (oder "normale" 32-Bit-Ganzzahl) in 64-Bit-Ganzzahl konvertieren müssen, verwenden Sie NumberLongwie db.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
folgt
es funktioniert gut. Darf ich wissen, wie man den Datentyp in eingebetteten Dokumentfeldern
Starten Mongo 4.2, db.collection.update()kann eine Aggregation Pipeline akzeptieren, schließlich die Aktualisierung eines Feldes ermöglicht , basierend auf seinen eigenen Wert:
Der erste Teil { a : { $type: 1 } }ist die Übereinstimmungsabfrage:
Es filtert, welche Dokumente aktualisiert werden sollen.
In diesem Fall entspricht "a"dies Elementen, für die "a"der Typ 1(double) ist , da wir in einen String konvertieren möchten, wenn sein Wert ein Double ist .
Diese Tabelle enthält die Codes, die die verschiedenen möglichen Typen darstellen.
Der zweite Teil [{ $set: { a: { $toString: "$a" } } }]ist die Update-Aggregations-Pipeline:
Beachten Sie die eckigen Klammern, die angeben, dass diese Aktualisierungsabfrage eine Aggregationspipeline verwendet.
$setist ein neuer Aggregationsoperator ( Mongo 4.2), der in diesem Fall ein Feld ändert.
Dies kann einfach gelesen werden als "$set"der Wert der "a"zu "$a"umgewandelt "$toString".
Was hier wirklich neu ist, ist die Möglichkeit Mongo 4.2, beim Aktualisieren auf das Dokument selbst zu verweisen: Der neue Wert für "a"basiert auf dem vorhandenen Wert von "$a".
Beachten Sie auch, "$toString"welcher neue Aggregationsoperator in eingeführt wurde Mongo 4.0.
Vergessen Sie nicht { multi: true }, sonst wird nur das erste übereinstimmende Dokument aktualisiert.
Falls Ihr Guss nicht doppelt zu bespannen, haben Sie die Wahl zwischen verschiedenen Konvertierungsoperator in eingeführt Mongo 4.0, wie $toBool, $toInt...
Und wenn es für Ihren Zieltyp keinen dedizierten Konverter gibt, können Sie ihn durch { $toString: "$a" }eine $convertOperation ersetzen : { $convert: { input: "$a", to: 2 } }Der Wert für tobefindet sich in dieser Tabelle :
db.collection.update({ a :{ $type:1}},[{ $set:{ a:{ $convert:{ input:"$a", to:2}}}}],{ multi:true})
Ich weiß nicht, warum dies nicht mehr positiv bewertet wird. Zeile für Zeile Operationen an großen Datenmengen sind Mord an der Leistung
Alf47
7
Um ein Feld vom Typ Zeichenfolge in ein Datumsfeld zu konvertieren, müssen Sie den von der find()Methode zurückgegebenen Cursor mithilfe von iterierenforEach() Methode zurückgegebenen , das Feld innerhalb der Schleife in ein Datumsobjekt konvertieren und das Feld dann mit dem $setOperator aktualisieren .
Nutzen Sie die Bulk-API für Bulk-Updates, die eine bessere Leistung bieten, da Sie die Vorgänge in Stapeln von beispielsweise 1000 an den Server senden. Dies führt zu einer besseren Leistung, da Sie nicht jede Anforderung nur einmal an den Server senden 1000 Anfragen.
Im Folgenden wird dieser Ansatz veranschaulicht. Im ersten Beispiel wird die in MongoDB-Versionen verfügbare Bulk-API verwendet >= 2.6 and < 3.2 . . Es aktualisiert alle Dokumente in der Sammlung, indem alle created_atFelder in Datumsfelder geändert werden:
var bulk = db.collection.initializeUnorderedBulkOp(),
counter =0;
db.collection.find({"created_at":{"$exists":true,"$type":2}}).forEach(function(doc){var newDate =newDate(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 queueif(counter %1000!=0){ bulk.execute();}
Das nächste Beispiel gilt für die neue MongoDB-Version, 3.2die seitdem die Bulk-API veraltet und einen neueren Satz von APIs bereitgestellt hat, indem sie bulkWrite():
Ich muss den Datentyp mehrerer Felder in der Sammlung ändern, daher habe ich Folgendes verwendet, um mehrere Datentypänderungen in der Sammlung von Dokumenten vorzunehmen. Beantworten Sie eine alte Frage, aber sie kann für andere hilfreich sein.
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 =newNumberInt(obj.field-name);//string to integer}if(obj.hasOwnProperty('cdate')){
obj.cdate =newISODate(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.
toString
das Feld eines Dokuments benötigt, ist hier das kleine Programm, das ich erstellt / verwendet habe .Antworten:
Die einzige Möglichkeit,
$type
die Daten zu ändern, besteht darin, eine Aktualisierung der Daten durchzuführen, bei denen die Daten den richtigen Typ haben.In diesem Fall scheinen Sie zu versuchen, die Zahl
$type
von 1 (doppelt) in 2 (Zeichenfolge) zu ändern .Laden Sie also einfach das Dokument aus der Datenbank, führen Sie cast (
new String(x)
) aus und speichern Sie das Dokument erneut.Wenn Sie dies programmgesteuert und vollständig über die Shell ausführen müssen, können Sie die
find(...).forEach(function(x) {})
Syntax verwenden.Als Antwort auf den zweiten Kommentar unten. Ändern Sie das Feld
bad
von einer Zahl in eine Zeichenfolge in der Sammlungfoo
.quelle
new String(x.bad)
eine Sammlung von Strings mit demx.bad
Wert 0-index-item erstellt . Die""+x.bad
von Simone beschriebene Variante funktioniert wie gewünscht - erstellt einen String-Wert anstelle von Int32db.questions.find({_id:{$type:16}}).forEach( function (x) { db.questions.remove({_id:x._id},true); x._id = ""+x._id; db.questions.save(x); });
String-Feld in Integer konvertieren:
Ganzzahlfeld in Zeichenfolge konvertieren:
quelle
NumberLong
wiedb.db-name.find({field-name : {$exists : true}}).forEach( function(obj) { obj.field-name = new NumberLong(obj.field-name); db.db-name.save(obj); } );
Für die Konvertierung von Zeichenfolgen in int.
Für die Konvertierung von Zeichenfolgen in doppelte.
Für Schwimmer:
quelle
radix
- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…new NumberInt()
quelle
Starten
Mongo 4.2
,db.collection.update()
kann eine Aggregation Pipeline akzeptieren, schließlich die Aktualisierung eines Feldes ermöglicht , basierend auf seinen eigenen Wert:Der erste Teil
{ a : { $type: 1 } }
ist die Übereinstimmungsabfrage:"a"
dies Elementen, für die"a"
der Typ1
(double) ist , da wir in einen String konvertieren möchten, wenn sein Wert ein Double ist .Der zweite Teil
[{ $set: { a: { $toString: "$a" } } }]
ist die Update-Aggregations-Pipeline:$set
ist ein neuer Aggregationsoperator (Mongo 4.2
), der in diesem Fall ein Feld ändert."$set"
der Wert der"a"
zu"$a"
umgewandelt"$toString"
.Mongo 4.2
, beim Aktualisieren auf das Dokument selbst zu verweisen: Der neue Wert für"a"
basiert auf dem vorhandenen Wert von"$a"
."$toString"
welcher neue Aggregationsoperator in eingeführt wurdeMongo 4.0
.Vergessen Sie nicht
{ multi: true }
, sonst wird nur das erste übereinstimmende Dokument aktualisiert.Falls Ihr Guss nicht doppelt zu bespannen, haben Sie die Wahl zwischen verschiedenen Konvertierungsoperator in eingeführt
Mongo 4.0
, wie$toBool
,$toInt
...Und wenn es für Ihren Zieltyp keinen dedizierten Konverter gibt, können Sie ihn durch
{ $toString: "$a" }
eine$convert
Operation ersetzen :{ $convert: { input: "$a", to: 2 } }
Der Wert fürto
befindet sich in dieser Tabelle :quelle
db.collection.updateMany( { a : { $type: 1 } }, [{ $set: { a: { $toString: "$a" } } }] )
- Dasmulti : true
kann vermieden werden mitupdateMany
Alle bisherigen Antworten verwenden eine Version von forEach, die clientseitig über alle Sammlungselemente iteriert.
Sie können jedoch die serverseitige Verarbeitung von MongoDB verwenden, indem Sie die aggregierte Pipeline und die $ out-Phase wie folgt verwenden :
Beispiel:
quelle
Um ein Feld vom Typ Zeichenfolge in ein Datumsfeld zu konvertieren, müssen Sie den von der
find()
Methode zurückgegebenen Cursor mithilfe von iterierenforEach()
Methode zurückgegebenen , das Feld innerhalb der Schleife in ein Datumsobjekt konvertieren und das Feld dann mit dem$set
Operator aktualisieren .Nutzen Sie die Bulk-API für Bulk-Updates, die eine bessere Leistung bieten, da Sie die Vorgänge in Stapeln von beispielsweise 1000 an den Server senden. Dies führt zu einer besseren Leistung, da Sie nicht jede Anforderung nur einmal an den Server senden 1000 Anfragen.
Im Folgenden wird dieser Ansatz veranschaulicht. Im ersten Beispiel wird die in MongoDB-Versionen verfügbare Bulk-API verwendet
>= 2.6 and < 3.2
. . Es aktualisiert alle Dokumente in der Sammlung, indem allecreated_at
Felder in Datumsfelder geändert werden:Das nächste Beispiel gilt für die neue MongoDB-Version,
3.2
die seitdem die Bulk-API veraltet und einen neueren Satz von APIs bereitgestellt hat, indem siebulkWrite()
:quelle
Um int32 in mongo in einen String umzuwandeln, ohne ein Array zu erstellen, fügen Sie einfach "" zu Ihrer Nummer hinzu :-)
quelle
Was mir wirklich geholfen hat, den Typ des Objekts in MondoDB zu ändern, war nur diese einfache Zeile, die hier vielleicht schon erwähnt wurde ...:
Benutzer sind meine Sammlung und Alter ist das Objekt, das eine Zeichenfolge anstelle einer Ganzzahl (int32) hatte.
quelle
Ich muss den Datentyp mehrerer Felder in der Sammlung ändern, daher habe ich Folgendes verwendet, um mehrere Datentypänderungen in der Sammlung von Dokumenten vorzunehmen. Beantworten Sie eine alte Frage, aber sie kann für andere hilfreich sein.
quelle
Versuchen Sie diese Abfrage ..
quelle
Demo Ändern Sie den Feldtyp in der Mitte von String zu Mongo ObjectId mit Mungo
Mongo ObjectId ist nur ein weiteres Beispiel für Stile wie
Zahl, Zeichenfolge, Boolescher Wert, die hoffen, dass die Antwort jemand anderem hilft.
quelle
Ich benutze dieses Skript in der Mongodb-Konsole für String-Float-Konvertierungen ...
Und dieser in php)))
quelle
In meinem Fall verwende ich Folgendes
quelle