mongoose

Mongoose

》Schema
Mongoose 的一切始于 Schema。每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成。
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var blogSchema = new Schema({
title: String,
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
}
});
在这之后你还想添加 keys 的话, 请使用 Schema#add 方法。
允许使用的 SchemaTypes 有:
String
Number
Date
Buffer
Boolean
Mixed
ObjectId
Array

SchemaType
指定字段约束,不同的SchemaType类型还有其他不同的属性配置
var schema2 = new Schema({
test: {
type: String,
lowercase: true // Always convert `test` to lowercase
}
});
常用可配参数有:
required: 必选验证器。
default: 默认值。Any或function,如果该值是一个函数,则该函数的返回值将用作默认值。
select: boolean值, 指定是否被投影
validate: 验证器
alias: 别名。
其他类型特有属性官方API查找。

since index creation can cause a significant performance impact. Disable the behavior by setting the autoIndex option of your schema to false, or globally on the connection by setting the option autoIndex to false.

mongoose.connect('mongodb://user:pass@localhost:port/database', { autoIndex: false }); //真心推荐
// or
mongoose.createConnection('mongodb://user:pass@localhost:port/database', { autoIndex: false });
// or
animalSchema.set('autoIndex', false);
// or
new Schema({..}, { autoIndex: false });

schema还可以添加一些Options:
option: id
Mongoose 会默认生成一个虚拟值 id,指向文档的 _id 字段。 如果你不需要 id 虚拟值,可以通过这个选项禁用此功能。
option: _id
Mongoose 默认给你的 Schema 赋值一个 _id。 这个值的类型是 ObjectId,这与MongoDB的默认表现一致。 如果你不需要 _id,可以通过这个选项禁用此功能。
option: strict
Strict 选项默认为 true,这意味着你不能 save schema 里没有声明的属性。
还可以设置转字符串时的一些参数:
schema.set('toJSON', { getters: true, virtuals: false });
schema.set('toObject', { getters: true });

》connction
我们可以通过利用mongoose的connect()方法连接到MongoDB 。
mongoose.connect('mongodb://localhost/myapp');
这是在默认端口(27017)连接到在本地运行的myapp数据库的最低需要。

我们也能根据你的环境指定URI中的几个参数,详细看MongoDB连接字符串格式。
mongoose.connect('mongodb://username:password@host:port/database?options...');
mongoose.connect('mongodb://test:1234@ip:port/test', {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(()=>{
response.end("connected!");
mongoose.connection.close();
}).catch((e)=>{
response.end("error!"+e);
});

要连接到副本集,你可以用逗号分隔,传入多个地址
mongoose.connect('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]' [, options]);
连接多个 mongos(MongoDB Shard)分片集群的实例。在 mongoose 5.x 中不需要传入任何特殊选项。
// Connect to 2 mongos servers
mongoose.connect('mongodb://mongosA:27501,mongosB:27501', cb);

多个连接
有时候我们需要多个连接,例如权限不同,或是连接到不同数据库。这个情况下我们可以使用 mongoose.createConnection(), 它接受之前提到的所有参数,给你返回一个新的连接。
const conn = mongoose.createConnection('mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]', options);
connection 对象后续用于创建和检索 models。 models 的范围总是局限于单个连接。

调用 mongoose.connect() 时,Mongoose 会自动创建默认连接。 你可以使用 mongoose.connection 访问默认连接。

Options
connect方法还接收一个option对象,该对象将被传递给底层驱动程序,可以传一些Mongo底层驱动的参数或mongoose自己的参数。这里的所有选项优先于连接字符串传递的选项。
mongoose.connect(uri, options);
可设置的有:
poolSize - MongoDB 保持的最大连接池的连接数。 poolSize 的默认值是 5。
autoIndex - 默认情况下,mongoose 在连接时会自动建立 schema 的索引,这可能导致长时间阻塞,建议设置为false。
user/pass - 用于认证的用户名和密码
bufferCommands - Mongoose会缓存所有命令直到连接上数据库,这意味着你不必等待它连接MongoDB再定义 models,执行 queries 等。这个操作很方便,但也回引起一些疑惑, 因为如果你没连上 ,Mongoose 不会 抛错。要禁用缓存,请修改 bufferCommands 配置,也可以全局禁用 bufferCommands :
mongoose.set('bufferCommands', false);
bufferMaxEntries - MongoDB 驱动同样有自己的离线时缓存机制。如果你希望链接错误时终止数据库操作,请将此选项设为 0 以及把 bufferCommands 设为 false 。
connectTimeoutMS - 连接超时时间
keepAlive - 保活时间

const options = {
user: "test",
pass: "1234"
autoIndex: false, // Don't build indexes
poolSize: 10, // Maintain up to 10 socket connections
bufferCommands: false,
bufferMaxEntries: 0 // If not connected, return errors immediately rather than waiting for reconnect
};
mongoose.connect(uri, options);
connect函数可以传入回调方法 function(error),或者返回promise写成then形式:
mongoose.connect(uri, options).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ },
err => { /** handle initial connection error */ }
);

