MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDb - Ändern Sie den Typ von Int zu Double

Standardmäßig werden alle "Zahlen" in MongoDB als "Doppelt" gespeichert, sofern sie nicht allgemein überschrieben werden.

Nehmen Sie die folgenden Proben:

db.sample.insert({ "a": 1 })
db.sample.insert({ "a": NumberLong(1) })
db.sample.insert({ "a": NumberInt(1) })
db.sample.insert({ "a": 1.223 })

Dies ergibt eine Sammlung wie diese:

{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }

Beachten Sie trotz der unterschiedlichen Konstruktorfunktionen, dass einige der Datenpunkte dort ziemlich gleich aussehen. Die MongoDB-Shell selbst unterscheidet nicht immer klar zwischen ihnen, aber es gibt eine Möglichkeit, dies zu erkennen.

Es gibt natürlich den $type Abfrageoperator, der die Auswahl von BSON-Typen ermöglicht.

Testen Sie dies also mit Typ 1 - der "doppelt" ist:

> db.sample.find({ "a": { "$type": 1 } })
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }

Sie sehen, dass sowohl die erste als auch die letzte Einfügung ausgewählt sind, aber natürlich nicht die anderen beiden.

Testen Sie jetzt also auf BSON Type 16 – das ist eine 32-Bit-Ganzzahl

> db.sample.find({ "a": { "$type": 16 } })
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }

Das war die "dritte" Einfügung, die NumberInt() verwendete Funktion in der Schale. Damit diese Funktion und andere Serialisierungen Ihres Treibers diesen spezifischen BSON-Typ festlegen können.

Und für den BSON-Typ 18 – das ist eine 64-Bit-Ganzzahl

> db.sample.find({ "a": { "$type": 18 } })
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }

Die "zweite" Einfügung, die über NumberLong() konstruiert wurde .

Wenn Sie Dinge "aussortieren" wollten, die "kein Double" waren, dann würden Sie Folgendes tun:

db.sample.find({ "$or": [{ "a": { "$type": 16 } },{ "a": { "$type": 18 } }]})

Welches sind die einzigen anderen gültigen numerischen Typen außer "double" selbst.

Um diese also in Ihrer Sammlung zu "konvertieren", können Sie wie folgt "Bulk" verarbeiten:

var bulk = db.sample.initializeUnorderedBulkOp(),
    count = 0;
db.sample.find({ 
    "$or": [
        { "a": { "$type": 16 } },
        { "a": { "$type": 18 } }
    ]
}).forEach(function(doc) {
    bulk.find({ "_id": doc._id })
        .updateOne({ 
            "$set": { "b": doc.a.valueOf() } ,
            "$unset": { "a": 1 } 
        });
    bulk.find({ "_id": doc._id })
        .updateOne({ "$rename": { "b": "a" } });
    count++;
    if ( count % 1000 == 0 ) {
        bulk.execute()
        bulk = db.sample.initializeUnOrderedBulkOp();
    }
})
if ( count % 1000 != 0 ) bulk.execute();

Was das tut, wird in drei Schritten "in großen Mengen" durchgeführt:

  1. Umwandlung des Werts in ein neues Feld als "Double"
  2. Entfernen Sie das alte Feld mit dem unerwünschten Typ
  3. Benennen Sie das neue Feld in den alten Feldnamen um

Dies ist notwendig da die BSON-Typinformationen an dem einmal erstellten Feldelement "haften". Um also "neu umzuwandeln", müssen Sie die alten Daten vollständig entfernen, einschließlich der ursprünglichen Feldzuordnung.

Das sollte also erklären, wie Sie unerwünschte Typen in Ihren Dokumenten „erkennen“ und auch „umwandeln“ können.