【问题标题】:Find values from MongDB from an array for only one date从数组中查找 MongoDB 中仅一个日期的值
【发布时间】:2015-11-17 00:37:01
【问题描述】:

我知道 SO 中有一个类似的问题,但我的问题与 Find values in mongdb 略有不同。我正在尝试一个酒店预订应用程序。在这里,我存储有关预订房间的日期的信息,这意味着房间在所有其他日期都可用。我正在与mongodbpython 合作。

我正在使用$nin 函数。我有一个称为备用日期的选项,用户可以在其中提供另一个日期。我只想显示一天的空房情况,即如果第一个日期有空房,那么搜索应该停止,如果没有的话,它应该继续到下一个日期,如果有的话给出结果。

这个解决方案给出了所有给定日期的结果。 solution of Find values in mongdb

存储的数据是

{
    "_id" : ObjectId("5645f0443f32df13e0dc786e"),
    "Booked Date" : ["28-9-2015","29-9-2015","1-10-2015"],
    "Room No.": "101"
},
{
    "_id" : ObjectId("5645f0c73f32df062064a0f6"),
    "Booked Date" : ["29-9-2015","1-10-2015"],
    "Room No.": "102"
},
{
    "_id" : ObjectId("5645f0c73f32df06205874f8"),
    "Booked Date" : ["29-9-2015","1-10-2015","2-10-2015"],
    "Room No.": "103"
},

我是这样查询的

db.booking.find({"Date": { '$nin':[Date]}},{"_id": False,"Booked Date": False})

这里我输入["1-10-2015","2-10-2015"]

所以当我得到结果时,我不知道房间在哪一天有空。

有什么办法可以解决这个问题。

当我运行这段代码时

db.booking.find({"Date": { '$nin':["1-10-2015","2-10-2015"]}},{"_id": False,"Booked Date": False})

我得到结果

{"Room No.": "101"}, 
{"Room No.": "102"}

但我不知道房间在哪一天有空。在上述情况下,它仅适用于2-10-2015

那么有没有办法说它在2-10-2015上可用。

另外一种情况:

db.booking.find({"Date": { '$nin':["1-10-2015","2-10-2015", "3-10-2015"]}},{"_id": False,"Booked Date": False})

这里可以在2-10-2015 & 3-10-2015 获得,但它应该只显示第一个可用日期,即2-10-2015

输出应该和上面一样:

{"Room No.": "101"},
{"Room No.": "102"}

【问题讨论】:

  • 您的问题难以理解,请出示预期结果。
  • @user3100115 请检查编辑
  • @TonyRoczz 我以为你需要第一个结果.. 但我想如果在那个日期有空的话,每个日期你只需要一个房间。对吗?
  • @TonyRoczz 如果是这样的话.. 我真的怀疑在 mongo 中可能有一个查询可以做到这一点.. 但你可以在你的 python 代码中反驳它.. 只需返回房间以及他们的日期可用.. 并剥离同一日期可用的房间.. :)
  • "Room No": 103 呢?结果应该是什么? 3-10-2015?对吗?

标签: python mongodb mongodb-query pymongo aggregation-framework


【解决方案1】:

您需要使用.aggregate() 方法。

您需要使用$match 运算符选择“预订日期”在您的“日期列表”中的文档,然后使用$project 运算符返回“房间号”和相应的“可用”列表日期”使用$setDifference 运算符。

那么您只需要处理剩下的工作客户端。

from pprint import pprint
date_list = ["1-10-2015","2-10-2015", "3-10-2015"]
cur = collection.aggregate([
    {"$match": {"Booked Date": {"$in": date_list}}}, 
    {"$project": {
        "Room No": 1, 
        "available_date": {
            "$setDifference": [date_list, "$Booked Date"]
        }
    }}
])

然后使用pprint.pprint打印结果:

pprint(list(cur))

产生:

[{'Room No': '101',
  '_id': ObjectId('5645f0443f32df13e0dc786e'),
  'available_date': ['2-10-2015', '3-10-2015']},
 {'Room No': '102',
  '_id': ObjectId('5645f0c73f32df062064a0f6'),
  'available_date': ['2-10-2015', '3-10-2015']},
 {'Room No': '103',
  '_id': ObjectId('5645f0c73f32df06205874f8'),
  'available_date': ['3-10-2015']}]

现在另一种效率较低的方法是,您可以使用$unwind 运算符对您的“available_date”数组或列表进行非规范化,然后使用$sort 按“available_date”升序排列您的结果。从那里您需要通过“房间号”$group 您的文档,并使用 $first 运算符返回每个文档的第一个日期。

如您所见,这给服务器带来了更多不必要的工作,因此不是一个好的解决方案。

cur = collection.aggregate([
    {"$match": {"Booked Date": {"$in": date_list}}},
    {"$project": {
        "Room No": 1, 
        "available_date": {
            "$setDifference": [date_list, "$Booked Date"]
        }
    }},
    {'$unwind': '$available_date'}, 
    {'$sort': {'avalable_date': 1}}, 
    {'$group': {
        '_id': '$Room No', 
        'available_date': {'$first': '$available_date'}
    }}
])
# pretty print the result
pprint(list(cur))

产量:

[{'_id': '102', 'available_date': '2-10-2015'},
 {'_id': '101', 'available_date': '2-10-2015'},
 {'_id': '103', 'available_date': '3-10-2015'}]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-07-18
    • 2023-02-09
    相关资源
    最近更新 更多