》model
Models 是从 Schema 编译来的构造函数。 它们的实例就代表着可以从数据库保存和读取的 documents。 从数据库创建和读取 document 的所有操作都是通过 model 进行的。

使用默认的connection把 schema 编译为一个 Model: mongoose.model(modelName, schema)
使用自定义的connection把 schema 编译为一个 Model: connection.model(modelName, schema)

var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Car = mongoose.model('Car', schema);
注意: mongoose.model里面定义的第一个参数,比如’Car’,实际上在db中的collection是’Cars’。要解决这种混淆,可以在创建Schema时明确设置collection名称:
var schema = new mongoose.Schema({ name: 'string', size: 'string' },{collection:'Car'} );

>有了Model,则可以创建文档、操作文档:
var small = new Car({ size: 'small' });
small.save(function (err) {
if (err) return handleError(err);
// saved!
})
// 或者
Car.create({ size: 'small' }, function (err, small) {
if (err) return handleError(err);
// saved!
})
要注意,直到 model 使用的数据库连接( connection )被打开,small 文档才会被创建/删除。

>查询
mongoose支持 MongoDB 的查询语法,即直接使用find/findOne并传入json格式的查询条件(可回调或promise的then处理结果),或者用 model 简单封装 findById、where 这些静态方法。

Mongoose 中每一处查询,被传入的回调函数都遵循 callback(error, result) 这种模式。查询结果的格式取决于做什么操作: findOne() 是单个文档(有可能是 null ),find() 是文档列表, count() 是文档数量,update() 是被修改的文档数量。

Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec(callback);
Tank.findById(id, function (err, tank) {
if (err) return handleError(err);
tank.size = 'large'; // 更新操作,直接操作对象即可,或者用 tank.set({ size: 'large' });
tank.save(function (err, updatedTank) {
if (err) return handleError(err);
res.send(updatedTank);
});
});
这个方法先检索数据,接着更新(使用了 save)。 如果我们仅仅需要更新而不需要获取该数据, Model#update 就很适合我们:
Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

如果我们确实需要返回文档,这个方法更适合:
Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, { new: true }, function (err, tank) {
if (err) return handleError(err);
res.send(tank);
});

增删改查
;(async ()=>{
//查
var t = await studentModel.find({})
//改 //注意! : 若使用 xxx.save() 则只有 schema 声明过的对象才能通过对应的 setter 传递值进入 xxx._doc.xxx.value
await studentModel.update({_id:"ae86"},{$set:{username:"newwww"}})
//增
await studentModel.create({ username:'test',phone:'110'})
//删除
await studentModel.remove({phone:'110'})
//$lt"(小于),"$lte"(小于等于),"$gt"(大于),"$gte"(大于等于),"$ne"(不等于)
await userMode.find({"age": {"$lt": 18}})

//简单分页查询
Model.find({}).sort({'_id':-1}).skip(page * 5).limit(5)
//复杂分页查询 要求前端返回一个 ObjectId
if (id) {
return Model.find({{'_id': {"$lt": id}}).sort({'_id':-1}).skip(page * 5).limit(5)
}else {
return Model.find({}).sort({'_id':-1}).skip(page * 5).limit(5)
}

//关闭连接
mongoose.connection.close()
})()

防止函数声明式调用失效
把( function a( ){ })()改写为;( function a( ) { })() 比较好,加一个分号防止上一行结尾没有分号导致的编译歧义

原文地址:https://www.cnblogs.com/ccdat/p/11749448.html