Mongo: строки, преобразованные в дату, но не «подлежащие запросу»

#string #mongodb #date

#строка #mongodb #Дата

Вопрос:

У меня есть коллекция с датой, хранящаяся в виде строк ГГГГ-мм-DD_HH:MM:SS.UUUZ, например, 2020-10-20_12:15:22.123 0100

Моя цель — запрашивать строки, обрабатывающие их как даты.

Что я делаю: я разматываю некоторые данные заголовка в нескольких документах:

     {
            "$unwind": {
                "path": "$events",
                "preserveNullAndEmptyArrays": true
            }
        }
  

а также

     {
            "$unwind": {
                "path": "$events.hi2",
                "preserveNullAndEmptyArrays": true
            }
}
  

Я добавляю новое поле, созданное со строкой, проанализированной как дата

     {
            "$addFields": {
                "events.hi2.ConnectTimets": {
                    "$dateFromString": {
                        "dateString": "$events.hi2.ConnectTime",
                        "format": "%Y-%m-%d_%H:%M:%S.%L%Z"
                    }
                }
    }}
  

затем на $match этапе я пытаюсь отфильтровать все записи с датой новее 1 июня 2020 года:

     {
            "$match":{
                "events.hi2.ConnectTimets": {
                                    "$gt": {"$dateFromString": {
                                                "dateString": "2020-06-01",
                                                "format": "%Y-%m-%d"
                                                 }
                                             }
                                }
                }   
         }
  

мой результат Fetched 0 record(s) in 0ms

даже если в базе данных существует (по крайней мере, один документ) с датой, соответствующей фильтру:

     {
        "_id" : ObjectId("5f438dfbf1feb13c4352e9f4"),
        "timestamp" : NumberLong(1598262779045),
        "attribute1" : [ 
            "common"
        ],
        "events" : [ 
            {
                "eventType" : "ty1",
                "timestamp" : NumberLong(1598262779018),
                "docId" : NumberLong(282578800148736),
                "hi2" : {
                    "Priority" : 3,
                    "ClientId" : "client1",
                    "ConnectTime" : "2020-08-24_09:52:58.993 0000",
                    "Direction" : 1
                }
            },
            {
                "eventType" : "ty2",
                "timestamp" : NumberLong(1598262781071),
                "docId" : NumberLong(282578800148736),
                "hi2" : {
                    "ref" : "bbbb"
                    
                }
            }
        ]  
    }

  

Когда я заметил что-то вроде

     {
            "_id" : ObjectId("5f438dfbf1feb13c4352e9f4"),
            "timestamp" : NumberLong(1598262779045),
            "attribute1" : [ 
                "common"
            ],
            "events" : [ 
                {
                    "eventType" : "ty1",
                    "timestamp" : NumberLong(1598262779018),
                    "docId" : NumberLong(282578800148736),
                    "hi2" : {
                        "Priority" : 3,
                        "ClientId" : "client1",
                        "ConnectTime" : "2020-08-24_09:52:58.993 0000",
                        "Direction" : 1
                 }
    }
    }
  

Примечание_: поле добавления в порядке, потому что, если я запускаю его без этапа сопоставления, выводится поле со строкой, проанализированной как дата

Ответ №1:

Вы никогда не должны хранить значения даты / времени в виде строки, всегда используйте правильные Date объекты. Тогда запрос намного проще:

 db.logging.aggregate([
   {
      $addFields: {
         "events.hi2.ConnectTimets": {
            $dateFromString: {
               dateString: "$events.hi2.ConnectTime",
               format: "%Y-%m-%d_%H:%M:%S.%L%Z"
            }
         }
      }
   },
   { $match: { "events.hi2.ConnectTimets": { $gte: ISODate("2020-06-01") } } }
])
  

Когда вам приходится работать со значениями даты / времени, я рекомендую moment.js . Тогда ваш запрос может выглядеть следующим образом:

 { $match: { "events.hi2.ConnectTimets": { $gte: moment("2020-06-01").toDate() } } }
{ $match: { "events.hi2.ConnectTimets": { $gte: moment("2020-06-01").tz('Europe/Zurich').toDate() } } }
{ $match: { "events.hi2.ConnectTimets": { $lte: moment.tz('Europe/Zurich').endOf('day').toDate() } } }