MongoDB数据库结构和最佳实践帮助。

15

我正在为我们的垃圾收集公司开发路线跟踪/优化软件,希望大家对我的当前数据结构和情况给予一些反馈。

这是我 MongoDB 结构的简化版本:

数据库:data

集合:

"customers" - 包含所有客户数据的数据集合。

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

“trucks” - 包含所有卡车数据的数据集合。

[
    {
        "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-lists” - 包含所有预定路线列表的数据集合。

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

"routes" - 数据集合,包含所有活动和已完成路线的数据。

[
    {
        "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. date
  3. truck

一旦所有数据正确输入,就会开始“开始新路线”:

  1. 在集合"routes"中创建新对象
  2. 查询集合"route-lists"以匹配"day""truck",并返回"stops"
  3. "route-lists"数据插入到"routes"集合中

随着司机继续进行日常停车/任务,"routes"集合将相应更新。

完成所有任务后,司机将有能力通过在"routes"集合中将“状态”字段从“complete”更改为“active”来完成路线进程。

以上是全部内容。非常感谢您的时间,如有任何反馈、意见、评论、链接或优化策略都将不胜感激。

提前道谢。

1个回答

19

根据我的看法,你的数据库模式看起来像一个“经典”的关系型数据库模式。Mongodb非常适合数据去规范化。我猜当你展示路线时,你会加载所有相关的客户、司机和卡车。

如果你想让你的系统真正快速,你可以将所有内容嵌入到路线集合中。

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

  1. customers - 不变
  2. trucks - 不变
  3. drivers - 不变
  4. route-list:

    将有关客户的数据嵌入到停留点内,而不是引用。同时也要嵌入卡车信息,这样架构将会是:

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

    当司机开始新路线时,从路线列表中复制路线,并额外嵌入司机信息:

  6.  {
         //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查找您当前的模式)。

    也许你会想到你的数据可能在某些情况下不同步,但是为了解决这个问题,你只需要编写一些单元测试来确保你正确更新了你的非规范化数据。

    希望以上内容能够帮助您从非关系型数据库的角度看待世界。


如果客户、卡车或司机信息更新到系统中,将会产生数据的歧义。最好只保留其他模型的ID。 - Love-Kesh
1
@Love-Kesh 如果你的目标是这样的话,那么你应该使用关系型数据库。MongoDB明确不是一个关系型数据库,所以试图将关系模式强加于其上并没有什么意义,对吧? - Phillip Copley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接