Работа с датами в MongoDB

MongoDBBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы научитесь работать с датами в MongoDB. Вы попрактикуетесь во вставке документов со значениями дат, запросах документов в пределах определенных диапазонов дат, форматировании полей дат для отображения, обновлении существующих полей дат и сортировке коллекций по дате. Эта лабораторная работа представляет собой всестороннее практическое руководство по функциям MongoDB, связанным с датами, которые необходимы для управления данными временных рядов, планирования и приложений для ведения журналов.

Вставка документов со значениями дат

На этом первом этапе вы подключитесь к серверу MongoDB и вставите несколько документов, содержащих значения дат. Это послужит основой для запросов и операций, которые вы выполните на последующих этапах.

Сначала откройте оболочку MongoDB, выполнив команду mongosh в вашем терминале. Это подключит вас к запущенному экземпляру MongoDB.

mongosh

Оказавшись внутри оболочки, вы увидите приглашение, похожее на test>. Давайте переключимся на новую базу данных с именем datelab. Если база данных не существует, MongoDB создаст ее для вас при первой вставке данных.

use datelab

Теперь вы вставите три документа в новую коллекцию под названием events. Каждый документ будет представлять событие и включать дату. MongoDB хранит даты как объекты BSON Date, которые вы можете создать с помощью конструктора new Date().

Вставляйте следующие документы по одному. Первый использует строку даты в формате ISO-8601, второй использует текущую дату и время, а третий использует временную метку Unix в миллисекундах.

db.events.insertOne({
    event_name: "Conference",
    date: new Date("2024-06-15T10:30:00Z")
})
db.events.insertOne({
    event_name: "System Maintenance",
    timestamp: new Date()
})
db.events.insertOne({
    event_name: "Project Deadline",
    timestamp: new Date(1718476800000)
})

После вставки документов вы можете проверить, были ли они добавлены правильно, используя метод find(), который извлекает все документы из коллекции.

db.events.find()

Ваш вывод должен выглядеть примерно так, хотя значения _id и timestamp для "System Maintenance" будут отличаться у вас.

[
  {
    _id: ObjectId("65d38f8a1c2d3e4f5a6b7c8d"),
    event_name: 'Conference',
    date: ISODate('2024-06-15T10:30:00.000Z')
  },
  {
    _id: ObjectId("65d38f9c1c2d3e4f5a6b7c8e"),
    event_name: 'System Maintenance',
    timestamp: ISODate('2024-02-19T14:55:24.123Z')
  },
  {
    _id: ObjectId("65d38fb11c2d3e4f5a6b7c8f"),
    event_name: 'Project Deadline',
    timestamp: ISODate('2024-06-15T18:00:00.000Z')
  }
]

Теперь вы успешно вставили документы со значениями дат. На следующем шаге вы узнаете, как запрашивать эти документы на основе их дат.

Запрос документов по диапазону дат

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

Сначала давайте добавим больше событий в нашу коллекцию, чтобы сделать запросы более интересными. Мы будем использовать метод insertMany() для добавления трех документов одновременно.

db.events.insertMany([
    {
        event_name: "Summer Conference",
        date: new Date("2024-07-15T09:00:00Z")
    },
    {
        event_name: "Winter Workshop",
        date: new Date("2024-01-20T14:30:00Z")
    },
    {
        event_name: "Spring Meetup",
        date: new Date("2024-04-10T11:15:00Z")
    }
])

Теперь у вас всего шесть событий. Давайте найдем все события, которые произошли после 1 июня 2024 года. Для этого вы будете использовать оператор "больше чем", $gt.

db.events.find({
    date: { $gt: new Date("2024-06-01") }
})

Далее, давайте найдем все события, которые произошли в первой половине 2024 года, а именно между 1 января и 1 июня. Для этого вы можете объединить операторы "больше или равно" ($gte) и "меньше чем" ($lt).

db.events.find({
    date: {
        $gte: new Date("2024-01-01"),
        $lt: new Date("2024-06-01")
    }
})

Запрос вернет события "Winter Workshop" и "Spring Meetup". Вывод должен выглядеть так:

[
  {
    _id: ObjectId("65d392a11c2d3e4f5a6b7c91"),
    event_name: 'Winter Workshop',
    date: ISODate('2024-01-20T14:30:00.000Z')
  },
  {
    _id: ObjectId("65d392a11c2d3e4f5a6b7c92"),
    event_name: 'Spring Meetup',
    date: ISODate('2024-04-10T11:15:00.000Z')
  }
]

Эти примеры демонстрируют, как использовать операторы сравнения ($gt, $gte, $lt, $lte) для эффективной фильтрации документов на основе полей дат.

Форматирование вывода дат с помощью агрегации

Часто требуется отображать даты в определенном, удобочитаемом формате. Фреймворк агрегации MongoDB предоставляет мощные инструменты для этого. На этом этапе вы будете использовать оператор $dateToString для форматирования ваших полей дат.

Фреймворк агрегации обрабатывает документы через конвейер стадий. Мы будем использовать стадию $project для изменения структуры наших документов и создания нового, отформатированного поля даты.

Давайте отформатируем поле date наших событий в формат ГГГГ-ММ-ДД. Этот запрос обработает только те документы, у которых есть поле date.

db.events.aggregate([
    {
        $project: {
            event_name: 1,
            formatted_date: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: "$date"
                }
            }
        }
    }
])

