ThinkJS 里内置的 ORM 可以很方便的操作关系型数据库和文档型数据库,支持:Mysql,SQLite,PostgreSQL,Mongo 等。如果内置的 ORM 不能满足项目的需求,那么也可以集成第三方的 ORM,如:Mongoose,Waterline 等。本文就来聊聊如何在 ThinkJS 里集成 Mongoose。
Mongoose 是一个专门用来操作 Mongo 的 ORM,提供了很多非常有用的方法。可以通过 npm install mongoose
命令来安装 Mongoose,Mongoose 详细文档请见: http://mongoosejs.com/docs/guide.html
项目里可以直接引入 Mongoose,然后根据官方文档来使用,但这种方式下开发会比较麻烦,因为没法使用 ThinkJS 里内置的模型类、自动实例化和自动传入模型配置等功能了。
ThinkJS 的模型是一个类,实例化的时候会传入模型名称和连接 Mongo 的配置,基类大致代码如下:
export default class {
// name 为传入的模型名称,没有传入的话会自动分析当前的文件名作为模型名
// config 为连接 Mongo 的配置
constructor(name, config){
this.name = name;
this.config = config;
}
}
而连接 Mongo 是通过 Mongo Socket 这个 Adapter 来完成的,后续操作都是等拿到 Socket Connection 后进行。
Mongoose 里是创建连接,然后定义 schema 和创建模型,使用时实例化模型。如果有多个配置连接的话,通过 createConnection
方法来创建连接。
var mongoose = require("mongoose")
, Schema = mongoose.Schema
var personSchema = Schema({
_id : Number,
name : String,
age : Number,
stories : [{ type: Schema.Types.ObjectId, ref: "Story" }]
});
var storySchema = Schema({
_creator : { type: Number, ref: "Person" },
title : String,
fans : [{ type: Number, ref: "Person" }]
});
所以可以通过包装将 Mongoose 的格式转成 ThinkJS 的格式。
"use strict";
import mongoose from "mongoose";
/**
* model
*/
export default class extends think.base {
/**
* schema
* @type {Object}
*/
schema = {};
/**
* model instance
* @type {[type]}
*/
_model = null;
/**
* constructor
* @param {[type]} name [description]
* @param {Object} config [description]
* @return {[type]} [description]
*/
constructor(name, config = {}){
super();
if(think.isObject(name)){
config = name;
name = "";
}
this.name = name;
this.config = think.parseConfig(config);
}
/**
* 创建连接
* @return {[type]} [description]
*/
getConnection(){
let user = "";
if(this.config.user){
user = this.config.user + ":" + this.config.password + "@";
}
let host = this.config.host || "127.0.0.1";
let port = this.config.port || 27017;
let str = `mongodb://${user}${host}:${port}/${this.config.database}`;
return mongoose.createConnection(str);
}
/**
* 获取 Mongoose 里的 Model
* @return {[type]} [description]
*/
getModel(){
if(!this._model){
let connection = this.getConnection();
this._model = connection.model(this.name, new mongoose.Schema(this.schema));
}
return this._model;
}
}
通过上面包装的方式后,可以通过 getModel
方法获取 Mongoose 里的模型,然后就可以对其实例化进行操作了。如:
export default class extends think.controller.base {
/**
* index action
* @return {Promise} []
*/
async indexAction(){
let instance = this.model("user");
let model = instance.getModel();
let ret = await model.create({
username: "welefen"
});
let data = await model.find({}).exec();
console.log(data)
//auto render template file index_index.html
return this.display();
}
}
实际项目中,建议将上面的包装放在 model/base.js
里,其他模型文件继承该类。 控制器里通过 getModel
方法获取模型,然后实例化并调用方法,也可以将这些逻辑封装在模型中。如:
// model/use.js
import Base from "./base";
export default class extends Base {
schema = {
username: String
};
findData(where = {}){
let Model = this.getModel();
return Model.find(where).exec();
}
addData(data = {}){
let Model = this.getModel();
return model.create(data);
}
}
这样就可以通过 findData
方法来查询数据,addData
方法来添加数据了。
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8