mongoose学习笔记

连接

引入mongoose后然后用connection连接就okay了
推荐一个可视化数据库软件robomongo

1
2
3
4
5
6
7
8
var mongoose=require("mongoose");
var db=mongoose.connect("mongodb://127.0.0.1:27017/test")
db.connection.on("error",function(err){
console.log(err)
})
db.connection.on("open",function(){
console.log("okay")
})

Schema

schema就像一个模块的框架.查询根据这个模板框架来查询,插入也根据这个模板框架来插入.

1
2
3
4
5
6
7
8
var mongoose=require("mongoose")
var testSchema=new mongoose.Schema({
name :{type:String},//属性为name,类型为String
age:{type:Number,default:0},//属性为age 类型为Number 默认值为0
time:{type:Date,default:Date.now},
email:{type:String,default:""},
gender:{type:Boolean,default:true}
})

Model

有了模板框架现在就可以生成模板了
test1是数据库中的集合名称 如果test1已经存在 则会保存到其目录下 如果不存在则会创建test1集合保存数据

1
2
var db =mongoose.connect("mongodb://127.0.0.1:27017/test")
var testmodel=db.model("test1",testSchema)

Entity 实体

有了模板就可以生成实体
这里没有传入time 所以默认time是当前时间.现在仅仅生成实体了 但是,还没有保存,
我们可以console.log打印一下

1
2
3
4
5
6
7
8
var testEntity=new testmodel({
name:"soul",
age:18,
email:"admin@emufan.com",
gender:true
})
console.log(testEntity.time)//Fri Nov 06 2015 13:27:58 GMT+0800 (中国标准时间)
console.log(testEntity.age)//18

创建集合(保存)

直接调用save方法就可以保存了
返回的doc如下
其中_id是每次保存随机给你生成的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
testEntity.save(function(err,doc){
if(err) {
console.log(err)
}
console.log(doc)
})

doc

{ age: 18,
time: Fri Nov 06 2015 13:32:57 GMT+0800 (中国标准时间),
email: 'admin@emufan.com',
gender: true,
_id: 563c3b89458e8e6d8c7e2588,
name: 'soul',
__v: 0 }

在 robomongo中显示为

db

查询

记得我们生成了一个model 模板吗? 我们就根据这个模板去查询
类似于我们这个model就相当于test1集合的映像了
下面是查询test1集合中所有的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
testmodel.find({},function(err,doc){
console.log(doc)
})

doc

[ { age: 18,
time: Fri Nov 06 2015 13:32:37 GMT+0800 (中国标准时间),
email: 'admin@emufan.com',
gender: true,
__v: 0,
name: 'soul',
_id: 563c3b75258fa05d79c14df4 } ]

保存的两种方法

Model.create

我们用Model.create再保存一条数据,
上面我们说过了 testmodel就相当于test1集合 那么我们可以对这个集合做一些事情 如更新一条数据
返回的doc相信大家都很清楚了
保存多条数据则可以用[obj,obj,obj..]这样来存储

1
2
3
4
5
6
7
8
testmodel.create({
name:"soul二号",
age:18,
email:"emufan@qq.com",
gender:false
},function(err,doc){
console.log(doc)
})

entity.save

同时我们也可以先生成一个实体后再进行保存,
两种方法都可以实现保存。

1
2
3
4
5
6
7
8
9
10
11
12
13
var testEntity=new testmodel({
name:"soul",
age:18,
email:"admin@emufan.com",
gender:true
})

testEntity.save(function(err,doc){
if(err) {
console.log(err)
}
console.log(doc)
})

更新数据

更新数据可以用save 也可以用update

第一种方法用 model.update(find,value,callback)

1
2
3
testmodel.update({name:"soul二号"},{$set:{age:22}},function(err){
console.log("update success")
})

第二种方法用save
用find查询传递回来的是一个数组[obj,obj]
用findOne查询返回的是一个obj

1
2
3
4
5
6
7
testmodel.find({name:"soul二号"},function(err,doc){
console.log(doc)
doc[0].email="23333@qq.com";
doc[0].save(function(err,doc){
console.log(doc.email)
})
})

删除数据

model.remove(find,callback)
删除是把整个集合的数据都删除.、

