Правильное использование / обработка DateTimeOffset в MongoDB
public class ScheduledEvent : Event
{
public DateTimeOffset StartDateTime { get; set; }
}
StartDateTime = 27.05.2013 2:09:00 +00:00, представляющий 26.05.2013, 19:09 PST
Что записано в MongoDB:
> db.ScheduledEvent.find().toArray()
[
{
"_id" : BinData(3,"ZE2p31dh00qb6kglsgHgAA=="),
"Title" : "Today 26th at 7:09pm",
"Length" : "00:00:00",
"MoreInformation" : "http://1.com",
"Speakers" : [
{
"_id" : BinData(3,"ndzESsQGukmYGmMgKK0EqQ=="),
"Name" : "Mathias Brandewinder"
}
],
"Location" : {
"_id" : BinData(3,"AAAAAAAAAAAAAAAAAAAAAA=="),
"Name" : "Somwhere "
},
"Organizers" : [
{
"_id" : BinData(3,"AAAAAAAAAAAAAAAAAAAAAA=="),
"Name" : null
}
],
"CreatedOn" : [
NumberLong("635052144104050898"),
0
],
"StartDateTime" : [
NumberLong("635052173400000000"),
0
]
}
]
Я понимаю, что StartDateTime хранится в виде тиков в MongoDB.
var dateMarker = DateTimeOffset.UtcNow;
var nextDay = dateMarker.AddDays(1);
Этот запрос не работает:
var today = EventRepoistory.All().Where(z => z.StartDateTime >= dateMarker && z.StartDateTime < nextDay).OrderByDescending(z => z.StartDateTime).ToList();
Я добавил отображение запроса в драйвер Mongo C#, который показывает следующий запрос:
{ "$query" : { "StartDateTime" : { "$gte" : [NumberLong("635052168609734070"), 0], "$lt" : [NumberLong("635053032609734070"), 0] } }, "$orderby" : { "StartDateTime" : -1 } }
Нижняя граница = 6350521 68609734070
Сервер = 6350521 73400000000
Верхняя граница = 6350530 32609734070
Вопрос: Почему запрос MongoDB ничего не возвращает?
db.ScheduledEvent.find ({"$ query": {"StartDateTime": {"$ gte": [NumberLong ("635052168609734070"), 0], "$ lt": [NumberLong ("635053032609734070"), 0]} }, "$ orderby": {"StartDateTime": -1}})
Исследуемый:
Тип MongoDB и DateTimeOffset, но он показывает, что поставщик LINQ делает то, что должен?
Пытался:
db.ScheduledEvent.find({ "StartDateTime" : { "$gte" : [NumberLong("1"), 0] } } )
не дает результатов.
2 ответа
Подобный ответ находится здесь: MongoDB и тип DateTimeOffset (как вы отметили в своем вопросе)
Я получил это, работая с драйвером C#, выполнив следующие действия:
var query = Query.GT("StartDateTime.0", startDate.Ticks);
var json = query.ToJson();
Производит этот JSON:
{ "StartDateTime.0" : { "$gt" : NumberLong("635251617859913739") } }
Выше JSON работает. Согласно связанному ответу причина в том, что DateTimeOffset является массивом.
Когда я использую LINQ, я получаю (как вы заметили) другой результат для JSON.
var query = from r in col.AsQueryable<MyObjectType>()
where r.StartDateTime>= startDate && r.StartDateTime< endDate
select r;
Приведенный выше запрос LINQ создает следующий JSON:
{ "StartDateTime" : { "$gte" : [NumberLong("635251617859913739"), 0], "$lt" : [NumberLong("635251635859913739"), 0] } }
Я не уверен, нужно ли исправлять поставщика LINQ в драйвере C# для обработки DateTimeOffset, но использование конструктора запросов для указания первого элемента массива DateTimeOffset (StartDateTime.0) было единственным способом, которым я получил эту работу.
Как утверждают другие ответы, основная причина проблемы заключается в том, что DateTimeOffset
поля по умолчанию сериализуются как массивы (с отметками и смещением).
Ответ, предложенный dsandor, отлично работает, если вы можете локализовать свои изменения в слое DAL и использовать запросы, специфичные для MongoDB.
Однако такой подход не работает, если в вашем репозитории есть IQueryable<ScheduledEvent>
и некоторые запросы LINQ применяются на уровне обслуживания.
Более общий подход - изменить способ DateTimeOffset
Поля сериализуются в MongoDB, чтобы запросы LINQ работали правильно, без необходимости настройки запросов MongoDB.
Вы можете легко изменить сериализацию DateTimeOffset
поля с BsonRepresentation(BsonType.String)
атрибут:
public class ScheduledEvent : Event
{
[BsonRepresentation(BsonType.String)]
public DateTimeOffset StartDateTime { get; set; }
}
В этом случае DateTimeOffset
поля сохраняются в MongoDB в строковой форме 2020-04-03T08:12:23+03:00
и запросы LINQ работают правильно.
Используйте следующий синтаксис в вашем запросе:
{
"StartDateTime.0": {
"$gte": 635052168609734070
}
}