Nodejs mongoose问题,能否使用model的virtual属性作为查询条件?以及该例应该怎么查询?
Nodejs mongoose问题,能否使用model的virtual属性作为查询条件?以及该例应该怎么查询?
我使用了mongoose和moment模块 需要查询出occur_time end_time时间区间和 from to 时间区间有交集的RiskEvent, 其中end_time是model的virtual属性,根据两个属性计算出来的, 不知下面的查询对不对,运行查询不出结果, node新手,还不会调试。。。 另外怎么提高查询速度?这个索引该怎么建,我主要是根据** 给定的时间区间 和 bussiness ** 查询
** /model/risk_event.js **
var RiskEventSchema = new Schema({
occur_time: {type: Date},
duration_time: {type: Number},
bussiness: {type: String},
comment: {type: String}
});
RiskEventSchema.virtual(‘end_time’).get(function(){
return moment(this.occur_time).add(‘minutes’, this.duration_time);
});
RiskEventSchema.index({occur_time: 1});
mongoose.model(‘RiskEvent’, RiskEventSchema);
** /proxy/risk_events.js **
exports.getRiskEventsByOccurTime = function(from, to, callback){
RiskEvent.find({"$or": [{occur_time: {"$lte": moment(from, 'YYYY-MM-DD')},
end_time: {"$gt": moment(from, 'YYYY-MM-DD')}},
{occur_time: {"$lt": moment(to, 'YYYY-MM-DD').add('days',1)},
end_time: {"$gt": moment(to, 'YYYY-MM-DD').add('days',1)}},
{occur_time: {"$gte": moment(from, 'YYYY-MM-DD')},
end_time: {"$lt": moment(to, 'YYYY-MM-DD').add('days',1)}}]}, callback);
};
Nodejs Mongoose 问题:能否使用 model 的 virtual 属性作为查询条件?
在 Mongoose 中,virtual 属性并不是实际存储在数据库中的字段,因此不能直接用于查询。不过,你可以通过一些技巧来实现类似的功能。
示例代码及解释
首先,我们需要修改 RiskEvent
模型定义,并添加一个方法来处理查询逻辑。
修改模型定义
const mongoose = require('mongoose');
const moment = require('moment');
const Schema = mongoose.Schema;
// 定义 RiskEvent 模型
var RiskEventSchema = new Schema({
occur_time: { type: Date },
duration_time: { type: Number },
bussiness: { type: String },
comment: { type: String }
});
// 添加虚拟属性 end_time
RiskEventSchema.virtual('end_time').get(function() {
return moment(this.occur_time).add('minutes', this.duration_time);
});
// 索引 occur_time 字段
RiskEventSchema.index({ occur_time: 1 });
// 导出模型
module.exports = mongoose.model('RiskEvent', RiskEventSchema);
修改查询逻辑
由于 virtual 属性不能直接用于查询,我们可以创建一个辅助函数来构建查询条件。
const RiskEvent = require('../models/risk_event');
exports.getRiskEventsByOccurTime = function(from, to, business, callback) {
// 构建查询条件
const query = {
$and: [
{ occur_time: { $lte: moment(to) } },
{ end_time: { $gt: moment(from) } },
{ bussiness: business }
]
};
// 执行查询
RiskEvent.find(query, callback);
};
解释
- Virtual 属性:
end_time
是一个虚拟属性,它基于occur_time
和duration_time
计算得出。 - 查询条件: 在
getRiskEventsByOccurTime
函数中,我们构建了一个查询条件对象query
,确保occur_time
小于等于to
,end_time
大于from
,并且bussiness
匹配给定的值。 - 执行查询: 使用
RiskEvent.find(query, callback)
来执行查询操作。
提高查询速度
为了提高查询速度,可以考虑为以下字段创建索引:
occur_time
end_time
(虽然这是一个虚拟属性,但可以通过其他方式优化查询)
例如:
RiskEventSchema.index({ occur_time: 1 });
RiskEventSchema.index({ duration_time: 1 });
通过这些索引,查询操作将变得更加高效。
在 Mongoose 中,虚拟属性(Virtual Attributes)是无法直接用于数据库查询的。这是因为虚拟属性是在对象实例层面定义的,并没有存储在数据库中。但是,你可以通过中间件(如 pre
或 post
hooks)或者在查询前处理数据的方式来间接实现这一需求。
对于您的具体问题,由于 end_time
是一个虚拟属性,不能直接用作查询条件。解决方法之一是通过查询数据库中的实际字段来间接实现。例如,可以先查询满足部分条件的数据,然后在结果上进行过滤。
示例代码
首先,我们修改查询逻辑,只用 occur_time
和 duration_time
字段来进行查询,然后在获取到的结果上应用 end_time
的逻辑来过滤数据。
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const moment = require('moment');
// 定义模式
const RiskEventSchema = new Schema({
occur_time: { type: Date },
duration_time: { type: Number },
bussiness: { type: String },
comment: { type: String }
});
// 虚拟属性
RiskEventSchema.virtual('end_time').get(function () {
return moment(this.occur_time).add('minutes', this.duration_time);
});
RiskEventSchema.index({ occur_time: 1 });
const RiskEvent = mongoose.model('RiskEvent', RiskEventSchema);
// 查询函数
exports.getRiskEventsByOccurTime = async (from, to, business) => {
const fromMoment = moment(from, 'YYYY-MM-DD');
const toMoment = moment(to, 'YYYY-MM-DD').add('days', 1);
const riskEvents = await RiskEvent.find({
occur_time: { $lte: toMoment.toDate() },
bussiness: business
}).exec();
// 过滤出符合条件的事件
const filteredRiskEvents = riskEvents.filter(event => {
const eventEndTime = moment(event.occur_time).add('minutes', event.duration_time);
return eventEndTime > fromMoment && eventEndTime <= toMoment;
});
return filteredRiskEvents;
};
解释
- 虚拟属性:定义了一个
end_time
的虚拟属性,基于occur_time
和duration_time
计算。 - 查询:使用
find
方法查询数据库,仅依据occur_time
和bussiness
字段。 - 过滤:在得到的结果中进一步过滤出满足
end_time
条件的记录。
这种方式虽然绕过了直接使用虚拟属性,但依然能够实现您想要的功能。如果需要更高效的查询性能,考虑创建合适的索引或优化查询条件。