MongoDB:Mapreduce有必要吗?预订应用程序中日期的范围查询

时间:2014-06-25 08:41:50

标签: mongodb mapreduce

我的收藏品有以下简化(预订)架构:

{
    name: "room 1",
    from: ISODate("2014-06-10T12:00:00Z"),
    to: ISODate("2014-06-14T12:00:00Z")
 },
 {
    name: "room 1",
    from: ISODate("2014-06-25T12:00:00Z"),
    to: ISODate("2014-06-27T12:00:00Z")
 },
 {
    name: "room 2",
    from: ISODate("2014-06-12T12:00:00Z"),
    to: ISODate("2014-06-26T12:00:00Z")
 }

如果某个房间在给定范围内可用,我想询问一下。例如,我想知道是否

  • 房间1可从2014-06-11至2014-06-13
  • 获得
  • 房间1可在2014-06-13至2014-06-26
  • 房间1可于2014-06-15至2014-06-18

3 个答案:

答案 0 :(得分:1)

好的,让我们打破这个,有4个预订冲突范围:

  • 在此开始之前开始另一次预订,但结束也是在此预订结束之前
  • 另一个预订的开始是在此开始之后,结束是在此结束之后
  • 另一个预订的开始是在此开始之后,结束是在此结束之前
  • 其他预订的开始是在此开始之前和此结束之后

因此,您正在寻找可以找到所有这些范围的查询。

现在我设置了这个数据:

> db.rooms.find()
{ "_id" : ObjectId("53ad206e1d8f2d8351182830"), "id" : 1, "from" : ISODate("2014-06-26T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad276f1d8f2d8351182831"), "id" : 1, "from" : ISODate("2014-06-24T00:00:00Z"), "to" : ISODate("2014-07-01T00:00:00Z") }
{ "_id" : ObjectId("53ad28ad1d8f2d8351182832"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad28c61d8f2d8351182833"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-07-03T00:00:00Z") }
{ "_id" : ObjectId("53ad29971d8f2d8351182834"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-06-21T00:00:00Z") }

(第5个范围是测试人员,以确保查询不会返回随机结果)

然后我跑了:

> db.rooms.find({from:{$lte: ISODate('2014-06-30T00:00:00.000Z')}, to:{$gte: ISODate('2014-06-23T00:00:00.000Z')}})
{ "_id" : ObjectId("53ad206e1d8f2d8351182830"), "id" : 1, "from" : ISODate("2014-06-26T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad276f1d8f2d8351182831"), "id" : 1, "from" : ISODate("2014-06-24T00:00:00Z"), "to" : ISODate("2014-07-01T00:00:00Z") }
{ "_id" : ObjectId("53ad28ad1d8f2d8351182832"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-06-28T00:00:00Z") }
{ "_id" : ObjectId("53ad28c61d8f2d8351182833"), "id" : 1, "from" : ISODate("2014-06-20T00:00:00Z"), "to" : ISODate("2014-07-03T00:00:00Z") }

如果该查询返回,则会有预订,因此无法插入。

这应该涵盖我认为的所有基础,我有点睡眠被剥夺,所以我可能是错的。

答案 1 :(得分:0)

考虑到您的数据显示了预订房间的日期,并且您想查询某些日期范围,那么您必须确保这两个日期(对于您要检查可用性的日期)超出了"从"和"到"预订的房间,因为你必须运行一个查询,其中你的输入日期都小于"来自"日期或两者都大于"到"约会,你就是这样做的

db.room.find({
 $or:[
  {$and : [{from:{$gt:new Date("2014-06-11T00:00:00.000Z")}},{to:{$gt:new Date("2014-06-13T00:00:00.000Z")}}]},
  {$and : [{from:{$lt:new Date("2014-06-11T00:00:00.000Z")}},{to:{$lt:new Date("2014-06-13T00:00:00.000Z")}}]}
    ]
})

如果您想计算房间数,只需将.count()添加到上述查询中,如果您想查询特定房间,只需在上述查询中添加"name":"roomname"即可。

希望它有所帮助。

答案 2 :(得分:0)

您可以创建范围查询,以检查fromto是否在搜索日期内。此外,第三个用例是当搜索日期涵盖另外一个文档时。 from / to间隔。

我执行测试的集合如下所示:

> db.booking.find()
{ "_id" : ObjectId("53aa8d8cdfae7e8ccdd4b49d"), "name" : "room 1", "from" : ISODate("2014-06-10T12:00:00Z"), "to" : ISODate("2014-06-14T12:00:00Z") }
{ "_id" : ObjectId("53aa8da1dfae7e8ccdd4b49e"), "name" : "room 1", "from" : ISODate("2014-06-25T12:00:00Z"), "to" : ISODate("2014-06-27T12:00:00Z") }
{ "_id" : ObjectId("53aab77fe0cd5e6e1c56c08c"), "name" : "room 2", "from" : ISODate("2014-06-12T12:00:00Z"), "to" : ISODate("2014-06-26T12:00:00Z") }
{ "_id" : ObjectId("53ad1107d20cc7b2fe2df520"), "name" : "room 1", "from" : ISODate("2014-07-05T12:00:00Z"), "to" : ISODate("2014-07-07T12:00:00Z") }
{ "_id" : ObjectId("23ad1107d20cc7b2fe2df520"), "name" : "room 1", "from" : ISODate("2014-06-12T12:00:00Z"), "to" : ISODate("2014-06-26T12:00:00Z") }
>

以下是您可以执行的查询,以检查房间是否可用(返回值为0表示房间可用):

房间1可用于2014-06-11至2014-06-13

db.booking.count({
    name:"room 1",
    $or:[
        { 
              from:{$lte:new Date("2014-06-11T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-11T00:00:00.000Z")}
        },
        {
              from:{$lte:new Date("2014-06-13T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-13T00:00:00.000Z")}
       },
       {
              from:{$gte:new Date("2014-06-11T00:00:00.000Z")}, 
              to:{$lte:new Date("2014-06-13T00:00:00.000Z")}
       }
]})

房间1可用于2014-06-13至2014-06-26

db.booking.count({
    name:"room 1",
    $or:[
        { 
              from:{$lte:new Date("2014-06-13T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-13T00:00:00.000Z")}
        },
        {
              from:{$lte:new Date("2014-06-26T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-26T00:00:00.000Z")}
       },
       {
              from:{$gte:new Date("2014-06-13T00:00:00.000Z")}, 
              to:{$lte:new Date("2014-06-26T00:00:00.000Z")}
       }
]})

房间1可用于2014-06-15至2014-06-18

db.booking.count({
    name:"room 1",
    $or:[
        { 
              from:{$lte:new Date("2014-06-15T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-15T00:00:00.000Z")}
        },
        {
              from:{$lte:new Date("2014-06-18T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-06-18T00:00:00.000Z")}
       },
       {
              from:{$gte:new Date("2014-06-15T00:00:00.000Z")}, 
              to:{$lte:new Date("2014-06-18T00:00:00.000Z")}
       }
]})

房间1可用于2014-07-02至2014-07-09

db.booking.count({
    name:"room 1",
    $or:[
        { 
              from:{$lte:new Date("2014-07-02T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-07-02T00:00:00.000Z")}
        },
        {
              from:{$lte:new Date("2014-07-09T00:00:00.000Z")}, 
              to:{$gte:new Date("2014-07-09T00:00:00.000Z")}
       },
       {
              from:{$gte:new Date("2014-07-02T00:00:00.000Z")}, 
              to:{$lte:new Date("2014-07-09T00:00:00.000Z")}
       }
]})