之前写的用 koa 开发 REST API,有提到过这个总让我想起加拿大鹅的中间件,索性好好学习一下。
准备工作
安装好 mongodb
,并新建一个数据库 testdb
新建一个工程,并初始化 npm init
安装 mongoose npm install mongoose
连接数据库
新建文件 serv.js,并输入一下代码
const mongoose = require("mongoose");
mongoose.connect("mongodb://127.0.0.1:27017/testdb");
let db = mongoose.connection;
db.on("error", function (error) {
console.log("fail--->" + error);
});
db.on("open", function () {
console.log("connected");
});
执行该文件 node serv.js,可以得到正确或错误的信息。
注意:如果你的 mongodb 版本较高,则会出现下面的警告
DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
解决办法,只要将
mongoose.connect("mongodb://127.0.0.1:27017/testdb");
改成
mongoose.connect("mongodb://127.0.0.1:27017/testdb", {useNewUrlParser: true});
即可。
Schema,Model和Entity
Scheme
可以理解为表结构,可以写成
const mongoose = require("mongoose");
let tempSchema = new mongoose.Schema({
name : {type:String},
age : {type:Number, default:0},
password: {type:String}
});
也可以写成
const mongoose = require('mongoose');
let tempSchema = new mongoose.Schema;
tempSchema.add({ name:'String', age:'Number', password:'String'});
Model
可以理解为数据库操作层,主要是对数据库层面的操作,其实就是对数据库中的集合(表)进行操作,比如结合刚才创建的 Schema,创建一个 Model
let db = mongoose.connect("mongodb://127.0.0.1:27017/testdb");
let tempModel = db.model("tempCollection", tempSchema);
需要注意,这里的 tempCollection 就是集合,如果该集合在数据库中存在,则将内容保存在里面,如果不存在,则会自动创建,并且再将内容保存在里面。
Entity
由 Model 创建的实体,同样结合上面的数据
var tempEntity = new tempModel({
name : "tcoder",
age : 100,
password: "123456"
});
console.log(tempEntity.name);
结果将得到 tcoder,Entity 使用 save 来保存数据,即 tempEntity.save()。
这样最终完整的代码
const mongoose = require("mongoose");
mongoose.connect("mongodb://127.0.0.1:27017/testdb", {useNewUrlParser: true});
let db = mongoose.connection;
let tempSchema = new mongoose.Schema({
name : {type:String},
age : {type:Number, default:0},
password: {type:String}
});
let tempModel = db.model("tempCollection", tempSchema);
let tempEntity = new tempModel({
name : "tcoder",
age : 1,
password: "123456"
});
tempEntity.save(function(error,data){
if(error){
console.log("error :" + error);
}else{
console.log(data);
}
});
执行代码,将会得到结果,进入到数据库中检查
>use testdb
switched to db testdb
>db.tempCollection.find()
{ "_id" : ObjectId("5b7d104487a4a795f30984ea"), "age" : 1, "name" : "tcoder", "password" : "123456", "__v" : 0 }
数据库的几个操作:增删改查
增
增加的操作,在前面的代码中已经实现,使用了 Entity 的 save 功能,即可将内容保存到 mongodb 中。
let tempEntity = new tempModel({
name : "tcoder",
age : 1,
password: "123456"
});
tempEntity.save(function(error,data){
if(error){
console.log("error :" + error);
}else{
console.log(data);
}
});
也可以用 Model 中的 create 功能来实现。
tempModel.create({ name:"newname", age:2}, function(error,data){
if(error) {
console.log(error);
} else {
console.log(data);
}
});
进入数据库中查询,可以发现该条数据也保存在数据库中了,如果同时增加多条信息,则可以通过数组方式增加,即
tempModel.create([{ name:"newname", age:2},{ name:"new2", age:30 }{ name:"test2", age:3 },{ name:"new3", age:4 }], function(error,data){
if(error) {
console.log(error);
} else {
console.log(data);
}
});
删除
和 sql 不一样,这里使用的是 remove 这个来进行资源的删除,其格式是 Model.remove(条件,回调);
let condition = {name : 'tcoder'};
tempModel.update(condition, function(error){
if(error) {
console.log(error);
} else {
console.log('Deleted');
}
});
运行将会提示删除,当集合中没有满足条件的数据时,还是会出现删除成功的提示。
修改/更新
使用 Model 的 update 进行更新,其格式是 Model.update(条件,更新对象,回调); 如找到 name 是 tcoder 的用户,将他的密码改成 654321,则代码如下
let condition = {name : 'tcoder'};
let updatecontent = {$set : {password :"654321"}};
tempModel.update(condition, updatecontent, function(error){
if(error) {
console.log(error);
} else {
console.log('Updated');
}
});
运行将会更新成功,因为是更新,它本身并没有创建数据的功能,所以当集合中没有满足条件的数据时,还是会出现更新完成的提醒。
查询
在 mongodb 中使用 find 命令来操作 db.tempCollection.find({}),其中 find 中可以有参数,如果没有写入参数,则表示查询所有的内容。而在 mongoose 中也是类似的概念,结合上面的 Model 进行操作。
tempModel.find({},function(error,data){
if(error) {
console.log("error :" + error);
} else {
console.log(data);
}
});
比如我们要查询 name 为 t 的用户,则在 find 中加入参数 {name:“t”} 即
tempModel.find({name:"t"},function(error,data){
if(error) {
console.log("error :" + error);
} else {
console.log(data);
}
});
运行,则得到结果是不存在的,因为的确是没有这条数据,将 t 改成 tcoder 即可得到数据。
注意:因为版本的问题,这里也会出现一个警告 DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.,更多看下面推荐阅读[1]。
有时候会对一些内容进行过滤,则格式为 Model.find(查询条件, 过滤条件, 回调);,比如下面一段代码
let filterCondition = {name:1}
tempModel.find({}, filterCondition, function(error,data){
console.log(data)
})
表示显示所有的数据,但只显示这些数据的 name 这一部分。因为 _id 是自动显示的,所以在结果中会出现 name 和 _id 两个。如果不想显示 _id,则将其设置为 0,即上面的条件可以更改为
let filterCondition = {name:1, _id:0}
即可只显示 name 的内容,需要注意的是,name 后面的数字 1 可以是任何一个非空的数字,但不可以是 0,如果是 0,则程序会报错 undefined。而一些数据没有一些键值,这个不会产生影响。
Model.findOne(查询条件, 回调) 则是查询第一条符合条件的数据
tempModel.findOne({age:1}, function(error, data){
console.log(data)
});
注意这里是第一条数据。
Model.findById(查询的_id, 回调) 是根据 _id 查询一条数据,用法如下
tempModel.findById('5b7d1f2a44e00f98705fda67', function(error, data){
console.log(data)
});
查询中的条件符号
$gt
大于 (>),格式为 {"age":{"$gt":1}}
$gte
大于等于 (>=),格式为 {"age":{"$gte":1}}
$lt
小于 (<),格式为 {"age":{"$lt":1}}
$lte
小于等于 (<=),格式为 {"age":{"$lte":1}}
{"age":{"$gt":1,"$lt":2}
则表示大于 1 小于 2
$ne
不等于 (!=),格式为 {name:{$ne:"tcoder"}}
和上面结合的多个条件则形如 {name:{$ne:"tcoder"}, age:{"$lte":1}}
$in
包含,格式为 {age:{$in:[1,2]}}
,表示包含 1 和 2 的,也可以是单独一个
$or
或者,满足一个条件即可,格式为 {"$or":[{"name":"tcoder"},{"age":1}]}
,这里的条件应该是数组形式
$exists
是否存在,格式为 {age:{$exists:true}}
,查看所有 age 存在的文档
所有的条件的查询格式如下
```
let condition = "待查询的状态"
tempModel.find(condition,function(error,data){
console.log(data)
});
```
游标
有时候查询结果的数量庞大,会需要对结果进行操作,这就要用到 limit 函数,格式为 Model.find(查询条件,过滤条件(可为 null ),{limit函数体}, 回调);
,比如要查询 10 条数据,则
tempModel.find({},null,{limit:10},function(error,data){
console.log(data);
});
和 limit 有同样作用的是 skip 函数,但不同的是,如果数量少于 skip 的数量,则不会显示内容
tempModel.find({},null,{skip:2},function(error,data){
console.log(data);
});
既然要处理多个结果中的一部分内容,势必就需要用到排序功能,sort 函数就是用来做排序的,格式和上面差不多,Model.find(查询条件,过滤条件,{sort函数体},回调)
,比如要按 age 升序排列
tempModel.find({},null,{sort:{age:1}},function(error,data){
console.log(data);
});
其中 1 表示是升序,-1 表示是降序。
mongoDB 操作
导入文件夹
mongorestore -d db_name 文件夹目录 // 文件夹里是文件
删除数据库
use db_name; // 选择要删除的数据库
db.dropDatabase()
推荐阅读
[1] https://github.com/Automattic/mongoose/issues/6880
[2] https://mongoosejs.com/docs/guide.html
> 可在 Twitter/X 上评论该篇文章或在下面留言(需要有 GitHub 账号)