首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果与其他日期重叠,MongoDB查找日期范围

如果与其他日期重叠,MongoDB查找日期范围
EN

Stack Overflow用户
提问于 2014-11-11 23:53:27
回答 2查看 6.7K关注 0票数 7

我有许多文档,模式如下所示,每个文档都包含(开始日期、结束日期),如下面的模式所示。在保存新文档之前,是否有一种简单的方法可以知道新文档是否开始日期、结束日期将与以前保存的文档日期重叠?谢谢

代码语言:javascript
复制
{
    "title" : "",
    "owner" : "",
    "notes" : "",
    "startdate" : "",
    "enddate" : ""
}

以下是目前保存的唯一文档:

代码语言:javascript
复制
Document.(anonymous function) {_id: "FADnPAxRu4Ps5hkLz", 
   title: "Round A", 
   customerid: "QDGvBQhS6vYgZtnRr", 
   startdate: "11/21/2014 7:25 AM"…}
_id: "FADnPAxRu4Ps5hkLz"customerid: "QDGvBQhS6vYgZtnRr"
enddate: "11/30/2014 6:09 AM"
startdate: "11/21/2014 7:25 AM"
title: "Round A"__proto__: Document.(anonymous function)

当我尝试对上面的文档执行以下任何查询时,它都不会返回任何内容,尽管这里有明显的重叠。

代码语言:javascript
复制
db.Projects.find({'startdate': {$lt: '11/25/2014 6:26 PM'}, 'enddate': {$gt: '11/19/2014 6:26 PM'}}, {sort:{time: -1}});

db.Projects.find({'startdate': {$lt: '11/30/2014 6:26 PM'}, 'enddate': {$gt: '11/21/2014 6:26 PM'}}, {sort:{time: -1}});
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-11-12 01:20:03

下面的图可以用这4种情况说明时间重叠,其中S/E是新文档的开始/结束日期,而S'/E‘是任何现有文档的开始日期/结束日期:

代码语言:javascript
复制
  S'                  E' 
  |-------------------|

   S                E 
   |****************|

S'          E' 
|-----------|

      S'          E' 
      |-----------|

              S'          E' 
              |-----------|

4例出现S'<EE'>S。查找所有重叠时间的文档的查询可以是:

代码语言:javascript
复制
db.collection.find({"startdate": {"$lt": E}, "enddate": {"$gt": S}})

编辑:

开始日期和结束日期是字符串格式的,而不是按词汇顺序排列的,因此不能使用"$gt“和"$lt”进行比较。您应该将它们转换为日期类型:

代码语言:javascript
复制
db.collection.find().forEach(
  function (e) {
    // convert date if it is a string
    if (typeof e.startdate === 'string') {
       e.startdate = new Date(e.startdate);
    }
    if (typeof e.enddate === 'string') {
       e.enddate = new Date(e.enddate);
    } 
    // save the updated document
    db.collection.save(e);
  }
)

最后的查询是:

代码语言:javascript
复制
db.collection.find({"startdate": {"$lt": new Date("E")}, "enddate": {"$gt": new Date("S")}})
票数 41
EN

Stack Overflow用户

发布于 2022-04-09 17:49:46

在被接受的答案的帮助下,我能够将所有四个案例融合在一起,并想出了一个完美的解决方案。希望它能帮到别人。

代码语言:javascript
复制
     S                E 
     |****************|
  S1                     E1
  |----------------------|
       S2        E2
       |----------|
 S3          E3
 |-----------|
              S4           E4
              |-------------|

案例1:间隔完全涵盖开始日期和结束日期

代码语言:javascript
复制
{ "startDate": { $lte: moment(S1).toDate() } }
{ "endDate": { $gte: moment(E1).toDate() } }

案例2:间隔完全在开始日期和结束日期内。

代码语言:javascript
复制
{ "startDate": { $gte: moment(S2).toDate() } }
{ "endDate": { $lte: moment(E2).toDate() } }

案例3:开始日期在间隔之外,结束日期在间隔内。

代码语言:javascript
复制
{ "endDate": { $gte: moment(S3).toDate() } }
{ "endDate": { $lte: moment(E3).toDate() } }

案例4:开始日期在间隔内,结束日期在间隔之外。

代码语言:javascript
复制
{ "startDate": { $gte: moment(S4).toDate() } }
{ "startDate": { $lte: moment(E4).toDate() } }

将这四种情况与“$and”和“$or”结合起来,就可以得到至少满足一种情况的数据。

代码语言:javascript
复制
const query = {};
const datePipeArray = [];
datePipeArray.push({ "$and":[
    { "startDate": { $gte: moment(queryStartDate).toDate() } },
    { "endDate": { $lte: moment(queryEndDate).toDate() } }
]});
datePipeArray.push({ "$and":[
    { "endDate": { $gte: moment(queryStartDate).toDate() } },
    { "endDate": { $lte: moment(queryEndDate).toDate() } }
]});
datePipeArray.push({ "$and":[
    { "startDate": { $gte: moment(queryStartDate).toDate() } },
    { "startDate": { $lte: moment(queryEndDate).toDate() } }
]});
datePipeArray.push({ "$and":[
    { "startDate": { $lte: moment(queryStartDate).toDate() } },
    { "endDate": { $gte: moment(queryEndDate).toDate() } }
]});
query["$or"] = datePipeArray;
db.calendar.find(query)

P.S:时刻是可选的

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26876803

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档