MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDb - Cambia tipo da Int a Double

Per impostazione predefinita, tutti i "numeri" sono archiviati come "doppi" in MongoDB a meno che non vengano generalmente espressi in modo eccessivo.

Prendi i seguenti campioni:

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

Questo produce una raccolta come questa:

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

Nonostante le diverse funzioni del costruttore, nota come molti dei punti dati presenti siano più o meno gli stessi. La stessa shell MongoDB non sempre distingue chiaramente tra loro, ma c'è un modo per dirlo.

C'è ovviamente il $type operatore di query, che consente la selezione di tipi BSON.

Quindi testarlo con il tipo 1, che è "doppio":

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

Vedi che sono selezionati sia il primo inserto che l'ultimo, ma ovviamente non gli altri due.

Quindi ora prova per BSON Type 16, che è un intero a 32 bit

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

Quello era il "terzo" inserimento che utilizzava NumberInt() funzione nella shell. In modo che quella funzione e altra serializzazione dal tuo driver possano impostare questo tipo BSON specifico.

E per il tipo BSON 18, che è un numero intero a 64 bit

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

Il "secondo" inserimento che è stato costruito tramite NumberLong() .

Se volessi "eliminare" le cose che "non erano un doppio", allora faresti:

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

Quali sono gli unici altri tipi numerici validi diversi dallo stesso "doppio".

Quindi, per "convertire" questi nella tua raccolta, puoi elaborare "in blocco" in questo modo:

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();

Ciò che fa viene eseguito in tre passaggi "in blocco":

  1. Ritrasforma il valore in un nuovo campo come "doppio"
  2. Rimuovi il vecchio campo con il tipo indesiderato
  3. Rinomina il nuovo campo con il vecchio nome del campo

Questo è necessario poiché le informazioni sul tipo BSON sono "appiccicose" all'elemento campo una volta creato. Quindi per "ritrasmettere" è necessario rimuovere completamente i vecchi dati che includono l'assegnazione del campo originale.

Quindi questo dovrebbe spiegare come "rilevare" e anche "ritrasmettere" i tipi indesiderati nei tuoi documenti.