Структура базы данных MongoDB и рекомендации по лучшей практике

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

Вот упрощенная версия моей структуры MongoDB:

База данных

Коллекции:

"клиенты" - сбор данных, содержащий все данные клиента.

  [
    {
        "cust_id": "1001",
        "name": "Customer 1",
        "address": "123 Fake St",
        "city": "Boston"
    },
    {
        "cust_id": "1002",
        "name": "Customer 2",
        "address": "123 Real St",
        "city": "Boston"
        },
    {
        "cust_id": "1003",
        "name": "Customer 3",
        "address": "12 Elm St",
        "city": "Boston"
    },
    {
        "cust_id": "1004",
        "name": "Customer 4",
        "address": "16 Union St",
        "city": "Boston"
        },
    {
        "cust_id": "1005",
        "name": "Customer 5",
        "address": "13 Massachusetts Ave",
        "city": "Boston"
    }, { ... }, { ... }, ...
]

"грузовики" - сбор данных, содержащий все данные грузовика.

[
    {
        "truckid": "21",
        "type": "Refuse",
        "year": "2011",
        "make": "Mack",
        "model": "TerraPro Cabover",
        "body": "Mcneilus Rear Loader XC",
        "capacity": "25 cubic yards"
    },
    {
        "truckid": "22",
        "type": "Refuse",
        "year": "2009",
        "make": "Mack",
        "model": "TerraPro Cabover",
        "body": "Mcneilus Rear Loader XC",
        "capacity": "25 cubic yards"
    },
    {
        "truckid": "12",
        "type": "Dump",
        "year": "2006",
        "make": "Chevrolet",
        "model": "C3500 HD",
        "body": "Rugby Hydraulic Dump",
        "capacity": "15 cubic yards"
    }
]

"drivers" - сбор данных, содержащий все данные драйвера.

  [
    {
        "driverid": "1234",
        "name": "John Doe"
    },
    {
        "driverid": "4321",
        "name": "Jack Smith"
    },
    {
        "driverid": "3421",
        "name": "Don Johnson"
    }
]

"списки маршрутов" - сбор данных, содержащий все предопределенные списки маршрутов.

   [
    {
        "route_name": "monday_1",
        "day": "monday",
        "truck": "21",
        "stops": [
            {
                "cust_id": "1001"
            },
            {
                "cust_id": "1010"
            },
            {
                "cust_id": "1002"
            }
        ]
    },
    {
        "route_name": "friday_1",
        "day": "friday",
        "truck": "12",
        "stops": [
            {
                "cust_id": "1003"
            },
            {
                "cust_id": "1004"
            },
            {
                "cust_id": "1012"
            }
        ]
    }
]

"маршруты" - сбор данных, содержащий данные для всех активных и завершенных маршрутов.

[
    {
        "routeid": "1",
        "route_name": "monday1",
        "start_time": "04:31 AM",
        "status": "active",
        "stops": [
            {
                "customerid": "1001",
                "status": "complete",
                "start_time": "04:45 AM",
                "finish_time": "04:48 AM",
                "elapsed_time": "3"
            },
            {
                "customerid": "1010",
                "status": "complete",
                "start_time": "04:50 AM",
                "finish_time": "04:52 AM",
                "elapsed_time": "2"
            },
            {
                "customerid": "1002",
                "status": "incomplete",
                "start_time": "",
                "finish_time": "",
                "elapsed_time": ""
            },
            {
                "customerid": "1005",
                "status": "incomplete",
                "start_time": "",
                "finish_time": "",
                "elapsed_time": ""
            }
        ]
    }
]

Вот такой процесс:

Каждый день драйверы начинаются с "Запуск нового маршрута". Перед запуском нового маршрута драйверы должны сначала ввести данные:

  • driverid
  • Дата
  • грузовик

Как только все данные будут введены правильно, начнется "Начать новый маршрут":

  • Создать новый объект в коллекции "маршруты"
  • Коллекция запросов "списки маршрутов" для "день" + "грузовик" соответствует и возвращает "останавливается"
  • Вставить "списки маршрутов в " маршруты

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

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

Что о суммирует его. Любые отзывы, мнения, комментарии, ссылки, тактика оптимизации приветствуются.

Заранее благодарим за ваше время.

Ответ 1

Схема базы данных выглядит как "классическая" схема реляционной базы данных. Mongodb хорошо подходит для денормализации данных. Я думаю, при отображении маршрутов вы загружаете всех связанных клиентов, водителей, грузовиков.

Если вы хотите сделать вашу систему очень быстрой, вы можете вставить все в сборку маршрутов.

Поэтому я предлагаю следующие модификации вашей схемы:

  • клиенты - как есть
  • грузовики - как есть
  • драйверы - как есть
  • маршрутный список:

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

     {
         "route_name": "monday_1",
         "day": "monday",
         "truck": {
             _id = 1,
             // here will be all truck data
         },
         "stops": [{
             "customer": {
                 _id = 1,
                 //here will be all customer data
             }
         }, {
             "customer": {
                 _id = 2,
                 //here will be all customer data
             }
         }]
     }
    
  • маршруты:

    Когда драйвер начинает новый маршрут маршрутизации маршрута из списка маршрутов и дополнительно вставляет информацию о драйвере:

     {
         //copy all route-list data (just make new id for the current route and leave reference to routes-list. In this case you will able to sync route with route-list.)
         "_id": "1",
         route_list_id: 1,
         "start_time": "04:31 AM",
         "status": "active",
         driver: {
             //embedd all driver data here
         },
         "stops": [{
             "customer": {
                 //all customer data
             },
             "status": "complete",
             "start_time": "04:45 AM",
             "finish_time": "04:48 AM",
             "elapsed_time": "3"
         }]
     }
    

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

Что улучшает структуру данных?

  • Каждый документ содержит все данные, которые могут отображаться в приложении. Так, например, вам не нужны пользователи, связанные с нагрузкой, водитель, грузовик, когда вам нужны маршруты отображения.
  • Вы можете делать любые сложные запросы в своей базе данных. Например, в вашей схеме вы можете создать запрос, который будет возвращать все маршруты, которые содержат остановки в конце клиента с именем = "Билл" (вам нужно сначала загрузить клиента по имени, получить идентификатор и посмотреть идентификатор клиента в вашей текущей схеме).

Вероятно, вы спрашиваете себя, что ваши данные могут быть несинхронизированы в некоторых случаях, но для решения этого вам просто нужно создать несколько unit test, чтобы убедиться, что вы правильно обновили данные denormolized.

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