Som standard er alle "numre" gemt som "dobbelt" i MongoDB, medmindre det generelt er castet over.
Tag følgende prøver:
db.sample.insert({ "a": 1 })
db.sample.insert({ "a": NumberLong(1) })
db.sample.insert({ "a": NumberInt(1) })
db.sample.insert({ "a": 1.223 })
Dette giver en samling som denne:
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
På trods af de forskellige konstruktørfunktioner skal du bemærke, hvordan flere af datapunkterne der ser meget ens ud. MongoDB-skallen i sig selv skelner ikke altid klart mellem dem, men der er en måde, du kan se.
Der er selvfølgelig $type
forespørgselsoperator, som tillader valg af BSON-typer.
Så tester dette med Type 1 - som er "dobbelt":
> db.sample.find({ "a": { "$type": 1 } })
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
Du ser, at både det første indstik og det sidste er valgt, men selvfølgelig ikke de to andre.
Så test nu for BSON Type 16 - som er et 32-bit heltal
> db.sample.find({ "a": { "$type": 16 } })
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
Det var den "tredje" indsættelse, der brugte NumberInt()
funktion i skallen. Så den funktion og anden serialisering fra din driver kan indstille denne specifikke BSON-type.
Og for BSON Type 18 - som er 64-bit heltal
> db.sample.find({ "a": { "$type": 18 } })
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
Den "anden" indsættelse, som blev konstrueret via NumberLong()
.
Hvis du ville "luge ud" ting, der "ikke var en dobbelt", så ville du gøre:
db.sample.find({ "$or": [{ "a": { "$type": 16 } },{ "a": { "$type": 18 } }]})
Som er de eneste andre gyldige numeriske typer ud over "dobbelt" selv.
Så for at "konvertere" disse til din samling, kan du "massebehandle" på denne måde:
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();
Hvad det gør, udføres i tre trin "i bulk":
- Gencast værdien til et nyt felt som en "dobbelt"
- Fjern det gamle felt med den uønskede type
- Omdøb det nye felt til det gamle feltnavn
Dette er nødvendigt da BSON-typeoplysningerne er "klæbende" til feltelementet, når først det er oprettet. Så for at "gencaste" skal du helt fjerne de gamle data, som inkluderer den originale felttildeling.
Så det burde forklare, hvordan du "opdager" og også "gencaster" uønskede typer i dine dokumenter.