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

mongodb casting

11872 просмотра

1 ответ

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

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

Теперь некоторые из "v" являются целыми числами, а некоторые - двойными. Я хочу изменить их все на двойники.

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

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

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

Автор: Carra Источник Размещён: 12.11.2019 09:41

Ответы (1)


10 плюса

Решение

По умолчанию все «числа» хранятся как «двойные» в 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 не всегда четко различает их, но есть способ, которым вы можете сказать.

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

Итак, тестируем это с Типом 1, который является «двойным»:

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

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

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

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

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

А для BSON Type 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. Повторите приведение значения к новому полю как к двойному.
  2. Удалите старое поле с нежелательным типом
  3. Переименуйте новое поле в старое имя поля

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

Так что это должно объяснить, как «обнаруживать», а также «повторно использовать» нежелательные типы в ваших документах.

Автор: Blakes Seven Размещён: 07.07.2015 11:42
Вопросы из категории :
32x32