腊月的季节

express之mongoose操作

mongoose简介

在说MongoDB数据插入操作之前,我们先来简单了解下它的数据逻辑结构。
MongoDB的逻辑结构是一种层次结构,主要由:文档(document)、集合(collection)、数据库(database)这三部分组成的。
文档(document):由键/值对构成,像{a:1};{s:”abc”}等,它是MongoDB核心单元,MongoDB的文档(document),相当于关系数据库中的一行记录。
集合(Collection):多个文档组成一个集合(collection),相当于关系数据库的表。
数据库(database):多个集合(collection),逻辑上组织在一起,就是数据库(database)。
一个MongoDB实例支持多个数据库(database)。

使用mongoose

安装mongoose

1
npm install mongoose

引用mongoose

1
var mongoose = require("mongoose");

使用mongoose链接数据库

1
var db = mongoose("mongodb://user:pass@localhost:port/database");

示例:

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 (error) {
console.log(“数据库连接失败:” + error);
});
db.connection.on(“open”, function () {
console.log(“——数据库连接成功!——”);
});

mongodb基础

Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力
Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对
Entity : 由Model创建的实体,他的操作也会影响数据库
Schema —— 一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力,仅仅只是数据库模型在程序片段中的一种表现,可以说是数据属性模型(传统意义的表结构),又或着是“集合”的模型骨架。
定义

1
2
3
4
5
6
7
var mongoose = require("mongoose")
var TestSchema = new mongoose.Schema({
name : {type:String},
age : {type:Number,default:0},
time : {type:Date,default:Date.now},
emial : {type:String,default:''}
});

基本属性类型有:字符串、日期型、数值型、布尔型(Boolean)、null、数组、内嵌文档等

Model —— 由Schema构造生成的模型,除了Schema定义的数据库骨架以外,还具有数据库操作的行为,类似于管理数据库属性、行为的类。

1
2
3
var db = mongoose.connect("mongodb://127.0.0.1:27017/test");
// 通过Schema创建Model
var TestModel = db.model("test1", TestSchema);

数据库中的集合名称,当我们对其添加数据时如果test1已经存在,则会保存到其目录下,如果未存在,则会创建test1集合,然后在保存数据。

Entity —— 由Model创建的实体,使用save方法保存数据,Model和Entity都有能影响数据库的操作,但Model比Entity更具操作性。

1
2
3
4
5
6
7
var TestEntity = new TestModel({
name : "Lenka",
age : 36,
email : "lenka@qq.com"
});
console.log(TestEntity.name); // Lenka
console.log(TestEntity.age); // 36

mongoose-mongodb

1、定义模式(Schema)
每个模式映射mongoDB的一个集合(注意映射这个词,下面会讲为什么),它定义(只是定义,不是实现)这个集合里面文档的结构,就是定义这个文档有什么字段,字段类型是什么,字段默认值是什么等。除了定义结构外,还定义文档的实例方法,静态模型方法,复合索引,中间件等。

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

/*定义模式Student_Schema*/
var Student_Schema = new Schema({
name: String,
id: Number,
phone: String,
date: Date
}, {
versionKey: false
});

/*定义模型Student,注意数据库存的是students*/
mongoose.model("Student", Student_Schema);

{versionKey: false}是干嘛用?如果不加这个设置,我们通过mongoose第一次创建某个集合时,它会给这个集合设定一个versionKey属性值,这个属性值包含这个文档的内部版本,数据库中显示为_v,如图:
图片加载中...
通过{versionKey: false}可以配置这个参数,让数据库不再添加这个属性,格式是:new Schema({..}, { versionKey: false });
2、定义模型(Model)
模型用来实现我们定义的模式,调用mongoose.model来编译Schema得到Model。

1
2
/*定义模型Student,数据库存的是students*/
mongoose.model("Student", Student_Schema);

为什么上面我强调模式的映射,那是因为模式仅仅是和db中集合文档的结构相对应(映射),它并不直接在数据库中操作这个结构,模型才是直接与数据库打交道的存在,可以这么说:模式是定义结构,模型是实现操作。当我们使用mongoose.model(“Student”, Student_Schema)创建Student模型对数据进行操作时,数据库会寻找一个名字叫students集合接受Student模型的操作,特别需要注意的是:1.如果是增加(instance.save)操作时,数据库中没有这个集合,数据库会自动创建这个集合存储数据,这个集合产生规则为:把Model名字字母全部变小写和在后面加复数s。2.如果是删改查三个操作数据库中没有这个集合,那就是没有,删除空修改空返回空。

3、访问模型

1
var MyStudent = mongoose.model("Student");

到这里,已经基本完成了使用mongoose前提操作了。有没有觉得有点繁琐,其实我也觉得挺繁琐,幸运的是234可以一步创建:

1
2
3
4
5
6
var MyStudent = mongoose.model('Student',{
name: String,
id: Number,
phone: String,
date: Date
});

4、创建实例(instance)

1
2
3
4
5
6
var sam = new MyStudent({
name: "sam976",
id: 123,
phone: "18706888888",
date: Date.now()
});

