$ cnpm install mongoose -S
let mongoose = require("mongoose");
let db = mongoose.createConnection("mongodb://user:pass@ip:port/database",{ useNewUrlParser: true,useUnifiedTopology: true});
let mongoose = require('mongoose');
let connection = mongoose.createConnection("mongodb://127.0.0.1/zfpx",{ useNewUrlParser: true,useUnifiedTopology: true});
connection.on('error', function (error) {
console.log('数据库连接失败: ' + error);
});
connection.on('open', function (error) {
console.log('数据库连接成功');
});
var personSchema = new Schema({
name:String, //姓名
binary:Buffer,//二进制
living:Boolean,//是否活着
birthday:Date,//生日
age:Number,//年龄
_id:Schema.Types.ObjectId, //主键
_fk:Schema.Types.ObjectId, //外键
array:[],//数组
arrOfString:[String],//字符串数组
arrOfNumber:[Number],//数字数组
arrOfDate:[Date],//日期数组
arrOfBuffer:[Buffer],//Buffer数组
arrOfBoolean:[Boolean],//布尔值数组
arrOfObjectId:[Schema.Types.ObjectId]//对象ID数组
nested:{ name:String} //内嵌文档
});
let p = new Person();
p.name= 'zfpx';
p.age = 25;
p.birthday = new Date();
p.married = false;
p.mixed= {any:{other:'other'}};
p._otherId = new mongoose.Types.ObjectId;
p.hobby.push('smoking');
p.ofString.push('string');
p.ofNumber.pop(3);
p.ofDates.addToSet(new Date);
p.ofBuffer.pop();
p.ofMixed = ['anything',3,{name:'zfpx'}];
p.nested.name = 'zfpx';
Model是由通过Schema构造而成 除了具有Schema定义的数据库骨架以外,还可以操作数据库 如何通过Schema来创建Model呢,如下:
var mongoose = require('mongoose');
var connection = mongoose.createConnection("mongodb://127.0.0.1/zfpx",{ useNewUrlParser: true,useUnifiedTopology: true});
connection.on('error', function (error) {
console.log('数据库连接失败: ' + error);
});
connection.on('open', function (error) {
console.log('数据库连接成功');
});
let PersonSchema = new mongoose.Schema({
name:String, //姓名
age:Number,//年龄
});
//两个参数表示定义一个模型
var PersonModel = connection.model("Person", PersonSchema);
// 如果该Model已经定义,则可以直接通过名字获取
var PersonModel = connection.model('Person');//一个参数表示获取已定义的模型
拥有了Model,我们也就拥有了操作数据库的能力 在数据库中的集合名称等于 模型名转小写再转复数,比如 Person>person>people,Child>child>children
let personEntity = new PersonModel({
name : "zhufeng",
age : 6
});
console.log(personEntity);//{ _id: 5d9c70438e748c3ae032a7fd, name: 'zhufeng', age: 6 }
Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作,但Model比Entity可以实现的功能更多
let mongoose = require("mongoose");
let conn = mongoose.createConnection("mongodb://127.0.0.1/zfpx",{ useNewUrlParser: true,useUnifiedTopology: true});
let PersonSchema = new mongoose.Schema({
name: {type: String},
age: {type: Number, default: 0}
});
let PersonModel = conn.model("Person", PersonSchema);
let PersonEntity = new PersonModel({
name: "zfpx",
age: 6
});
PersonEntity.save(function (error, doc) {
if (error) {
console.log("error :" + error);
} else {
//doc是返回刚存的person对象
console.log(doc);
}
});
5d9c70b3 f88966 4f24 d9caa5
部分 | 值 | 含义 |
---|---|---|
4字节 | 5d9c70b3 | 时间戳是自 1970 年 1 月 1 日(08:00:00 GMT)至当前时间的总秒数,它也被称为 Unix 时间戳,单位为秒 |
3字节 | f88966 | 所在主机的唯一标识符,通常是机器主机名的散列值(hash),可以确保不同主机生成不同的ObjectId 不产生冲突 |
2字节 | 4f24 | 产生ObjectId的进程的进程标识符(PID) |
3字节 | d9caa5 | 由一个随机数开始的计数器生成的值 |
let ts = parseInt('5d9c70b3', 16);;
console.log(ts);
let date = new Date(ts*1000);
console.log(date.toLocaleString());
console.log(parseInt('4f24',16));//20260
console.log(parseInt('d9caa5',16))//14273189
前9个字节保证了同一秒钟不同机器不同进程产生的ObjectId是唯一的,最后3个字节是一个自动增加的计数器,确保相同进程同一秒产生的ObjectId也是不一样的,一秒钟最多允许每个进程拥有256的3次方(16777216)个不同的ObjectId 每一个文档都有一个特殊的键_id,这个键在文档所属的集合中是唯一的。
语法
Model.find(查询条件,callback);
代码
Model.find({},function(error,docs){
//若没有向find传递参数,默认的是显示所有文档
});
Model.find({ "age": 6 }, function (error, docs) {
if(error){
console.log("error :" + error);
}else{
console.log(docs); //docs: age为6的所有文档
}
});
语法
Model.create(文档数据, callback))
代码
PersonModel.create({ name:"zfpx", age:7}, function(error,doc){
if(error) {
console.log(error);
} else {
console.log(doc);
}
});
`
语法
Entity.save(callback))
代码
var PersonEntity = new PersonModel({name:"zfpx",age: 9});
PersonEntity.save(function(error,doc) {
if(error) {
console.log(error);
} else {
console.log(doc);
}
});
语法
Model.update(查询条件,更新对象,callback);
代码
var conditions = {name : 'zfpx'};
var update = {$set : { age : 100 }};
PersonModel.update(conditions, update, function(error){
if(error) {
console.log(error);
} else {
console.log('Update success!');
}
});
请注意如果匹配到多条记录,默认只更新一条,如果要更新匹配到的所有记录的话需要加一个参数 {multi:true}
语法
Model.remove(查询条件,callback);
代码
var conditions = { name: 'zfpx' };
PersonModel.remove(conditions, function(error){
if(error) {
console.log(error);
} else {
console.log('Delete success!');
}
});
PersonModel.create([
{ name:"zfpx1", age:1 },
{ name:"zfpx2", age:2 },
{ name:"zfpx3", age:3 },
{ name:"zfpx4", age:4 },
{ name:"zfpx5", age:5 },
{ name:"zfpx6", age:6},
{ name:"zfpx7", age:7 },
{ name:"zfpx8", age:8 },
{ name:"zfpx9", age:9},
{ name:"zfpx10",age:10 }
], function(error,docs) {
if(error) {
console.log(error);
} else {
console.log('save ok');
}
});
语法
find(Conditions,field,callback)
代码
//field省略或为Null,则返回所有属性。
//返回只包含name、age两个键的所有记录
Model.find({},{name:1, age:1, _id:0},function(err,docs){
//docs 查询结果集
})
我们只需要把显示的属性设置为大于零的数就可以,当然1是最好理解的,_id是默认返回,如果不要显示加上("_id":0)
与find相同,但只返回单个文档,也就说当查询到即一个符合条件的数据时,将停止继续查询,并返回查询结果 语法
findOne(Conditions,callback)
代码
TestModel.findOne({ age: 6}, function (err, doc){
// 查询符合age等于6的第一条数据
// doc是查询结果
});
与findOne相同,但它只接收文档的_id作为参数,返回单个文档 语法
findById(_id, callback)
代码
PersonModel.findById(person._id, function (err, doc){
//doc 查询结果文档
});
查询时我们经常会碰到要根据某些字段进行条件筛选查询,比如说Number类型,怎么办呢,我们就可以使用$gt(>)、$lt(<)、$lte(<=)、$gte(>=)操作符进行排除性的查询,如下示例:
Model.find({"age":{"$gt":6}},function(error,docs){
//查询所有nage大于6的数据
});
Model.find({"age":{"$lt":6}},function(error,docs){
//查询所有nage小于6的数据
});
Model.find({"age":{"$gt":6,"$lt":9}},function(error,docs){
//查询所有nage大于6小于9的数据
});
$ne(!=)操作符的含义相当于不等于、不包含,查询时我们可通过它进行条件判定,具体使用方法如下:
Model.find({ age:{ $ne:6}},function(error,docs){
//查询age不等于6的所有数据
});
和$ne操作符相反,$in相当于包含、等于,查询时查找包含于指定字段条件的数据
Model.find({ age:{ $in: 6}},function(error,docs){
//查询age等于6的所有数据
});
Model.find({ age:{$in:[6,7]}},function(error,docs){
//可以把多个值组织成一个数组
});
可以查询多个键值的任意给定值,只要满足其中一个就可返回,用于存在多个条件判定的情况下使用,如下示例:
Model.find({"$or":[{"name":"zfpx"},{"age":6}]},function(error,docs){
//查询name为zfpx或age为6的全部文档
});
$exists操作符,可用于判断某些关键字段是否存在来进行条件查询。如下示例:
Model.find({name: {$exists: true}},function(error,docs){
//查询所有存在name属性的文档
});
Model.find({email: {$exists: false}},function(error,docs){
//查询所有不存在email属性的文档
});
可以限制结果的数量,跳过部分结果,根据任意键对结果进行各种排序
所有这些选项都要在查询被发送到服务器之前指定
在查询操作中,有时数据量会很大,这时我们就需要对返回结果的数量进行限制 那么我们就可以使用limit函数,通过它来限制结果数量。 语法
find(Conditions,fields,options,callback);
代码
Model.find({},null,{limit:20},function(err,docs){
console.log(docs);
});
如果匹配的结果不到20个,则返回匹配数量的结果,也就是说limit函数指定的是上限而非下限
skip函数的功能是略过指定数量的匹配结果,返回余下的查询结果 如下示例:
find(Conditions,fields,options,callback);
代码
Model.find({},null,{skip:4},function(err,docs){
console.log(docs);
});
如果查询结果数量中少于4个的话,则不会返回任何结果。
sort函数可以将查询结果数据进行排序操作 该函数的参数是一个或多个键/值对 键代表要排序的键名,值代表排序的方向,1是升序,-1是降序 语法
find(Conditions,fields,options,callback)
代码
Model.find({},null,{sort:{age:-1}},function(err,docs){
//查询所有数据,并按照age降序顺序返回数据docs
});
sort函数可根据用户自定义条件有选择性的来进行排序显示数据结果。
Model('User').find({})
.sort({createAt:-1})
.skip((pageNum-1)*pageSize)
.limit(pageSize)
.populate('user')
.exec(function(err,docs){
console.log(docs);
});
var mongoose = require('mongoose');
//连接数据库
mongoose.connect('mongodb://localhost:27017/201606blog');
//定义课程Schema
var CourseSchema = new mongoose.Schema({
name:String
});
var CourseModel = mongoose.model('Course',CourseSchema);
var PersonSchema = new mongoose.Schema({
name:{
type:String,
required:true
},
// 外键 别的集合的主键
course:{
type:mongoose.Schema.Types.ObjectId,
ref:'Course' //指明此外键是哪个集合中的外键
}
});
var PersonModel = mongoose.model('Person',PersonSchema);
CourseModel.create({name:'node.js'},function(err,course){
PersonModel.create({name:'zfpx',course:course._id},function(err,doc){
console.log(doc);
PersonModel.findById(doc._id).populate('course').exec(function(err,doc){
console.log(doc);
})
})
});