Standaard worden alle "nummers" opgeslagen als "dubbel" in MongoDB, tenzij ze over het algemeen overmatig worden gegoten.
Neem de volgende voorbeelden:
db.sample.insert({ "a": 1 })
db.sample.insert({ "a": NumberLong(1) })
db.sample.insert({ "a": NumberInt(1) })
db.sample.insert({ "a": 1.223 })
Dit levert een verzameling op zoals deze:
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
Merk ondanks de verschillende constructorfuncties op hoe verschillende datapunten er ongeveer hetzelfde uitzien. De MongoDB-shell zelf maakt niet altijd duidelijk onderscheid tussen hen, maar er is een manier om het te zien.
Er is natuurlijk de $type
query-operator, waarmee u BSON-typen kunt selecteren.
Dus dit testen met Type 1 - Wat "dubbel" is:
> db.sample.find({ "a": { "$type": 1 } })
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
Je ziet dat zowel de eerste als de laatste zijn geselecteerd, maar de andere twee natuurlijk niet.
Dus test nu voor BSON Type 16 - wat een 32-bits geheel getal is
> db.sample.find({ "a": { "$type": 16 } })
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
Dat was de "derde" invoeging die de NumberInt()
. gebruikte functie in de schil. Zodat functie en andere serialisatie van uw stuurprogramma dit specifieke BSON-type kan instellen.
En voor de BSON Type 18 - dat is 64-bit integer
> db.sample.find({ "a": { "$type": 18 } })
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
De "tweede" invoeging die is gemaakt via NumberLong()
.
Als je dingen die "geen dubbel" waren, zou willen "verwijderen", dan zou je het volgende doen:
db.sample.find({ "$or": [{ "a": { "$type": 16 } },{ "a": { "$type": 18 } }]})
Dit zijn de enige andere geldige numerieke typen dan "dubbel" zelf.
Dus om deze in uw verzameling te "converteren", kunt u dit als volgt "bulken":
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();
Wat dat doet, wordt in drie stappen "in bulk" uitgevoerd:
- Creëer de waarde naar een nieuw veld als een "double"
- Verwijder het oude veld met het ongewenste type
- Hernoem het nieuwe veld naar de oude veldnaam
Dit is noodzakelijk omdat de informatie van het BSON-type "kleverig" is voor het veldelement dat eenmaal is gemaakt. Dus om te "re-casten" moet je de oude gegevens volledig verwijderen, inclusief de originele veldtoewijzing.
Dus dat zou moeten verklaren hoe u ongewenste typen in uw documenten kunt "detecteren" en ook "opnieuw casten".