1
2
3
4
testmodel.remove({name:"soul二号"},function(err){
if(err){console.log(err)}
console.log("删除成功")
})

简单查询

增加测试数据

在test数据库里面新增一个test2集合

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
var mongoose=require("mongoose");
var db=mongoose.connect("mongodb://127.0.0.1:27017/test")

var test2=new mongoose.Schema({
name:String,
age:Number,
email:{type:String,default:""}
})

var test2Model=db.model("test2",test2)

test2Model.create(
[
{ name:"test1", age:20 },
{ name:"test2", age:30 },
{ name:"test3", age:24 },
{ name:"test4", age:18 },
{ name:"test5", age:60 },
{ name:"test6", age:50, email:"t6@qq.com" },
{ name:"test7", age:40, email:"t7@163.com" },
{ name:"test8", age:27 },
{ name:"test9", age:27, email:"t9@yeah.net" },
{ name:"test10",age:65 }
]
,function(err,docs) {
if (err) {
console.log(err)
}
console.log(docs)
})

find 查询

model.find(Conditions,field,callback);

  • conditions:查询方法
  • field:返回过滤 需要返回的数据 可以不写
  • callback 回调函数

field可以选择性的返回属性 如果不写则返回全部属性 true则为返回 false则为不返回
下例会返回name和age 却不会返回_id

1
2
3
test2Model.find({},{name:true,_id:false,age:true},function(err,docs){
console.log(docs)
})

findOne查询

如果有多条相同数据只返回一个当前相同数据中的第一个数组
doc为obj而不是arr 因为只有一条数据

1
2
3
test2Model.findOne({age:27},function(err,doc){
console.log(doc)
})

findById查询

model.findById(obj.id,callback)
仅仅接受_id进行查询

1
2
3
test2Model.findById("563cbb7aec048261537b2530",function(err,doc){
console.log(doc)
})

高级查询

$gt、$lt简述

$gt(>)、$lt(<)、$lte(<=)、$gte(>=)
其中如果写多条则为且 比如
{age:{$gt:18,$lt:60}} //大于18 小于60

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
* $gt >
* $lt <
* $lte <=
* $gte >=
*
*
* */

test2Model.find({age:{$gt:18}},function(err,docs){
//查询所有age大于18的数据 返回arr
console.log(docs)
})

test2Model.find({age:{$lt:60}},function(err,docs){
//查询所有age小于60的数据 返回arr
console.log(docs)
})

test2Model.find({age:{$gt:18,$lt:60}},function(err,docs){
//查询所有age大于18且小于60的数据 返回arr
console.log(docs)
})

$ne

$ne类似于js中的!= 也就是非

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
*
* $ne(!=)
*
* */

test2Model.find({age:{$ne:24}},function(err,docs){
//查询age不等于24的所有数据
})

test2Model.find({name:{$ne:"tom"},age:{$gte:18}},function(err,docs){
//查询name不等于tom,age>=18的所有数据
})

$in

$in 包含,等于 用数组来做分组(或)

1
2
3
4
5
6
7
8
test2Model.find({age:{$in:20}},function(err,docs){
//查询age等于20的数据
})

test2Model.find({age:{$in:[20,30]},name:{$in:["test1","test2","test3"]}},function(err,docs){
console.log(docs)
//查询 age等于20或者30 ,name为 test1或者test2,test3 中的数据
})

$or

$or:或 满足一个值就可以返回

1
2
3
4
test2Model.find({$or:[{"name":"test1"},{"age":28}]},function(err,docs){
//查询name为test1 或 age为28的全部文档
console.log(docs)
})

$exists

$exists: 存在 存在为true 不存在为false

1
2
3
4
5
6
7
8
9
10
11
var test2Model=db.model("test2",test2)

test2Model.find({name:{$exists:true}},function(err,docs){
//查询所有name存在的文档
//console.log(docs)
})

test2Model.find({email:{$exists:false}},function(err,docs){
//查询email不存在的所有文档
//console.log(docs)
})

游标

限制返回数量

有时候查询数据量过大我们得限制一下返回数量
find(Conditions,fields,options,callback);
options:游标配置 如限制返回数量

