Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何根据截止日期搜索mongodb?_Javascript_Node.js_Mongodb - Fatal编程技术网

Javascript 如何根据截止日期搜索mongodb?

Javascript 如何根据截止日期搜索mongodb?,javascript,node.js,mongodb,Javascript,Node.js,Mongodb,使用MERN stack构建租赁清单应用程序。我的上市模式如下: const listingShcema = new mongoose.Schema( { hostedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User', }, title: { type: String, required: true, }, description: {

使用MERN stack构建租赁清单应用程序。我的上市模式如下:

const listingShcema = new mongoose.Schema(
  {
    hostedBy: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User',
    },
    title: {
      type: String,
      required: true,
    },
    description: {
      type: String,
      required: true,
    },
    numberOfGuests: {
      type: String,
      required: true,
    },
    numberOfRooms: {
      type: String,
      required: true,
    },
    numberOfBeds: {
      type: String,
      required: true,
    },
    numberOfBaths: {
      type: String,
      required: true,
    },
    price: {
      type: String,
      requried: true,
    },
    location: {
      streetAddress: { type: String },
      city: { type: String },
      state: { type: String },
      postalCode: { type: String },
    },
    bookedDates: [
      {
        startDate: Date,
        endDate: Date,
      },
    ],
    imgUrls: [
      {
        type: String,
      },
    ],
    amenities: [
      {
        type: String,
      },
    ],
  },
  { timestamps: true }
);

现在,对用户搜索查询提供的所有内容运行查询相当容易,除了他们想要出租的日期。列表模型跟踪所有bookedDates。我希望能够在mongodb中搜索没有与用户搜索查询提供的日期匹配的bookedDates的列表(向用户显示可用列表)。我想不出一个办法来做这个??我认为只记录预订日期很容易,而不是从所有可用日期数组中删除预订日期。

直接在数据库中这样做有点尴尬,尤其是如果您只存储每个预订的
开始日期和
结束日期。例如,如果有人从1号到5号预订了一个列表-如果另一个用户从3号到7号搜索同一个列表,则该列表与保存的预订不匹配,但该列表仍不会被视为可用

我建议你再看一看你的模型,甚至可以把预定的日期分到他们自己的文件中

但是,根据您所拥有的,假设您将来不会预订太远,那么将
bookedDates
存储为平面阵列可能是值得的。因此,如果我们从1号到3号以及6号到8号预订了一个列表,那么您的阵列将如下所示:

bookedDates: [
    '2021-01-01',
    '2021-01-02',
    '2021-01-03',
    '2021-01-06',
    '2021-01-07',
    '2021-01-08'
]
然后,如果有人在2号和4号之间搜索列表,您会再次将这些日期分解为一个平面数组,然后您应该能够使用
$nin
操作符():

引用本页的相关部分:

如果字段包含数组,则$nin运算符将选择其字段包含数组的文档,该数组中没有与指定数组中的值相等的元素(例如,等等)

如果您有另一种方法过滤掉大部分列表,那么这显然是最有效的,因为您没有对数据库中的每个列表进行数组检查

您还必须通过删除过去的日期来保持
bookedDates
最新

另一个选项是只查询您的列表并在应用程序级别进行日期筛选,在这种情况下,您可能可以保留现有的
startDate
endDate
格式

扁平化日期更新

这样的办法应该行得通。我只是蛮力的-人们通常只会在几天内预订一个列表,所以你的循环会非常小。如果是一天,那里会有一些检查,以确保开始是在结束之前,但仅此而已

作为一种方法,您可以随时调用它,它将把两个日期分割成一个扁平的字符串数组,格式为
yyy-mm-dd
格式

function getFlattenedDatesAr(inputStart, inputEnd) {
    // convert to dates and make sure that start is before end
    let startDate = new Date(inputStart)
    let endDate = new Date(inputEnd)
    if(startDate > endDate) {
        let temp = startDate;
        startDate = endDate;
        endDate = temp;
    }

    // get our dates in yyyy-mm-dd format
    const startDateStr = startDate.toISOString().substr(0, 10)
    const endDateStr = endDate.toISOString().substr(0, 10)

    // check if they've only booked for one day
    if(startDateStr === endDateStr) {
        return [startDateStr];
        return; 
    }
    
    // fill our our dates array
    const bookedDates = [startDateStr]
    let currDate = startDate;
    while(true) {
        // NOTE: setDate returns a timestamp, not a Date
        const nextDateTS = currDate.setDate(currDate.getDate() + 1);
        
        // get our date string and add it to our bookedDates array
        currDate = new Date(nextDateTS)
        const currDateStr = currDate.toISOString().substr(0, 10);
        bookedDates.push(currDateStr);
        
        // if our string matches our end date, we're done
        if(currDateStr === endDateStr) {
            break
        }
    }
    return bookedDates
}


// assume these are the dates sent, in yyyy-mm-dd format
let inputStart = '2021-01-01'
let inputEnd = '2021-01-05'

const datesAr = getFlattenedDatesAr(inputStart, inputEnd)
console.log(datesAr);

您建议我如何获取介于两者之间的其他日期,即给定的两个期望开始日期和结束日期,以添加到BookEdates数组中?@stinny我添加了一个编辑来显示我将如何执行此操作
function getFlattenedDatesAr(inputStart, inputEnd) {
    // convert to dates and make sure that start is before end
    let startDate = new Date(inputStart)
    let endDate = new Date(inputEnd)
    if(startDate > endDate) {
        let temp = startDate;
        startDate = endDate;
        endDate = temp;
    }

    // get our dates in yyyy-mm-dd format
    const startDateStr = startDate.toISOString().substr(0, 10)
    const endDateStr = endDate.toISOString().substr(0, 10)

    // check if they've only booked for one day
    if(startDateStr === endDateStr) {
        return [startDateStr];
        return; 
    }
    
    // fill our our dates array
    const bookedDates = [startDateStr]
    let currDate = startDate;
    while(true) {
        // NOTE: setDate returns a timestamp, not a Date
        const nextDateTS = currDate.setDate(currDate.getDate() + 1);
        
        // get our date string and add it to our bookedDates array
        currDate = new Date(nextDateTS)
        const currDateStr = currDate.toISOString().substr(0, 10);
        bookedDates.push(currDateStr);
        
        // if our string matches our end date, we're done
        if(currDateStr === endDateStr) {
            break
        }
    }
    return bookedDates
}


// assume these are the dates sent, in yyyy-mm-dd format
let inputStart = '2021-01-01'
let inputEnd = '2021-01-05'

const datesAr = getFlattenedDatesAr(inputStart, inputEnd)
console.log(datesAr);