Преобразование строки на сегодняшний день в mongodb

Есть ли способ конвертировать строку в дату с использованием пользовательского формата с использованием оболочки mongodb

Я пытаюсь преобразовать "21/май/2012: 16: 35: 33 -0400" на сегодняшний день,

Есть ли способ пройти DateFormatter или что-то еще Date.parse(...) или ISODate(....) метод?

Ответы

Ответ 1

Вы можете использовать javascript во второй ссылке, предоставленной Ravi Khakhkhar, или вам придется выполнить некоторые манипуляции с строкой, чтобы преобразовать вашу оригинальную строку (так как некоторые специальные символы в вашем исходном формате не признаются действительными метриками), но как только вы это сделаете, вы можете использовать "новые"

training:PRIMARY> Date()
Fri Jun 08 2012 13:53:03 GMT+0100 (IST)
training:PRIMARY> new Date()
ISODate("2012-06-08T12:53:06.831Z")

training:PRIMARY> var start = new Date("21/May/2012:16:35:33 -0400")        => doesn't work
training:PRIMARY> start
ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ")

training:PRIMARY> var start = new Date("21 May 2012:16:35:33 -0400")        => doesn't work    
training:PRIMARY> start
ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ")

training:PRIMARY> var start = new Date("21 May 2012 16:35:33 -0400")        => works
training:PRIMARY> start
ISODate("2012-05-21T20:35:33Z")

Здесь некоторые ссылки, которые могут оказаться полезными (относительно модификации данных в оболочке mongo) -

http://cookbook.mongodb.org/patterns/date_range/

http://www.mongodb.org/display/DOCS/Dates

http://www.mongodb.org/display/DOCS/Overview+-+The+MongoDB+Interactive+Shell

Ответ 2

В моем случае у меня получилось следующее решение для преобразования поля ClockInTime из коллекции ClockTime из строки в тип даты:

db.ClockTime.find().forEach(function(doc) { 
    doc.ClockInTime=new Date(doc.ClockInTime);
    db.ClockTime.save(doc); 
    })

Ответ 3

Использование MongoDB 4.0 и новее

Оператор $toDate преобразует значение в дату. Если значение не может быть преобразовано в дату, ошибки $toDate. Если значение равно null или отсутствует, $toDate возвращает null:

Вы можете использовать его в совокупном конвейере следующим образом:

db.collection.aggregate([
    { "$addFields": {
        "created_at": {
            "$toDate": "$created_at"
        }
    } }
])

Вышеупомянутое эквивалентно использованию оператора $convert следующим образом:

db.collection.aggregate([
    { "$addFields": {
        "created_at": { 
            "$convert": { 
                "input": "$created_at", 
                "to": "date" 
            } 
        }
    } }
])

Использование MongoDB 3.6 и новее

Вы также используете оператор $dateFromString который преобразует строку даты/времени в объект даты и имеет параметры для указания формата даты, а также часового пояса:

db.collection.aggregate([
    { "$addFields": {
        "created_at": { 
            "$dateFromString": { 
                "dateString": "$created_at",
                "format": "%m-%d-%Y"
            } 
        }
    } }
])

Использование версий MongoDB >= 2.6 and < 3.2

Если версия MongoDB не имеет собственных операторов, которые выполняют преобразование, вам необходимо вручную перебрать курсор, возвращаемый методом find(), либо используя метод forEach() либо метод cursor next() для доступа к документам. С помощью цикла преобразуем поле в объект ISODate и затем обновляем поле с помощью оператора $set, как в следующем примере, где поле называется created_at и в настоящее время содержит дату в строчном формате:

var cursor = db.collection.find({"created_at": {"$exists": true, "$type": 2 }}); 
while (cursor.hasNext()) { 
    var doc = cursor.next(); 
    db.collection.update(
        {"_id" : doc._id}, 
        {"$set" : {"created_at" : new ISODate(doc.created_at)}}
    ) 
};

Для улучшения производительности, особенно при работе с большими коллекциями, используйте преимущества Bulk API для массовых обновлений, поскольку вы будете отправлять операции на сервер партиями 1000, что дает вам лучшую производительность, поскольку вы не отправляете каждый запрос на сервер, только один раз в 1000 запросов.

Следующий пример демонстрирует этот подход, первый пример использует Bulk API, доступный в версиях MongoDB >= 2.6 and < 3.2. Он обновляет все документы в коллекции, изменяя поля created_at на дату:

var bulk = db.collection.initializeUnorderedBulkOp(),
    counter = 0;

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
    var newDate = new ISODate(doc.created_at);
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "created_at": newDate}
    });

    counter++;
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }

Использование MongoDB 3.2

Следующий пример применим к новой версии MongoDB 3.2 которая с тех пор устарела от Bulk API и предоставила новый набор apis, используя bulkWrite():

var bulkOps = [],
    cursor = db.collection.find({"created_at": {"$exists": true, "$type": 2 }});

cursor.forEach(function (doc) { 
    var newDate = new ISODate(doc.created_at);
    bulkOps.push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "created_at": newDate } } 
            }         
        }           
    );

    if (bulkOps.length === 500) {
        db.collection.bulkWrite(bulkOps);
        bulkOps = [];
    }     
});

if (bulkOps.length > 0) db.collection.bulkWrite(bulkOps);

Ответ 4

У меня были некоторые строки в MongoDB Хранилище, которое нужно было перестроить в правильное и действительное поле DateTime в mongodb.

вот мой код для специального формата даты: "2014-03-12T09: 14: 19.5303017 + 01: 00"

но вы можете легко принять эту идею и написать собственное регулярное выражение для анализа форматов даты:

// format: "2014-03-12T09:14:19.5303017+01:00"
var myregexp = /(....)-(..)-(..)T(..):(..):(..)\.(.+)([\+-])(..)/;

db.Product.find().forEach(function(doc) { 
   var matches = myregexp.exec(doc.metadata.insertTime);

   if myregexp.test(doc.metadata.insertTime)) {
       var offset = matches[9] * (matches[8] == "+" ? 1 : -1);
       var hours = matches[4]-(-offset)+1
       var date = new Date(matches[1], matches[2]-1, matches[3],hours, matches[5], matches[6], matches[7] / 10000.0)
       db.Product.update({_id : doc._id}, {$set : {"metadata.insertTime" : date}})
       print("succsessfully updated");
    } else {
        print("not updated");
    }
})

Ответ 5

Как насчет использования библиотеки momentjs, написав script следующим образом:

[install_moment.js]
function get_moment(){
    // shim to get UMD module to load as CommonJS
    var module = {exports:{}};

    /* 
    copy your favorite UMD module (i.e. moment.js) here
    */

    return module.exports
}
//load the module generator into the stored procedures: 
db.system.js.save( {
        _id:"get_moment",
        value: get_moment,
    });

Затем загрузите script в командной строке следующим образом:

> mongo install_moment.js

Наконец, в следующем сеансе mongo используйте его так:

// LOAD STORED PROCEDURES
db.loadServerScripts();

// GET THE MOMENT MODULE
var moment = get_moment();

// parse a date-time string
var a = moment("23 Feb 1997 at 3:23 pm","DD MMM YYYY [at] hh:mm a");

// reformat the string as you wish:
a.format("[The] DDD['th day of] YYYY"): //"The 54'th day of 1997"

Ответ 6

Вы можете использовать агрегацию $dateFromString которая преобразует дату строки в дату ISO

db.collection.aggregate([
  {
    "$project": {
      "date": {
        "$dateFromString": {
          "dateString": "$date"
        }
      }
    }
  }
])