仅从一个数组中查找MongDB中的值只有一个日期

时间:2015-11-16 04:28:25

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

我知道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"}

1 个答案:

答案 0 :(得分:0)

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

您需要使用$match运算符选择“预订日期”在“date_list”中的文档,然后使用$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您的文档“Room No”,并使用$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'}]