从数组中查找 MongoDB 中仅一个日期的值

Find values from MongDB from an array for only one date

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

合作

我正在使用 $nin 函数。我有一个称为备用日期的选项,用户可以在其中输入另一个日期。我只想显示一天的空房情况,也就是说,如果第一个日期有空房,则搜索应该停止,否则应该继续到下一个日期,并在有空房的情况下给出结果。

此解决方案给出了所有给定日期的结果。

存储的数据是

{
    "_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"}

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

您将需要使用 $match operator to select document where the "Booked Date" is in your "date_list" then use the $project operator to return the the "Room No" and the corresponding list of "available date" using the $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 operator then $sort your result by "available_date" in ascending order. From there you will need to $group your document by "Room No" and use the $first 运算符将 "available_date" 数组或列表非规范化为 return 每个文档的第一个日期。

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

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'}]