V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
msmmbl
V2EX  ›  问与答

mongodb 中,甘特图时间冲突的检测

  •  
  •   msmmbl · 2021-05-26 09:56:31 +08:00 · 920 次点击
    这是一个创建于 1059 天前的主题,其中的信息可能已经有所发展或是发生改变。

    mongodb 中,使用这样的数据结构描述甘特图:

    [
        { person: "nameA", task: "taskA", from: Date('xxxx'), to: Date('yyyyy')}, 
        { person: "nameA", task: "taskB", from: Date('xxxx'), to: Date('yyyyy')},
        { person: "nameB", task: "taskA", from: Date('xxxx'), to: Date('yyyyy')},
        ...
    ]
    

    代表 person 在 from 到 to 的时间段做 task 。

    有一个约束条件是,person 在同一个时间段( from - to )不能同时在做两个不同的 task 。例如,在某个时间段,nameA 不能同时即在做 taskA,又在做 taskB 。

    因此,在插入或者修改数据的时候,可以简单的通过下面的语句检测数据库中已经是否有冲突记录

    model.findOne({ person: 'xxxx', task: 'yyyy', to: { $gte: newFrom }, from: { $lte: newEnd } })
    

    存在一个场景,person 比如因为请假或者什么其他原因,从时间 t 开始,他的所有任务都往后移动一天。可以这样更新:

    model.updateMany({ person: 'xxxx', from: { $gte: Date('tttt') }, { $set: { from: { $add: 86400000 }  }, { to: { $add: 86400000 }  }  })
    

    但是这样是没有检查上面说的约束条件的。应该怎么做呢?

    1. 单独一条一条更新记录,检测冲突,而不是像上面那样 updateMany
    2. 将修改的记录的时间段先放到到队列中,然后开启一个异步的任务检测冲突
    第 1 条附言  ·  2021-05-26 10:38:10 +08:00

    感谢@freeminder提醒,上面的场景有误,正确的是:

    由于有优先级更高的任务插入,导致某个任务需要延后一天。这个时候通过

    model.updateMany({ task: 'xxxx', from: { $gte: Date('tttt') }, { $set: { from: { $add: 86400000 }  }, { to: { $add: 86400000 }  }  })
    

    如下图所示,此时产生冲突。 1.png

    7 条回复    2021-05-27 16:10:33 +08:00
    freeminder
        1
    freeminder  
       2021-05-26 10:03:16 +08:00
    如果平移前就不存在时间重叠,平移后为什么会产生呢?
    msmmbl
        2
    msmmbl  
    OP
       2021-05-26 10:33:48 +08:00
    额,我头晕了。我错了。应该是这个场景:task 由于有优先级更高的任务插入,导致某个任务需要延后一天。像下面的图那样子。https://sm.ms/image/J6aZn1VsqQvMyXS
    clf
        3
    clf  
       2021-05-26 11:25:43 +08:00
    就按照你检查是否冲突的方式标记冲突的任务让配置甘特图的人来处理呗。

    如果只是一个人的话可以简单粗暴的直接让这个人所有的任务都延后一天。但两个人处理同一个任务的时候,会存在可以同时处理和不能同时处理的两种逻辑,而这两种逻辑的处理也会很麻烦。

    另外就是这个任务的所需的标准工时以及每个人的实际效率没有体现在数据库里,还有包括当前各个任务的进度等,如果有这些数据,可以考虑做成部分任务人定,定下后其他任务安排系统自动生成,弄个字段区分人定的和系统自动生成的数据,如果任务有人为调整,则重新生成非人为的部分。
    msmmbl
        4
    msmmbl  
    OP
       2021-05-26 11:44:45 +08:00
    @lychs1998 厉害了。确实后面还要考虑您说的“标准工时”“实际效率”这些。请问,对于“标记冲突的任务”,是在修改任务时候实时的去标记了,还是异步去处理的。
    clf
        5
    clf  
       2021-05-26 14:48:49 +08:00
    @msmmbl 在“产生冲突任务”的这一步操作的时候,就是你例子里插入一个任务的时候,返回会冲突的任务,让管理员先去调整完这些任务后,才能完成插入操作,只要插入会产生冲突,就不能完成插入操作。

    这样的好处是不会存在“插入了任务后不去修改那些冲突数据”的情况。(不过感觉也是有点麻烦。
    msmmbl
        6
    msmmbl  
    OP
       2021-05-27 15:54:06 +08:00
    @lychs1998 嗯,但是实际上,即使插入的时候,数据是不冲突的。但是当做了一次批量任务延期后,就会出现冲突了,后面还需要操作者微调下几个冲突的任务。所以我觉得从插入的地方去堵不是很合适。我做了一版在修改任意任务后,都去查找下这个任务的冲突项。查询数据库次数有点多,先线上跑一跑试试。
    clf
        7
    clf  
       2021-05-27 16:10:33 +08:00
    @msmmbl 前端有甘特图数据的时候可以前端监测冲突,前端处理完后,然后把“变动过”的数据发上来后,后端再去数据库检查传上来的数据有没有冲突。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1154 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 18:19 · PVG 02:19 · LAX 11:19 · JFK 14:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.