#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() } } }