Node.js mongoose按照时间范围筛选查询结果

在项目中需要实现这样的功能:按照发布时间的范围筛选查询结果。Date posted(发布时间): Last 24hours(过去24小时), Last 3days(过去三天),Last 7days (过去七天) ,Others (其他时间) ,当用户点击不同的发布时间时,会对查询结果进行筛选并返回符合条件的结果列表。在此记录一下我的做法并整理相关知识点,如果有不正确的地方,欢迎指出。

用户点击相应的筛选条件链接时,将相应的数据存放在URL中。根据我的设计,几个条件分别对应的是“&postDate=1”,“&postDate=3” ,“&postDate=7”,“&postDate=others”。那么用户选择的内容可以根据req.query.postDate得知。如果用户不采用对发布时间的筛选,postDate === undefined, 这时需要展示所有时间的查询结果,并默认按照由新到旧的顺序排序。部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   // 按照发布时间筛选
var postDate = req.query.postDate;
var day;
var today = new Date();
if(postDate === undefined){
// 发布时间任意
postDate = {$lte: Date.now()};
} else if(postDate == 1){
// 过去24小时发布
day = today.setDate(today.getDate() - 1);
postDate = {$gte: day};
}else if (postDate == 3){
// 过去三天发布
day = today.setDate(today.getDate() - 3);
postDate = {$gte: day};
}else if (postDate == 7){
// 过去七天发布
day = today.setDate(today.getDate() - 7);
postDate = {$gte: day};
} else if (postDate == "others"){
// 七天以前发布
day = today.setDate(today.getDate() - 7);
postDate = {$lt: day};
}

// 省略其他不相关代码
Job.find({
date: postDate
}, null,
{
sort: {date: -1}
})

根据以上代码,回顾相关知识点:

(一) JavaScript的Date对象

以下内容参考MDN文档

(1)创建与设置日期

日期的创建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 没有输入参数,则按照当前的时间创建日期对象
var today = new Date();

// new Date(year, month, day, hours, minutes, seconds, milliseconds);
// 注意日期从0开始。如果数值不合理(如month=12, minutes=61等),则相关数值自动调整
var birthday = new Date(1995,7,23)

// new Date(value),value表示自1970年1月1日00:00:00 到日期的毫秒数
var date = new Date(1500000000000);

// new Date(dateString),表示日期的字符串值
var date = new Date("May 31,2019 18:00:00");

// 如果提供了至少两个参数,其余的参数均会默认设置为 1(如未指定 day)或者 0(如未指定 day 外的参数)

日期的设置:

1
2
3
4
5
6
7
// 设置为指定日期
var birthday=new Date();
birthday.setFullYear(1995,7,23);

// 将日期设置为几天前或几天后,如果加减后的日期月份或者年份也发生变化,会自动进行调整
var yesterday=new Date();
yesterday.setDate(yesterday.getDate()-1);

(2)Date对象常用方法

更全面的方法详见上述链接,以下列出几个最常用的:

Getter
Date.prototype.getDate() 返回日期对象在月份中的第几天(0-31)
Date.prototype.getDay() 返回日期对象在星期中的第几天(0-6)
Date.prototype.getFullYear() 返回日期对象的年份
Date.prototype.getMonth() 返回日期对象的月份(0-11)
Date.prototype.getMinutes() 返回日期对象的分钟(0-59)
Date.prototype.getHours() 返回日期对象的小时(0-23)
Setter
Date.prototype.setDate() 设置日期对象在月份中的第几天(0-31)
…… 与Getter对应

(二) MongoDB条件操作符

MongoDB的条件操作符用于比较并从MongoDB集合中获取数据。

(>)大于 $gt
(<)小于 $lt
(>=)大于等于 $gte
(<=)小于等于 $lte

对于日期而言,比如{$gt: new Date(2019,5,1)}代表大于2019年6月1日的日期(注意月份范围)。{$lte: new Date()}代表今天以及今天之前的日期。

(三)Mongoose的基本查询

参考mongoose文档

Model.find(query, fields, options, callback), 其中fields和options是可选的参数。如果进行排序如options参数参数sort: {date: -1},那就也要填写fields,没有field需填写null。如:Job.find({date: postDate}, null,{sort: {date: -1}})

以下是官方文档的查询示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// named john and at least 18
MyModel.find({ name: 'john', age: { $gte: 18 }});

// executes, passing results to callback
MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});

// executes, name LIKE john and only selecting the "name" and "friends" fields
MyModel.find({ name: /john/i }, 'name friends', function (err, docs) { })

// passing options
MyModel.find({ name: /john/i }, null, { skip: 10 })

// passing options and executes
MyModel.find({ name: /john/i }, null, { skip: 10 }, function (err, docs) {});

// executing a query explicitly
var query = MyModel.find({ name: /john/i }, null, { skip: 10 })
query.exec(function (err, docs) {});

// using the promise returned from executing a query
var query = MyModel.find({ name: /john/i }, null, { skip: 10 });
var promise = query.exec();
promise.addBack(function (err, docs) {});

Model.findOne() 和Model.find()类似,只不过返回的是单个结果; Model.findById()也返回单个文档,不过它是接收_id作为参数,这个参数可以是字符串,也可以是ObjectId对象,以下是Model.findById()的官网文档示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// find adventure by id and execute
Adventure.findById(id, function (err, adventure) {});

// same as above
Adventure.findById(id).exec(callback);

// select only the adventures name and length
Adventure.findById(id, 'name length', function (err, adventure) {});

// same as above
Adventure.findById(id, 'name length').exec(callback);

// include all properties except for `length`
Adventure.findById(id, '-length').exec(function (err, adventure) {});

// passing options (in this case return the raw js objects, not mongoose documents by passing `lean`
Adventure.findById(id, 'name', { lean: true }, function (err, doc) {});

// same as above
Adventure.findById(id, 'name').lean().exec(function (err, doc) {});