一般只在save(增加)操作中需要。

模型的实例是集合中真实的数据,就是collection中的document,用mysql中的术语来说就是一条记录。模型在数据库中建好了集合和文档结构后,通过实例往里面添加真实的document。
捋一捋模式、模型、实例的关系:模式定义了操作和属性,这些操作和属性包括mongoose自带和自定义,而模型和实例可以对模式里面定义的属性和方法进行引用。模型是mongoose用来和数据库直接打交道的中介,实例是往数据库存的真实数据。模式并非必须,那为什么要分开模式和模型呢?我觉得是遵循了软件设计中“定义和实现分开”这个原则。有的文章说模式没有操作数据库的能力,模型才有,对这个观点,我觉得部分对,虽说模式不能直接操作数据库,但模式定义的方法可以被模型用来操作数据库。官方文档是这么说的:

model.find

Mongoose 模型提供了 find, findOne, 和 findById 方法用于文档查询。
Model.find(query, fields, options, callback)
// fields 和 options 都是可选参数
简单查询

1
Model.find({ 'csser.com': 5 }, function (err, docs) { // docs 是查询的结果数组 });

只查询指定键的结果

1
2
3
Model.find({}, ['first', 'last'], function (err, docs) {
// docs 此时只包含文档的部分键值
})

Model.findOne

与 Model.find 相同,但只返回单个文档

1
2
3
Model.findOne({ age: 5}, function (err, doc){
// doc 是单个文档
});

Model.findById

与 findOne 相同,但它接收文档的 _id 作为参数,返回单个文档。_id 可以是字符串或 ObjectId 对象。

1
2
3
Model.findById(obj._id, function (err, doc){
// doc 是单个文档
});

Model.count

返回符合条件的文档数

1
Model.count(conditions,callback)

Model.remove

删除符合的条件的文档

1
Model.remove(conditions,callback);

Model.distinct

查询符合条件的文档并返回根据键分组的结果.
Model.distinct(field,conditions,callback);

Model.where

当查询比较复杂时,用where:

1
2
3
4
5
6
7
8
9
10
Model
.where('age').gte(25)
.where('tags').in(['movie', 'music', 'art'])
.select('name', 'age', 'tags')
.skip(20)
.limit(10)
.asc('age')
.slaveOk()
.hint({ age: 1, name: 1 })
.run(callback);

Model.$where

有时我们需要在 mongodb 中使用 javascript 表达式进行查询,这时可以用 find({$where : javascript}) 方式,$where 是一种快捷方式,并支持链式调用查询。

1
Model.$where('this.firstname === this.lastname').exec(callback)

Model.update

使用 update 子句更新符合指定条件的文档,更新数据在发送到数据库服务器之前会改变模型的类型。

1
2
3
4
5
var conditions = { name: 'borne' }
, update = { $inc: { visits: 1 }}
, options = { multi: true };

Model.update(conditions, update, options, callback)

注意:为了向后兼容,所有顶级更新键如果不是原子操作命名的,会统一被按 $set 操作处理,例如:

1
2
3
4
5
6
var query = { name: 'borne' };
Model.update(query, { name: 'jason borne' }, options, callback)

// 会被这样发送到数据库服务器

Model.update(query, { $set: { name: 'jason borne' }}, options, callback)

查询API

如果不提供回调函数,所有这些方法都返回 Query 对象,它们都可以被再次修改(比如增加选项、键等),直到调用exec 方法。

1
2
3
4
5
6
7
8
9
var query = Model.find({});

query.where('field', 5);
query.limit(5);
query.skip(100);
query.exec(function (err, docs) {
// called when the `query.complete` or `query.error` are called
// internally
});

mongodb查询示例

1、db.user.find({});
2、db.user.find();
3、db.user.find({“name”:”user2”});
4、db.user.find({},{“name”:1,”password”:1});
5、db.user.find({},{“_id”:0});
6、查询条件
\$lt,\$lte,\$gt,\$gte,\$ne和<,<=,>,>=,!=是一一对应的,它们可以组合起来以查找一个范围内的值。
db.user.find({“age”:{“\$gte”:”20”,”\$lte”:”30”}});
db.user.find({“age”:{“\$gte”:20,”\$lte”:30}});
7、关联查询
db.user.find({“age”:{“\$in”:[20,25,26]}});
db.user.find({“age”:{“\$nin”:[20,25,26]}});
db.user.find({“age”:{“\$in”:[20,25,26]}});
用$or用于对多个键做or查询。
db.user.find({“\$or”:[{“age”:{“in”:[24,25,26]}},{“name”:”user3”}]});
8、特定类型的查询
null查询
db.user.update({“name”:”user2”},{\$set:{“sex”:null}});
db.user.find({“sex”:{“\$in”:[null]}});
正则表达式
db.user.find({“name”:/^user/});
数组查询
db.food.find({fruit:{\$all:[“apple”,”banana”]}});
db.food.find({“fruit.2”:”peach”});
\$size:查询指定长度的数组
db.food.find({“fruit”:{“\$size”:3}});

热评文章