Som standard lagras alla "siffror" som "dubbla" i MongoDB såvida de inte generellt kastas över.
Ta följande prover:
db.sample.insert({ "a": 1 })
db.sample.insert({ "a": NumberLong(1) })
db.sample.insert({ "a": NumberInt(1) })
db.sample.insert({ "a": 1.223 })
Detta ger en samling så här:
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
Trots de olika konstruktorfunktionerna notera hur flera av datapunkterna där ser ungefär likadana ut. MongoDB-skalet i sig skiljer inte alltid tydligt mellan dem, men det finns ett sätt du kan se.
Det finns naturligtvis $type
frågeoperator, som tillåter val av BSON-typer.
Så testar detta med typ 1 - vilket är "dubbelt":
> db.sample.find({ "a": { "$type": 1 } })
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }
Du ser att både den första och den sista är markerade, men naturligtvis inte de andra två.
Så testa nu för BSON Type 16 - som är ett 32-bitars heltal
> db.sample.find({ "a": { "$type": 16 } })
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
Det var den "tredje" infogningen som använde NumberInt()
funktion i skalet. Så den funktionen och annan serialisering från din drivrutin kan ställa in den här specifika BSON-typen.
Och för BSON Type 18 - som är 64-bitars heltal
> db.sample.find({ "a": { "$type": 18 } })
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
Den "andra" infogningen som skapades via NumberLong()
.
Om du ville "rensa bort" saker som "inte var en dubbel" så skulle du göra:
db.sample.find({ "$or": [{ "a": { "$type": 16 } },{ "a": { "$type": 18 } }]})
Som är de enda andra giltiga numeriska typerna förutom "dubbel" själv.
Så för att "konvertera" dessa i din samling kan du "Massa" process så här:
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();
Vad det gör utförs i tre steg "i bulk":
- Skapa om värdet till ett nytt fält som en "dubbel"
- Ta bort det gamla fältet med den oönskade typen
- Byt namn på det nya fältet till det gamla fältnamnet
Detta är nödvändigt eftersom BSON-typinformationen är "klibbig" till fältelementet när det väl skapats. Så för att "casta om" måste du helt ta bort den gamla data som inkluderar den ursprungliga fälttilldelningen.
Så det borde förklara hur man "upptäcker" och även "castar om" oönskade typer i dina dokument.