sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDb - Cambiar tipo de Int a Double

De forma predeterminada, todos los "números" se almacenan como "dobles" en MongoDB, a menos que generalmente se emitan al revés.

Tome las siguientes muestras:

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

Esto produce una colección como esta:

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

A pesar de las diferentes funciones del constructor, observe cómo varios de los puntos de datos se parecen mucho. El propio shell de MongoDB no siempre distingue claramente entre ellos, pero hay una manera de saberlo.

Por supuesto, existe el $type operador de consulta, que permite la selección de tipos de BSON.

Así que probando esto con Tipo 1, que es "doble":

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

Verá que tanto el primer inserto como el último están seleccionados, pero por supuesto no los otros dos.

Así que ahora prueba para BSON Tipo 16, que es un número entero de 32 bits

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

Esa fue la "tercera" inserción que utilizó el NumberInt() función en la cáscara. Entonces esa función y otra serialización de su controlador pueden establecer este tipo de BSON específico.

Y para BSON Tipo 18, que es un entero de 64 bits

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

La "segunda" inserción que se construyó a través de NumberLong() .

Si quisieras "eliminar" las cosas que "no eran un doble", entonces harías:

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

Cuáles son los únicos otros tipos numéricos válidos además del "doble" en sí mismo.

Entonces, para "convertir" estos en su colección, puede realizar un proceso "en bloque" como este:

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

Lo que hace se realiza en tres pasos "a granel":

  1. Volver a emitir el valor a un nuevo campo como "doble"
  2. Eliminar el campo antiguo con el tipo no deseado
  3. Cambie el nombre del campo nuevo al nombre del campo antiguo

Esto es necesario ya que la información de tipo BSON es "pegajosa" al elemento de campo una vez creado. Entonces, para "volver a emitir", debe eliminar por completo los datos antiguos que incluyen la asignación de campo original.

Eso debería explicar cómo "detectar" y también "refundir" tipos no deseados en sus documentos.