问题 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"
    }
]

“司机”  - 包含所有驱动程序数据的数据收集

  [
    {
        "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": ""
            }
        ]
    }
]

这是迄今为止的过程:

每天司机都以“开始新路线”开始。在开始新路由之前,驱动程序必须先输入数据:

  1. driverid
  2. 日期
  3. 卡车

正确输入所有数据后,将开始启动新路线:

  1. 在集合中创建新对象 “路线” 
  2. 查询集合 “路由列表“为了 “天” + “卡车” 匹配并返回 “停止”
  3. “路由表” 数据进入 “路线” 采集

当司机继续他的每日停止/任务时 “路线” 集合将相应更新。

完成所有任务后,驱动程序将能够通过简单地将“状态”字段从“路径”集合中的“完成”更改为“活动”来完成路径处理。

这总结了一下。任何反馈,意见,评论,链接,优化策略都非常感谢。

在此先感谢您的时间。


12571
2018-06-11 19:48


起源



答案:


您将数据库模式看作是“经典”关系数据库模式。 Mongodb非常适合数据非规范化。我想当你显示路线时,你加载所有相关的客户,司机,卡车。

如果你想让你的系统真正快速,你可以将所有东西都嵌入到路线收集中。

所以我建议您对架构进行以下修改:

  1. 客户 - 原样
  2. 卡车 - 原样
  3. 司机 - 原样
  4. 路由表:

    嵌入有关客户的数据而不是参考。还嵌入卡车。在这种情况下,架构将是:

     {
         "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
             }
         }]
     }
    
  5. 路线:

    当驾驶员从路线列表开始新的路线复制路线时,另外嵌入了驾驶员信息:

     {
         //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"
         }]
     }
    

我猜你问自己,如果主要集合中的驱动程序,客户或其他非规范化数据发生了变化,该怎么办?是的,您需要更新其他集合中的所有非规范化数据。您可能需要更新数十亿个文档(取决于您的系统大小),这没关系。如果花费很多时间,你可以做异步。

以上数据结构有什么好处?

  1. 每个文档都包含您可能需要在应用程序中显示的所有数据。因此,例如,当您需要显示路线时,您不需要加载相关的客户,司机,卡车。
  2. 您可以对数据库进行任何困难的查询。例如,在您的模式中,您可以构建查询,该查询将返回包含名称=“Bill”的客户停止时停止的所有路由(您需要先按名称加载客户,获取ID,并在当前模式中按客户ID查找)。

您可能会问自己,在某些情况下您的数据可能会不同步,但要解决此问题,您只需构建一些单元测试,以确保正确更新您的denormolized数据。

从文档数据库的角度来看,希望以上将帮助您从非关系方面看世界。


13
2018-06-11 21:09



如果将客户或卡车或驾驶员信息更新到系统中,将会产生数据模糊性。请保留其他模型的ID。 - Love-Kesh


答案:


您将数据库模式看作是“经典”关系数据库模式。 Mongodb非常适合数据非规范化。我想当你显示路线时,你加载所有相关的客户,司机,卡车。

如果你想让你的系统真正快速,你可以将所有东西都嵌入到路线收集中。

所以我建议您对架构进行以下修改:

  1. 客户 - 原样
  2. 卡车 - 原样
  3. 司机 - 原样
  4. 路由表:

    嵌入有关客户的数据而不是参考。还嵌入卡车。在这种情况下,架构将是:

     {
         "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
             }
         }]
     }
    
  5. 路线:

    当驾驶员从路线列表开始新的路线复制路线时,另外嵌入了驾驶员信息:

     {
         //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"
         }]
     }
    

我猜你问自己,如果主要集合中的驱动程序,客户或其他非规范化数据发生了变化,该怎么办?是的,您需要更新其他集合中的所有非规范化数据。您可能需要更新数十亿个文档(取决于您的系统大小),这没关系。如果花费很多时间,你可以做异步。

以上数据结构有什么好处?

  1. 每个文档都包含您可能需要在应用程序中显示的所有数据。因此,例如,当您需要显示路线时,您不需要加载相关的客户,司机,卡车。
  2. 您可以对数据库进行任何困难的查询。例如,在您的模式中,您可以构建查询,该查询将返回包含名称=“Bill”的客户停止时停止的所有路由(您需要先按名称加载客户,获取ID,并在当前模式中按客户ID查找)。

您可能会问自己,在某些情况下您的数据可能会不同步,但要解决此问题,您只需构建一些单元测试,以确保正确更新您的denormolized数据。

从文档数据库的角度来看,希望以上将帮助您从非关系方面看世界。


13
2018-06-11 21:09



如果将客户或卡车或驾驶员信息更新到系统中,将会产生数据模糊性。请保留其他模型的ID。 - Love-Kesh