Как удалить объект, если вложенный объект соответствует условию в агрегации MongoDB - PullRequest
0 голосов
/ 14 июля 2020

У меня есть коллекция, содержащая данные о местах. На место может быть несколько бронирований. детали бронирования сохранены в другой коллекции. эти две коллекции, как показано ниже.

//place collection
{
    "_id" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
    "name" : "abc"
}
//booking collection
/* 1 */
{
    "_id" : ObjectId("5f0e0260cd2767d8b9d1da32"),
    "placeId" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
    "startDate" : ISODate("2020-07-25T00:00:00.000Z"),
    "endDate" : ISODate("2020-07-27T00:00:00.000Z")
}

/* 2 */
{
    "_id" : ObjectId("5f0e02e6cd2767d8b9d1dc38"),
    "placeId" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
    "startDate" : ISODate("2020-07-29T00:00:00.000Z"),
    "endDate" : ISODate("2020-07-30T00:00:00.000Z")
}

, поэтому мне нужно найти наличие места для указанной c даты. Итак, я попытался выполнить следующий запрос.

var date = ISODate("2020-07-25T00:00:00.000Z");
db.getCollection('place').aggregate([
{"$lookup":{"from":"booking","localField":"_id","foreignField":"placeId","as":"bookings"}},
{
   "$match":{
      "$or":[
         {"bookings.startDate":{"$gt":date}},
         {
            "$and":[
               {"bookings.startDate":{"$lte":date}},
               {"bookings.endDate":{"$lt":date}}
            ]
         }
      ]
   }
}
]);

Результат:

{
    "_id" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
    "name" : "abc",
    "bookings" : [ 
        {
            "_id" : ObjectId("5f0e0260cd2767d8b9d1da32"),
            "placeId" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
            "startDate" : ISODate("2020-07-25T00:00:00.000Z"),
            "endDate" : ISODate("2020-07-27T00:00:00.000Z")
        }, 
        {
            "_id" : ObjectId("5f0e02e6cd2767d8b9d1dc38"),
            "placeId" : ObjectId("5f0e01f3cd2767d8b9d1d884"),
            "startDate" : ISODate("2020-07-29T00:00:00.000Z"),
            "endDate" : ISODate("2020-07-30T00:00:00.000Z")
        }
    ]
}

в основном, если это определенное c место недоступно для даты, тогда результат не должен прийти. Но здесь, для этого места есть несколько бронирований, критериям соответствия соответствует только одно бронирование. поэтому мне нужно удалить весь результат, если данные о бронировании соответствуют критериям. Как я могу это сделать?

Я пробовал запрос с условием $not.

var date = ISODate("2020-07-28T00:00:00.000Z");
db.getCollection('place').aggregate([
{"$lookup":{"from":"booking","localField":"_id","foreignField":"placeId","as":"bookings"}},
{
   "$match":{
      "$or":[
         {"bookings.startDate":{"$not":{"$gt":date}}},
         { 
            "$and":[
               {"bookings.startDate":{"$not":{"$lte":date}}},
               {"bookings.endDate":{"$not":{"$lt":date}}}
            ]
         }
      ]
   }
}
]);

Это работает с датами 25, 26, 27 числа. но для 28 место должно быть доступно, но это не дает результата.

1 Ответ

0 голосов
/ 15 июля 2020

Я решил эту проблему с помощью конвейера поиска следующим образом.

var date = ISODate('2020-07-28T00:00:00.000Z');
db.getCollection('place').aggregate([
{'$lookup':{
    'from':'booking',
    'let':{'place':'$_id','checkingDate':date},
    'pipeline': [{ '$match':{ 
                    '$expr':{
                        '$and':[
                            {'$eq':['$placeId','$$place']},
                            {'$not':{'$gt':['$startDate','$$checkingDate']}},
                            {'$not':{'$lt':['$endDate','$$checkingDate']}}
                         ]}}}
    ],
    'as':'bookings'
    }
}
,
{'$match':{'bookings':{ '$exists': 'true','$size': 0}}}
]);
...