发布时间:
我们在egg中使用sequelize,要先在 app/model/
目录下编写 Model,在CmsWing我们把编写Model做成了类似 “Navicat”的数据库管理工具,就像Navicat一样后台创建表,字段,关联会自动生成 sequelize Model文件并且会自动生成增、删、改、查的GraphQL接口。
这里只列出 CmsWing 特有的,更详细的内容请阅读 Egg.js 文档 Sequelize
我们通过CmsWing的模型管理,创建一个 cms_doc 的模型,会在app/model/
目录下自动生成这个 Model,具体的 Sequelize 的使用请阅读 Sequelize官方文档
// app/model/cms_doc.js
// 本文件由CmsWing根据模型管理自动生成,请勿手动修改!
'use strict';
module.exports = app => {
const DataTypes = app.Sequelize;
const CmsDoc = app.model.define('cms_doc', {
id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, comment: '主键' },
createdAt: { type: DataTypes.DATE, comment: '创建时间' },
updatedAt: { type: DataTypes.DATE, comment: '更新时间' },
user_uuid: { type: DataTypes.UUID, comment: '作者uuid' },
title: { type: DataTypes.STRING, comment: '内容标题' },
classify_id: { type: DataTypes.INTEGER, defaultValue: 0, comment: '分类ID' },
classify_sub: { type: DataTypes.JSON, comment: '子分类' },
description: { type: DataTypes.STRING(1000), comment: '描述' },
root: { type: DataTypes.INTEGER, defaultValue: 0, comment: '根节点' },
pid: { type: DataTypes.INTEGER, defaultValue: 0, comment: '所属ID' },
models_uuid: { type: DataTypes.UUID, comment: '模型UUID' },
type: { type: DataTypes.INTEGER, defaultValue: 2, comment: '内容类型(1-目录,2-主题,3-段落)' },
position: { type: DataTypes.STRING, comment: '推荐位(1-列表推荐,2-频道页推荐,4-首页推荐)' },
ext_link: { type: DataTypes.STRING, comment: '如果填写链接,会跳转到这个链接,不填不跳转' },
cover_url: { type: DataTypes.STRING, comment: '封面' },
display: { type: DataTypes.BOOLEAN, defaultValue: true, comment: '可见性' },
deadline: { type: DataTypes.DATE, comment: '截止时间' },
view: { type: DataTypes.INTEGER, defaultValue: 0, comment: '浏览量' },
level: { type: DataTypes.INTEGER, defaultValue: 0, comment: '优先级(越高排序越靠前)' },
status: { type: DataTypes.INTEGER, defaultValue: 1, comment: '数据状态(0-禁用,1-正常,2-待审核,3-草稿)' },
template: { type: DataTypes.STRING, comment: '模板详情' },
tags: { type: DataTypes.STRING, comment: '标签' },
sort: { type: DataTypes.INTEGER, defaultValue: 0, comment: '排序同级有效越小越靠前' },
}, {
indexes: [{ unique: false, fields: [ 'classify_id' ] }, { unique: false, fields: [ 'pid' ] }, { unique: false, fields: [ 'models_uuid' ] }],
paranoid: true,
});
CmsDoc.associate = function() {
app.model.CmsClassify.hasMany(app.model.CmsDoc, {
foreignKey: 'classify_id',
sourceKey: 'id',
constraints: false,
});
app.model.CmsDoc.belongsTo(app.model.CmsClassify, {
foreignKey: 'classify_id',
targetKey: 'id',
constraints: false,
});
app.model.CmsDoc.hasOne(app.model.CmsDocArticle, {
foreignKey: 'doc_id',
sourceKey: 'id',
constraints: false,
});
app.model.CmsDocArticle.belongsTo(app.model.CmsDoc, {
foreignKey: 'doc_id',
targetKey: 'id',
constraints: false,
});
app.model.CmsDoc.hasOne(app.model.CmsDocDownload, {
foreignKey: 'doc_id',
sourceKey: 'id',
constraints: false,
});
app.model.CmsDocDownload.belongsTo(app.model.CmsDoc, {
foreignKey: 'doc_id',
targetKey: 'id',
constraints: false,
});
app.model.CmsDoc.hasOne(app.model.CmsDocPicture, {
foreignKey: 'doc_id',
sourceKey: 'id',
constraints: false,
});
app.model.CmsDocPicture.belongsTo(app.model.CmsDoc, {
foreignKey: 'doc_id',
targetKey: 'id',
constraints: false,
});
app.model.SysUser.hasMany(app.model.CmsDoc, {
foreignKey: 'user_uuid',
sourceKey: 'uuid',
constraints: false,
});
app.model.CmsDoc.belongsTo(app.model.SysUser, {
foreignKey: 'user_uuid',
targetKey: 'uuid',
constraints: false,
});
};
// CmsDoc.sync({ alter: true });
return CmsDoc;
};
这个 Model 就可以在 Controller 和 Service 中通过 app.model.CmsDoc
或者 ctx.model.CmsDoc
访问到了。
创建模型命名建议都是小写 应用_表名 的格式,比如 cms_doc , cms_doc_ext, 在Controller 和 Service 中使用 ctx.model.CmsDoc,ctx.model.CmsDocExt;
cms_doc -> CmsDoc
cms_doc_ext -> CmsDocExt
CmsWing 模型管理不支持多数据源,但是我们可以手动创建Model,来实现,比如我们需要增加一个db2数据库,配置如下,需要在app目录下新建一个mysql2目录来放置db2的model文件。
'use strict';
const { Op } = require('sequelize');
module.exports = {
datasources: [
{//默认数据库,支持CmsWing模型管理
dialect: 'mysql',
host: '127.0.0.1',
port: 3306,
database: 'cmswing2',
username: 'root',
password: 'root123456',
timezone: '+08:00',
define: {
freezeTableName: true, // 强制表名称等于模型名称
underscored: false,
},
},
{//新增加的数据库配置,不支持模型管理,需要手动编写Model
dialect: 'mysql',
// 这里是通过app.Model2来使用db1数据库的模型
delegate: 'model2',
// 指定模型文件在哪里,默认是model
baseDir: 'model2',
host: '127.0.0.1',
port: 3306,
database: 'db2',
username: 'root',
password: 'root123456',
timezone: '+08:00',
define: {
freezeTableName: true, // 强制表名称等于模型名称
underscored: false,
},
}
],
};
model2需要手动编写model文件
// model2/title2.js
"use strict"
module.exports = app=>{
const {
INTEGER,
STRING,
DATE
} = app.Sequelize;
const Title2 = app.Model2.define('student1',{
Id: {
type: STRING,
},
age1: INTEGER,
name: STRING,
birth: DATE
}, {
freezeTableName: true,
timestamps: false
})
return Title2;
}
//默认
await this.ctx.Model.CmsDoc.findOne({where: {name: id}})
//db2
await this.ctx.Model2.Title2.findOne({where: {name: id}})
使用CmsWing模型管理创建会在app/graphql目录下自动生成对应的 GraphQL 接口。app/graphql目录下的文件系统自动生成,请勿手动修改,详细的graphql语法请阅读 graphql官方文档
生成命名规则 假如你的 模型名称是cms_doc ,会自动生成下面的 GraphQL 方法。
#Query
type Query {
#cms内容主表 findAll 方法. 它生成一个标准的 SELECT 查询,该查询将从表中检索所有条目(除非受到 where 子句的限制).
CmsDoc_findAll(where:WhereCmsDoc,order:[[String]],limit:Int,offset:Int):[CmsDoc]
#cms内容主表 findByPk 方法使用提供的主键从表中仅获得一个条目.
CmsDoc_findByPk(id:ID!):CmsDoc
#cms内容主表 findOne 方法获得它找到的第一个条目(它可以满足提供的可选查询参数).
CmsDoc_findOne(where:WhereCmsDoc):CmsDoc
#cms内容主表 findAndCountAll 方法是结合了 findAll 和 count 的便捷方法. 在处理与分页有关的查询时非常有用,在分页中,你想检索带有 limit 和 offset 的数据,但又需要知道与查询匹配的记录总数.
CmsDoc_findAndCountAll(where:WhereCmsDoc,order:[[String]],limit:Int!,offset:Int!):CountCmsDoc
}
#Mutation
type Mutation {
#cms内容主表 添加
CmsDoc_create(data:AddCmsDoc):CmsDoc
#cms内容主表 删除
CmsDoc_destroy(where:WhereCmsDoc!):ResDelCmsDoc
#cms内容主表 更新
CmsDoc_update(data:EditCmsDoc!,where:WhereCmsDoc!):ResEditCmsDoc
}
以amis为例:
{
"method": "post",
"url": "/graphql/admin",
"data": {
"query": "mutation AddUser($name: String!, $email: String!) {insert_user(object: { title: $title, email: $email }) { title email}}",
"variables": {
"name": "${name}",
"email": "${email}"
}
}
}
以amis为例:
{
"method": "post",
"url": "/graphql/mc",
"data": {
"query": "mutation AddUser($name: String!, $email: String!) {insert_user(object: { title: $title, email: $email }) { title email}}",
"variables": {
"name": "${name}",
"email": "${email}"
}
}
}
以amis为例:
{
"method": "post",
"url": "/graphql/open",
"data": {
"query": "mutation AddUser($name: String!, $email: String!) {insert_user(object: { title: $title, email: $email }) { title email}}",
"variables": {
"name": "${name}",
"email": "${email}"
}
}
}
假如我们有这么一个需求,我们在后台创建了一个模型,名称是 sys_models,我们要根据id获取这个模型的信息
在后台使用 amis 调用,amis 的api本身就支持 graphql 可以参考 amis文档
{
"initApi": {
"method": "post",
"url": "/graphql/admin",
"graphql": "query($id:ID!){SysModels_findByPk(id:$id){id name desc paranoid}}",
"data": {
"id": "${models_id}"
},
"responseData": {
"&": "${SysModels_findByPk}",
"oldName":"${SysModels_findByPk.name}"
}
}
}
在jQuery中使用ajax请求
$.ajax({
// headers: { token: "123456" }, //如果需要携带 token
type: "post",
url: "/graphql/mc",
data: {
query: "query($id:ID!){SysModels_findByPk(id:$id){id name desc paranoid}}",
variables: { id: 1 },
},
success: function (result) {
// 业务逻辑
console.log(result);
},
});
微信小程序示例
wx.request({
method:'POST',
url: 'http://127.0.0.1:7001/graphql/mc',
data: {
query: "query($id:ID!){SysModels_findByPk(id:$id){id name desc paranoid}}",
variables: { id: 1 },
},
header: {
'content-type': 'application/json',
//因为小程序是跨端调用 所有需要登录的接口需要携带登录返回的token
'token':'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjoxLCJjcmVhdGVkQXQiOiIyMDIyLTA5LTI3VDA3OjAzOjM5LjAwMFoiLCJ1cGRhdGVkQXQiOiIyMDIyLTA5LTI4VDA0OjUxOjA5LjAwMFoiLCJ1c2VybmFtZSI6ImFydGVybGkiLCJwYXNzd29yZCI6IjE3Mzg5NGJhY2M0Yjk1MDI0OGE1MDM0MTMyNTQzOWNhIiwiZW1haWwiOiJhcnRlcmxpQHFxLmNvbSIsIm1vYmlsZSI6IjE4NjgxODUxNjM3Iiwic3RhdGUiOnRydWUsInV1aWQiOiIwMGNjMjRkYy03YmY4LTRkZGQtODg5NS1hMTM1MWZmNmM1ODUiLCJ0aGlyZCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9vc3MuY21zd2luZy5jb20vdXBsb2FkLzRiZDJmODE0LWFhZTAtNDkxZC05MTdiLTlmNWNiNzJlZDUzOC5qcGcifSwiaWF0IjoxNjY2MTYxODkxfQ.vmu71eQm_bz79b9UDkDBQiJcuMjoxnaBOBWnZS4SHhU'
},
success (res) {
console.log(res.data)
}
})
假如我们要对 sys_models 进行添加,更新,删除,我们需要使用 Mutations ,下面我们以更新为例来说明如何使用
在后台使用 amis 调用,amis 的api本身就支持 graphql 可以参考 amis文档
{
"api": {
"url": "/graphql/admin",
"method": "post",
"graphql": "mutation($name:String,$desc:String,$paranoid:Boolean,$id:ID!,$oldName:String){SysModels_update(data:{name:$name,desc:$desc,paranoid:$paranoid,oldName:$oldName},where:{id:{op_eq:$id}}){ids}}"
},
}
在jQuery中使用ajax请求
$.ajax({
// headers: { token: "123456" }, //如果需要携带 token
type: "post",
url: "/graphql/mc", // MCenter 中使用
data: {
query: "mutation($name:String,$desc:String,$paranoid:Boolean,$id:ID!,$oldName:String){SysModels_update(data:{name:$name,desc:$desc,paranoid:$paranoid,oldName:$oldName},where:{id:{op_eq:$id}}){ids}}",
variables: { name: 'ceshi_ceshibiao',desc:'测试',paranoid:false, id:1,oldName:'sys_models'},
},
success: function (result) {
// 业务逻辑
console.log(result);
},
});
微信小程序示例
wx.request({
method:'POST',
url: 'http://127.0.0.1:7001/graphql/mc', //MCenter 中使用
data: {
query: "mutation($name:String,$desc:String,$paranoid:Boolean,$id:ID!,$oldName:String){SysModels_update(data:{name:$name,desc:$desc,paranoid:$paranoid,oldName:$oldName},where:{id:{op_eq:$id}}){ids}}",
variables: { name: 'ceshi_ceshibiao',desc:'测试',paranoid:false, id:1,oldName:'sys_models'},
},
header: {
'content-type': 'application/json',
//因为小程序是跨端调用 所有需要登录的接口需要携带登录返回的token
'token':'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7ImlkIjoxLCJjcmVhdGVkQXQiOiIyMDIyLTA5LTI3VDA3OjAzOjM5LjAwMFoiLCJ1cGRhdGVkQXQiOiIyMDIyLTA5LTI4VDA0OjUxOjA5LjAwMFoiLCJ1c2VybmFtZSI6ImFydGVybGkiLCJwYXNzd29yZCI6IjE3Mzg5NGJhY2M0Yjk1MDI0OGE1MDM0MTMyNTQzOWNhIiwiZW1haWwiOiJhcnRlcmxpQHFxLmNvbSIsIm1vYmlsZSI6IjE4NjgxODUxNjM3Iiwic3RhdGUiOnRydWUsInV1aWQiOiIwMGNjMjRkYy03YmY4LTRkZGQtODg5NS1hMTM1MWZmNmM1ODUiLCJ0aGlyZCI6bnVsbCwiYXZhdGFyIjoiaHR0cHM6Ly9vc3MuY21zd2luZy5jb20vdXBsb2FkLzRiZDJmODE0LWFhZTAtNDkxZC05MTdiLTlmNWNiNzJlZDUzOC5qcGcifSwiaWF0IjoxNjY2MTYxODkxfQ.vmu71eQm_bz79b9UDkDBQiJcuMjoxnaBOBWnZS4SHhU'
},
success (res) {
console.log(res.data)
}
})
我们可以在后台点击左上角的 GraphQL 按钮进行调试
最后更新时间: 2023-09-29 08:17:57