论 如何把NoSQL用成RDBMS
好好的Mongodb,本来是一个非关系型数据库,楞是让我用成了强关系型,我也是很懵逼呀。到现在接手的一个项目(迄今为止仅有的一个项目)用的Mongodb作为后台,就是我们小程序的项目。
明天要考英语了,背单词是不可能背单词的,心里烦就回顾一下我是怎么在Nodejs里用Mongodb的吧。
本文中操作Mongodb使用的包为 mongoose
Mongodb直观感觉
Mongodb给我最直观的感觉就是像JSON,整个数据库就像是一个JS的对象一样,这无疑是一个极大的特色。我们可以操作使用条件查找、可以添加方法、可以添加对象、删除,一切就像是使用JS的Object一样方便,如果关系处理得当,性能也不会慢多少。
具体使用
数据表
这就是我说把Mongodb用成Mysql的地方,在这里我要先定义好一个数据表中每项数据的结构。每个结构都是从Mongoose.Schema
中 new
出来的对象。
1 | let user_info = new Schema({ |
这个例子可以清晰地看出我声明的结构的样子,像JSON一样。
注意到其中以一个比较特殊的对象 mongoose.Schema.ObjectId
。这一项是用来联查其他数据表中数据的,联查的结果会变成对象放在对应的位置,联查的命令下面再说。
但是我们现在仅仅是建立了一个数据表中的一行,那么这个数据表叫什么呢?在这里定义
1 | mongoose.connect(global.conf.mongodb.url, { config: { autoIndex: false } }); |
呵呵,直接就连数据库都连上了。后面那个自动索引,忘了从哪里看的了,说是作者都推荐关闭以提高性能。emmmmm既然这样你为啥要写呢。无论如何,自动索引也不知道他索的什么,干脆就关了吧,然后觉得需要查询的项自己写个手动索引。
上文中生成的数据表中的一项经过model()
这个方法添加到数据库中,这个函数有两个参数,一个是这个数据表叫啥,他会自动在Mongodb中自动创建一个对应的数据表,比如这个user_info
对应user_infos
没错,加了个s
(我绝对不会告诉你,当时眼瞎没看见,手动添加测试数据死活用不了的),这时候就要说说上面那个联查的ref:
是干什么用的了,他是告诉Mongoose,这个需要联查的数据表叫什么用的。
现在,我们就得到了一个可以操作的对象了。
数据表添加方法
在只有数据结构的时候,我们就可以给Schema
添加方法了:
1 | user_info.statics.find_openid = function(openid, callback) { |
通过statics
在里面添加一个方法。注意这时就不能用我熟悉的()=>{}
来声明函数了,一定要用function(){}
来声明函数,因为下面会用到this
,前者的this
作用域会继承之前的环境,这就没法用了。
在函数内部的this
就是是这个数据表了,他就是Model
类型,有查询之类的方法,随意使用。
当然在实例化之后我们也可以添加方法。准确的说是用函数包装数据表变成一个方法。
1 | let find_user_by_openid = (openid) => { |
这里脱裤子放屁机智的实例就是把上面的方法直接用了一下。交叉看一下应该差不多了吧。
数据表的操作
其实主要用到的就几个,更多的请看API-Model-MongooseDoc
Model.find()
1 | user.find({/*....*/}, (err,docs)=>{ |
第一个参数就是条件,{ name: 'john', age: { $gte: 18 }}
类似,可以查找范围,也可以或什么的,没用过,需要的话再取看官方文档。
之后是回调函数,也可以没有,最后使用.exec()
里面再给回调函数。
如果查询出点什么意外(不知道能出啥意外,没出过)err就会有值,后面可以使用
1 | if (err) console.error(err); |
后面那个就是查询结果了,是个数组,里面就是符合条件的项。使用for..of
一个一个取出食用。
Model.findById()
众所周知,Mongodb所有的项都会一个独一无二的ID,这就是根据Id找项用的。
第一个穿Id进去,后面回调同上。
这个API还可以加点简单操作的东西:
Model.findByIdAndDelete()
Model.findByIdAndRemove()
Model.findByIdAndUpdate()
这个有些不同,没用过,需要的自取文档食用
不过多解释。
Model.findOne()
根据条件找一个,找第一个(?应该是吧,没实验过)符合条件的。
同样可以跟And,同上,回调函数同上上。
new Model()
这就是添加记录了后面跟着和之前 Schema
定义的一样的数据结构进去就行了。
1 | let add_user = async(user_info) => { |
(不要问我为啥定义这么简单的函数,我乐意 (傲娇
记得调用save,要不就消失了,如果你的方法中有修改查询到的结果,也记得要保存一下。
populate() 联查
在NoSQl中使用联查是不好的习惯,这证明你的数据库设计有问题,需要改正。
1 | user.findById(user_id). |
path就是需要联查哪一项,后面是限制条件,比如不把哪些信息联查出来等。
如果不联查的话,取到哪里就只有一个mongoose.Schema.ObjectId
对象,现在就是个含有数据的项了。如果还想取id就用._id
。
2018-6-29更新
感谢高渐离同学,对我笔记中错别字,词语滥用,概念混淆做出指正。
有啥不会就百度。
db的一种写法:sql.js-Questionnaire_nodejs