MongoDb-изменить тип с Int на Double

у нас есть коллекция, которая выглядит так:

{
    "_id" : "10571:6",
    "v" : 261355,
    "ts" : 4.88387e+008
}

Теперь некоторые из " v " - это ints, некоторые-Double. Я хочу сменить их на двойные.

Я пробовал несколько вещей, но ничего не работает (v-int32 для этой записи, я хочу изменить его на двойной):

db.getCollection('VehicleLastValues')
.find
(

    {_id : "10572:6"}
)
.forEach
(
function (x)
{
    temp = x.v * 1.0;
    db.getCollection('VehicleLastValues').save(x);
}}

вещи, которые я пробовал:

x.v = x.v * 1.1 / 1.1;
x.v = parseFloat (new String(x.v));

но я не могу получить его, чтобы сохранить как двойной...

1 ответов


по умолчанию все " числа "хранятся как" двойные " в MongoDB, если обычно не перелистываются.

возьмите следующие образцы:

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

это дает такую коллекцию:

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

несмотря на различные функции конструктора обратите внимание, как несколько точек данных там выглядят примерно одинаково. Сама оболочка MongoDB не всегда четко распределяется между ними, но есть способ, которым вы можете сказать.

есть конечно the $type оператор запроса, который позволяет выбирать типы BSON.

Итак, тестирование этого с типом 1-который является "двойным":

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

вы видите, что выбраны как первая вставка, так и последняя, но, конечно, не два других.

Итак, теперь тест для типа bson 16-это 32-разрядное целое число

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

это была" третья " вставка, которая использовала NumberInt() функция в оболочке. Так что функция и другая сериализация из вашего драйвера может установить этот конкретный тип BSON.

и для типа bson 18-который является 64-разрядным целым числом

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

" вторая " вставка, которая была сконструирована через NumberLong().

если бы вы хотели "отсеять" вещи, которые не были "двойными", вы бы сделали:

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

которые являются единственными другими допустимыми числовыми типами, кроме самого "double".

таким образом, чтобы "конвертировать" их в свою коллекцию, вы можете "Массовый" процесс выглядит так:

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

то, что это делает, выполняется в три шага "навалом":

  1. повторно приведите значение в новое поле как "double"
  2. удалите старое поле с нежелательным типом
  3. переименовать новое поле в старое имя поля

это необходимые поскольку информация о типе BSON "прилипает" к элементу поля после его создания. Так что для того, чтобы" переиграть " нужно полностью удалите старые данные, которые включают в себя исходное назначение поля.

так что должно объяснить, как "обнаружить", а также "перепрофилировать" нежелательные типы в ваших документах.