{limit:4}//限制返回4条

1
2
3
4
test2Model.find({},null,{limit:4},function(err,docs){
//限制返回4条
console.log(docs)
})

skip 跳过返回数量

skip:设置返回下限
跳过匹配结果的前几条结果
如果返回结果达不到这个数值 则不返回;

1
2
3
4
test2Model.find({},null,{skip:4},function(err,docs){
//如果匹配的结果小于4个 则不返回任何结果
//跳过匹配结果的前两条 返回剩下的结果
})

sort排序

sort -1为降序,1为升序

1
2
3
4
5
6
7
8
9
10
/*
* sort -1为降序
* sort 1为升序
*
* */


test2Model.find({},null,{sort:{age:-1},limit:4},function(err,docs){
//按照年龄降序排序 同时限制返回数量为4
console.log(docs)
})

属性方法

ObjectId简述

存储在mongodb集合中的每个文档(document)都有一个默认的主键_id,这个主键名称是固定的,它可以是mongodb支持的任何数据类型,默认
ObjectId。该类型的值由系统自己生成,从某种意义上几乎不会重复,生成过程比较复杂,有兴趣的朋友可以查看源码。

使用过MySQL等关系型数据库的友友们都知道,主键都是设置成自增的。但在分布式环境下,这种方法就不可行了,会产生冲突。为此,MongoDB采用了
一个称之为ObjectId的类型来做主键。ObjectId是一个12字节的 BSON 类型字符串。按照字节顺序,一次代表:
4字节:UNIX时间戳
3字节:表示运行MongoDB的机器
2字节:表示生成此_id的进程
3字节:由一个随机数开始的计数器生成的值

1
2
var mongoose = require('mongoose');
var tSchema = new mongoose.Schema({}); //默认_id:ObjectId类型

添加属性

支持在同一集合中添加字段,如下例
第一次生成只有name和age这个属性 插入的数据也只有这两个属性
后来增加了一个email属性 后来插入的都具有email这个属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var mongoose=require("mongoose");
var db=mongoose.connect("mongodb://127.0.0.1:27017/test")

var tSchema=new mongoose.Schema({name:"String",age:"Number"});

var tModel=db.model("test3",tSchema)

tModel.create({name:"hello",age:20},function(err,docs){
console.log(docs)
})

tSchema.add({email:"String"})
tModel.create({name:"ss",age:25,email:"ww@ww.com"},function(err,docs){
console.log(docs)
})

实例方法

利用method来配置实例方法,每个生成的实例都具有这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
var mongoose = require('mongoose');

var saySchema = new mongoose.Schema({name : String});

saySchema.method('say', function () {
console.log('Trouble Is A Friend');
})

var say = mongoose.model('say', saySchema);

var lenka = new say();

lenka.say(); //Trouble Is A Friend

静态方法

静态方法不能在实例上用 如果生成一个实例
如 var ss=new TestModel({})
ss.findByName() // undefined is not a function
会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var mongoose = require("mongoose");

var db = mongoose.connect("mongodb://127.0.0.1:27017/test");

var TestSchema = new mongoose.Schema({
name : { type:String },
age : { type:Number, default:0 },
email: { type:String, default:"" },
time : { type:Date, default:Date.now }
});

TestSchema.static('findByName', function (name, callback) {
return this.find({ name: name }, callback);
});

var TestModel = db.model("test1", TestSchema );

TestModel.findByName('tom', function (err, docs) {
//docs所有名字叫tom的文档结果集
});

追加方法

Schema中以前定义的say方法是已经定义好了
如果要追加方法可以用Schema.methods.name来定义
这样在实例中就可以使用了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var mongoose = require("mongoose");

var db = mongoose.connect("mongodb://127.0.0.1:27017/test");

var TestSchema = new mongoose.Schema({
name : { type:String },
age : { type:Number, default:0 },
email: { type:String, default:"" },
time : { type:Date, default:Date.now }
});

TestSchema.methods.speak = function(){
console.log('我的名字叫'+this.name);
}

var TestModel = db.model('test1',TestSchema);

var TestEntity = new TestModel({name:'Lenka'});

TestEntity.speak();//我的名字叫Lenka