Проверьте, не конфликтует ли диапазон дат с текущими документами MongoDB - PullRequest
0 голосов
/ 08 января 2020

Эта проблема имеет уровень сложности, и я не уверен, что лучшие методы, чтобы обойти.

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

Текущая функциональность просто берет самую позднюю дату окончания и служит на следующий день, она стала очень неточной и оставляет пробелы из-за отмен.

Пример. Пользователь ищет книгу на 10 дней в ближайшую доступную дату. В базе данных есть разрыв между 2 документами, которые подойдут этому пользователю, как мне запросить, чтобы проверить эту доступность?

Пример документа базы данных

{
    "start_date" : "2020-02-06T19:58:25.430Z",
    "end_date" : "2020-02-16T19:58:25.430Z"
},
{
    "start_date" : "2020-02-17T19:58:25.430Z",
    "end_date" : "2020-02-27T19:58:25.430Z"
},
{
    "start_date" : "2020-03-21T19:58:25.430Z",
    "end_date" : "2020-03-31T19:58:25.430Z"
},

Между вторым и третьим документом есть 2-недельный период, на который пользователь может претендовать. В настоящее время этот пользователь будет получать 2020-04-01 в качестве следующей доступности. Я хотел бы дать им возможность запросить дату отмены, отправив 2020-02-28 в качестве следующей доступности.

Как запросить у mongodb, чтобы узнать, есть ли доступность суммы x дней между диапазонами документов, до того, как по умолчанию будет задана самая поздняя дата окончания?

Ответы [ 2 ]

0 голосов
/ 17 января 2020

Я нашел решение после того, как оно в течение недели бродило в моем мозгу. Я не мог получить желаемый результат от запроса mongodb. Мне пришлось использовать javascript для сравнения некоторых документов. Не уверен в том, как продлится время выполнения, для меня это проблема для другого дня.

Я думал, что добавлю свое решение, когда наткнулся на свой собственный вопрос в поиске в Google за последнюю неделю.

//Find all the documents that have an end date greater than today, sort them based // on the start date to order documents
let sort = await db.collection(COLLECTION)
        .find({end_date : { $gte:new Date() }
      })
        .sort({start_date: 1 })
        .toArray();

//Set the nextDate variable
      let nextDate;
      if(sort.length >= 2){

//Javascript iteration if there are more than 2 documents returned from sorting

        for (let i = 0; i < sort.length; i++) {

          var startDate = Date.parse(sort[i].end_date);

//endDate is ternary incase the amount of documents is odd number

          var endDate = sort[i + 1] ? Date.parse(sort[i + 1].start_date) : new Date()
          var timeDiff = endDate - startDate;
          var daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24))


//Get the day difference between the date if the difference is greater than the //days alloted by user return the end date

          if(daysDiff > days) {
            return nextDate = sort[i].end_date
          } 

        }
//If no days have room for the decided days, return the last document in array

          return nextDate = sort[sort.length - 1].end_date

//If only one document, return end date

      } else if (sort.length === 1) {
        nextDate = sort[0].endDate

//No documents found, return todays date as it is available.
      } else {
        nextDate = new Date()
      }

На самом деле это прекрасно работает для того, что мне нужно. Надеюсь, получится хороший рефакторинг и его можно упростить.

0 голосов
/ 09 января 2020

Одна идея: создать отдельную коллекцию cancelled и переместить все отмененные встречи в эту коллекцию.

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

Иллюстрация:

> db.appointments.find()
{ "_id" : 0, "start" : 1, "end" : 2, "duration" : 1, "name": "John" }
{ "_id" : 1, "start" : 2, "end" : 4, "duration" : 2, "name": "Jane" }
{ "_id" : 2, "start" : 4, "end" : 5, "duration" : 1, "name": "Jack" }

// Jane cancelled the appt with _id 1
> c = db.appointments.findOne({_id: 1})
> db.cancelled.insert(c)
> db.appointments.deleteOne({_id: 1})

// current state of appointments
> db.appointments.find()
{ "_id" : 0, "start" : 1, "end" : 2, "duration" : 1, "name": "John" }
{ "_id" : 2, "start" : 4, "end" : 5, "duration" : 1, "name": "Jack" }

// Bob wanted to make an appointment spanning two "time units". Is it available?
> db.cancelled.findOne({duration: 2})
{ "_id" : 1, "start" : 2, "end" : 4, "duration" : 2, "name" : "Jane" }

// If Bob agreed to take over Jane's time slot
// reinsert the document from "cancelled" to "appointments", changing the name
> a = db.cancelled.findOne({duration: 2})
> a.name = "Bob"
> db.appointments.insert(a)
> db.cancelled.deleteOne({_id:1})

// end state of appointments
> db.appointments.find().sort({start: 1})
{ "_id" : 0, "start" : 1, "end" : 2, "duration" : 1, "name": "John" }
{ "_id" : 1, "start" : 2, "end" : 4, "duration" : 2, "name": "Bob" }
{ "_id" : 2, "start" : 4, "end" : 5, "duration" : 1, "name": "Jack" }

Обратите внимание, что на этой иллюстрации я также записал продолжительность каждой встречи поэтому их можно эффективно искать. Конечное состояние _id: 1 от Джейн было заменено Бобом, в коллекции cancelled ничего нет.

Чтобы убедиться, что обе коллекции appointments и cancelled обновлены правильно, вы можете захотеть использовать Транзакции , доступные с MongoDB 4.0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...