Разберем эту команду:

  • db.events.aggregate([...]): Инициирует конвейер агрегации для коллекции events.
  • $project: Стадия, которая изменяет структуру документов. Мы включаем event_name и создаем новое поле formatted_date.
  • $dateToString: Оператор, который преобразует объект даты в строку.
  • format: "%Y-%m-%d": Указывает формат вывода. %Y — год, %m — месяц, %d — день.
  • date: "$date": Указывает входное поле даты из исходного документа. Префикс $ указывает на путь к полю.

Вывод покажет исходное название события и новую отформатированную строку даты. Обратите внимание, что документы без поля date (например, "System Maintenance") будут исключены из результата.

[
  { _id: ObjectId("..."), event_name: 'Conference', formatted_date: '2024-06-15' },
  { _id: ObjectId("..."), event_name: 'Summer Conference', formatted_date: '2024-07-15' },
  { _id: ObjectId("..."), event_name: 'Winter Workshop', formatted_date: '2024-01-20' },
  { _id: ObjectId("..."), event_name: 'Spring Meetup', formatted_date: '2024-04-10' }
]

Вы также можете извлекать отдельные компоненты даты, такие как год или месяц, используя операторы, такие как $year и $month.

db.events.aggregate([
    {
        $project: {
            event_name: 1,
            year: { $year: "$date" },
            month: { $month: "$date" },
            day: { $dayOfMonth: "$date" }
        }
    }
])

Это дает вам детальный контроль над тем, как вы обрабатываете и представляете информацию о датах.

Обновление полей дат

Ваши данные не всегда статичны. Возможно, вам потребуется обновить поля дат, например, перенести событие или добавить временную метку модификации. На этом этапе вы узнаете, как обновлять поля дат, используя различные операторы обновления.

Сначала давайте перенесем событие "Conference" на новую дату. Мы будем использовать метод updateOne() для выбора одного документа и оператор $set для изменения его поля date.

db.events.updateOne(
    { event_name: "Conference" },
    {
        $set: {
            date: new Date("2024-09-01T10:00:00Z"),
            status: "Rescheduled"
        }
    }
)

Теперь давайте выполним массовое обновление. Мы отметим все события, которые произошли до 1 мая 2024 года, как "Archived" (Архивировано). Мы также добавим новое поле last_modified, чтобы записать, когда произошло это обновление. Метод updateMany() изменит все соответствующие документы, а оператор $currentDate идеально подходит для установки поля на текущее время сервера.

db.events.updateMany(
    { date: { $lt: new Date("2024-05-01") } },
    {
        $set: { status: "Archived" },
        $currentDate: { last_modified: true }
    }
)

Давайте проверим изменения, получив все документы. Метод .pretty() устарел, поэтому мы просто используем find().

db.events.find()

Вы увидите, что у "Conference" новая дата и статус. "Winter Workshop" и "Spring Meetup" теперь помечены как "Archived" и имеют временную метку last_modified.

Пример вывода для архивированного события:

{
 "_id" : ObjectId("..."),
 "event_name" : "Winter Workshop",
 "date" : ISODate("2024-01-20T14:30:00Z"),
 "status" : "Archived",
 "last_modified" : ISODate("2024-02-19T15:10:00Z")
}

Эти операции показывают, как вы можете точно изменять информацию, связанную с датами, в ваших документах.

Сортировка документов по дате

Последняя фундаментальная операция, которую вы изучите, — это сортировка. Отображение событий в хронологическом порядке является распространенным требованием. MongoDB позволяет легко сортировать результаты запросов по любому полю, включая даты.

Чтобы отсортировать документы, добавьте метод .sort() к запросу find(). Метод sort() принимает документ, который указывает поле для сортировки и порядок сортировки. Значение 1 указывает на порядок по возрастанию (от ранних к поздним), а -1 — на порядок по убыванию (от поздних к ранним).

Давайте получим все события, отсортированные по их date в порядке возрастания.

db.events.find().sort({ date: 1 })

Это выведет события от "Winter Workshop" (самое раннее) до "Summer Conference" (самое позднее). Документы без поля date будут отсортированы первыми, если они включены в запрос.

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

db.events.find().sort({ date: -1 })

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

db.events.find({ status: { $ne: "Archived" } }).sort({ date: 1 })

Вывод покажет неархивированные события в хронологическом порядке.

[
  {
    _id: ObjectId("..."),
    event_name: 'System Maintenance',
    timestamp: ISODate("...")
  },
  {
    _id: ObjectId("..."),
    event_name: 'Project Deadline',
    timestamp: ISODate('2024-06-15T18:00:00.000Z')
  },
  {
    _id: ObjectId("..."),
    event_name: 'Summer Conference',
    date: ISODate('2024-07-15T09:00:00.000Z')
  },
  {
    _id: ObjectId("..."),
    event_name: 'Conference',
    date: ISODate('2024-09-01T10:00:00.000Z'),
    status: 'Rescheduled'
  }
]

Сортировка — это важный инструмент для осмысленного представления данных, упорядоченных по времени. Когда вы закончите, вы можете выйти из оболочки MongoDB, набрав exit или нажав Ctrl+D.

Резюме

В этой лабораторной работе вы изучили основные методы работы с датами в MongoDB. Вы начали с вставки документов со значениями дат в различных форматах. Затем вы практиковались в запросе документов на основе диапазонов дат с использованием операторов сравнения. После этого вы изучили фреймворк агрегации для форматирования полей дат с целью улучшения читаемости. Вы также узнали, как обновлять поля дат и добавлять временные метки модификации. Наконец, вы освоили сортировку коллекций по дате для представления данных в хронологическом порядке. Эти навыки необходимы любому разработчику, работающему с данными, основанными на времени, в MongoDB.