Mongoose实现虚拟字段查询的方法详解


Posted in Javascript onAugust 15, 2017

前言

不知道大家知不知道,mongoose为数据模型提供了虚拟属性, 借此可以更加一致地、方便地读写模型属性,类似于C#或Java中的访问器。 我们知道虚拟属性在Query阶段一定是查不到的,因为事实上MongoDB并没有存储这些属性。 但是否可以通过一个拦截器来实现虚拟属性的查询呢?

这个问题很有趣,而且在很多场景下都相当方便。例如:

  • 实现一个暴力的全文检索时,需要对多个字段匹配统一查询词,该查询词可抽象为虚拟属性;
  • 多处都需要进行同一个复杂条件的查询时,可以用虚拟属性封装该查询条件。

事实上,虚拟属性查询和虚拟属性读写都是为了代码复用。

Mongoose 中的 Hook

Mongoose Schema几乎所有静态方法和对象方法都添加了 .pre和.post钩子。 这些钩子其实就是函数钩子,采用hooks-js的实现。

来自官网的例子:

var hooks = require('hooks')
 , Document = require('./path/to/some/document/constructor');
// Add hooks' methods: `hook`, `pre`, and `post`
for (var k in hooks) {
 Document[k] = hooks[k];
}
// Define a new method that is able to invoke pre and post middleware
Document.hook('save', Document.prototype.save);

// 上述代码在mongoose中实现
/////////////////////////////////////////////////////////////////////
// 下面的代码则是mongoose提供的Hook API

// Define a middleware function to be invoked before 'save'
Document.pre('save', function validate(next) {
 // ...
});

Document.save()被调用时,上述validate函数就会被回调。

添加查询钩子

Mongoose没有对hooks-js进一步封装,这意味着我们不能对所有Query方法设置钩子, 只能一一枚举需要监视的方法。当然,这不影响我们进行代码复用。

// 设置 findOne 和 find 钩子
CompanySchema.pre('findOne', preFind).pre('find', preFind);

接下来便着手实现preFind函数。

实现虚拟查询

在钩子(preFind)中,我们可以更改查询条件借此实现虚拟查询。 值得注意的是,完全可控的Query意味着我们可以实现任何形式的虚拟查询。

 例如全文检索:

function preFind() {
 var word = this.getQuery().word;
 if(word === undefined) return;

 // 从真实的Query中删掉虚拟属性
 delete this._conditions.word;
 // 构造正则表达式
 var regex = new RegExp(word);
 // 全文检索
 this.where({ $or: [{ title: regex }, { content: regex }, { author: regex }] });
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript实现动态CSS换肤技术的脚本
Jun 29 Javascript
js bind 函数 使用闭包保存执行上下文
Dec 26 Javascript
Google的跟踪代码 动态加载js代码方法应用
Nov 12 Javascript
js对文章内容进行分页示例代码
Mar 05 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
Apr 30 Javascript
jquery attr方法获取input的checked属性问题
May 26 Javascript
JS获取CSS样式(style/getComputedStyle/currentStyle)
Jan 19 Javascript
jQuery实现立体式数字滚动条增加效果
Dec 21 Javascript
Bootstrap table表格简单操作
Feb 07 Javascript
关于定制FileField中的上传文件名称问题
Aug 22 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
Aug 27 Javascript
JS实现换肤功能的方法实例详解
Jan 30 Javascript
深入浅析Vue不同场景下组件间的数据交流
Aug 15 #Javascript
React应用中使用Bootstrap的方法
Aug 15 #Javascript
JavaScript函数中的this四种绑定形式
Aug 15 #Javascript
详解react使用react-bootstrap当轮子造车
Aug 15 #Javascript
JScript实现表格的简单操作
Aug 15 #Javascript
AngularJS日程表案例详解
Aug 15 #Javascript
jQuery实现菜单栏导航效果
Aug 15 #jQuery
You might like
php 删除记录同时删除图片文件的实现代码
2010/05/12 PHP
php中error与exception的区别及应用
2014/07/28 PHP
postfixadmin忘记密码后的修改密码方法详解
2016/07/20 PHP
PHP基于pdo的数据库操作类【可支持mysql、sqlserver及oracle】
2018/05/21 PHP
深入浅析安装PhpStorm并激活的步骤详解
2020/09/17 PHP
onpropertypchange
2006/07/01 Javascript
YUI 读码日记之 YAHOO.util.Dom - Part.1
2008/03/22 Javascript
几个比较经典常用的jQuery小技巧
2010/03/01 Javascript
jquery.validate使用攻略 第二部
2010/07/01 Javascript
利用JS自动打开页面上链接的实现代码
2011/09/25 Javascript
JS关闭窗口或JS关闭页面的几种代码分享
2013/10/25 Javascript
jquery数组封装使用方法分享(jquery数组遍历)
2014/03/25 Javascript
js实现百度联盟中一款不错的图片切换效果完整实例
2015/03/04 Javascript
JavaScript实现自动消除按钮功能的方法
2015/08/05 Javascript
Bootstrap基本样式学习笔记之表单(3)
2016/12/07 Javascript
javaScript生成支持中文带logo的二维码(jquery.qrcode.js)
2017/01/03 Javascript
Nodejs进阶之服务端字符编解码和乱码处理
2017/09/04 NodeJs
对VUE中的对象添加属性
2018/09/18 Javascript
linux 下以二进制的方式安装 nodejs
2020/02/12 NodeJs
js HTML DOM EventListener功能与用法实例分析
2020/04/27 Javascript
[04:45]上海特级锦标赛主赛事第三日TOP10
2016/03/05 DOTA
[57:22]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第五场
2018/04/10 DOTA
Tornado协程在python2.7如何返回值(实现方法)
2017/06/22 Python
Django rest framework实现分页的示例
2018/05/24 Python
在django view中给form传入参数的例子
2019/07/19 Python
Python使用type关键字创建类步骤详解
2019/07/23 Python
使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件及出现问题解决方法
2019/09/06 Python
新版Pycharm中Matplotlib不会弹出独立的显示窗口的问题
2020/06/02 Python
Selenium alert 弹窗处理的示例代码
2020/08/06 Python
铭立家具面试题
2012/12/06 面试题
设计总监岗位职责
2013/12/07 职场文书
护士自我评价范文
2014/01/25 职场文书
空中乘务员岗位职责
2014/03/08 职场文书
儿园租房协议书范本
2014/12/02 职场文书
中标通知书范本
2015/04/17 职场文书
关于Javascript闭包与应用的详解
2021/04/22 Javascript