用于CRUD等的模型驱动REST或GraphQL API

介绍

本文介绍了用于CRUD(创建、读取、更新、删除)的模型驱动RESTGraphQL API。有了它,您可以编写简单的模型(指定数据库表和要公开的列集),CRUDREST端点将自动可用。不需要任何SQL的手动编码。

这个概念可以在不同的技术栈和语言上实现。在这里,我将JavaScript(生成SQL)与Node.jsExpressPostgreSQL结合使用。

背景

大多数项目需要CreateReadUpdateDelete对象。当这些对象足够简单时(一个驱动表和数据库中的几列),代码从一个对象到另一个对象非常相似。实际上,模式是相同的,唯一的区别是表的名称和列的名称和类型。

当然,总会有复杂的端点需要手工编写,但通过自动化简单的端点,我们可以节省大量时间。

使用代码

示例数据库为待办事项列表、地址簿和图画小说库存提供了三个示例。这些示例使用模型中指定的对象ID“todocontactcomics

使用它们之后,更改数据库(在config.js中),更改模型(在模型目录中),RESTful API将根据您的数据结构进行更改。

按照以下步骤使用示例数据库安装和设置项目。

安装

从GitHub下载或克隆。

# To get the latest stable version, use git from the command line.
git clone https://github.com/evoluteur/evolutility-server-node

或使用npm包

# To get the latest stable version, use npm from the command line.
npm install evolutility-server-node

设置

安装Evolutility-Server-Node后,请执行以下步骤:

  1. 创建一个PostgreSQL数据库。
  2. 在文件config.js中,设置PostgreSQL连接字符串和模式名称以访问您的新数据库。
  3. 在命令行中,键入以下内容:

# Install dependencies
npm install

# Create sample database w/ demo tables
node js/setup/database.js

# Run the node.js server
npm start

Web浏览器中,转到URL http://localhost:3000/api/v1/evolutility/todo

配置

目录下,编辑文件config.js来设置数据库连接和其他选项,如分页和上传目录。

Models

要由REST API访问,必须在模型中描述每个数据库表。模型包含驱动表的名称和API中存在的字段/列的列表。

实体

财产

意义

id

标识实体的唯一键(用作API参数)

table

数据库表名

fields

字段数组

titleField

记录标题的字段ID

searchFields

用于执行搜索的字段的字段ID数组

字段

财产

意义

id

字段的唯一键(可以与列相同,但不一定)

column

字段的数据库列名称

lovtable

字段值要加入的表(仅适用于lov类型的字段)

lovcolumn

字段值的列名(在lovtable中)(仅适用于lov类型的字段)

type

字段类型不是数据库列类型,而是UI字段类型。可能的字段类型:

  • boolean(是/否)
  • date
  • datetime
  • decimal
  • document
  • email
  • image
  • integer
  • lov(值列表)
  • money
  • text
  • textmultiline
  • time
  • url

readonly

防止字段修改

inMany

确定字段是否存在于记录列表中(默认情况下)

注意:更多字段属性(uniqueminmaxminLengthmaxLength...)将在稍后添加。

示例模型

这是一个待办事项应用程序的模型。

module.exports = {
    id: "todo",
    table: "task",
    titleField: "title",
    searchFields: ["title", "duedate", "description"],
    fields: [
        {
            id: "title", 
            column: "title", 
            type: "text", 
            inMany: true
        },
        {
            id: "duedate", 
            column: "duedate", 
            type: "date", 
            inMany: true
        },
        {
            id: "category", 
            column: "category_id", 
            type: "lov", 
            lovtable: "task_category",
            inMany: true
        },
        {
            id: "priority", 
            column: "priority_id", 
            type: "lov", 
            lovtable: "task_priority", 
            required: true, 
            inMany: true
        {
            id: "complete", 
            column: "complete", 
            type: "boolean", 
            inMany: true
        },
        {
            id: "description",  
            column: "description", 
            type: "textmultiline"
        }
    ]
};

此模型仅涵盖后端。也可以对前端进行建模(只要UX模式足够简单或者变得复杂到不值得)。

REST API

Evolutility-Server-NodeAPI受到PostgREST的极大启发(甚至部分复制),PostgREST也提供通用CRUD,但直接检查数据库模式而不是使用模型。

在本地运行项目时,todo应用程序的URLhttp://localhost:3000/api/v1/evolutility/todo

请求的信息

得到一个

要通过ID获取特定记录,请使用< ObjectName >/ID

GET /<object>/<id>

GET /todo/12

获得许多

每个模型都暴露出来。您可以使用模型ID查询项目列表。

GET /<object>

GET /todo

过滤

您可以通过在字段上添加条件来过滤结果行,每个条件都是一个查询字符串参数。

GET /<object>/<field.id>=<operator>.<value>

GET /todo?title=sw.a
GET /todo?priority=in.1,2,3

添加多个参数结合条件:

todo?complete=0&duedate=lt.2017-01-01

这些运算符可用的:

操作符

意义

例子

eq

等于

/todo?category=eq.1

gt

...更大

/todo?duedate=gt.2017-01-15

lt

少于

/todo?duedate=lt.2017-01-15

gte

大于或等于

/todo?duedate=gte.2017-01-15

lte

小于或等于

/todo?duedate=lte.2017-01-15

ct

包含

/todo?title=ct.e

sw

...开始

/todo?title=sw.a

fw

结束

/todo?title=fw.z

in

值列表之一

/todo?priority=in.1,2,3

0

是假的

/todo?complete=0

1

是真的

/todo?complete=1

null

null

/todo?category=null

nn

不是null

/todo?category==nn

排序

保留字order对响应行重新排序。它使用逗号分隔的字段和方向列表:

GET /<object>?order=<field.id>.<asc/desc>

GET /todo?order=priority.desc,title.asc

如果没有指定方向,则默认为升序:

GET /todo?order=duedate

限制和分页

保留字pagepageSize限制了响应行。

GET /<object>?page=<pageindex>&pageSize=<pagesize>

GET /todo?page=0&pageSize=50

格式化

默认情况下,所有API都以JSON格式返回数据。此API调用允许以CSV格式请求数据(导出到Excel)。此功能使用express-csv

GET /<object>?format=csv

GET /todo?format=csv

注意:在返回的数据中,每个对象都有一个额外的属性_full_count,表示查询中的记录总数(限制之前)。

更新数据

记录创建

要在数据库表中创建一行,请发布一个JSON对象,其键是您要创建的列的名称。缺少的键将在适用时设置为默认值。

POST /todo
{ title: 'Finish testing', priority: 2}

更新

PATCH /todo
{ title: 'Finish testing', priority: 2}

删除

只需使用带有记录id的动词DELETE即可删除。

DELETE /<object>/<id>

DELETE /todo/5

附加端点

除了CRUDEvolutility-Server-Node还为常见的UI需求提供端点,例如图表和值列表。

发现

返回对象及其API的列表(仅包括标记为活动的对象)。

GET /

注意:必须在配置中使用{apiInfo: true}启用此端点。

图表

对于图表数据,可以获得聚合数据。

GET /<object>/chart/<field id>

GET /todo/chart/category

值列表

UI中的下拉字段(在模型中的field.type="lov")有一个REST端点来获取下拉列表的值。

GET /<object>/lov/<field id>

GET /todo/lov/category

统计数据

返回模型中数值字段的总数以及最小值、最大值、平均值和总计。

GET /<object>/stats

GET /todo/stats

上传文件

此端点允许您上传文件。当前(幼稚)实现仅将文件服务器上的文件保存在名为对象id的文件夹中。

POST /<object>/upload/<id>

POST /comics/upload/5

带有查询参数:filefieldid

嵌套集合

如果模型定义了集合,则可以使用此端点查询它们。

GET /<model.id>/collec/<collection.id>?id=<id>

GET /winecellar/collec/wine_tasting?id=1</code>

API版本

此端点获取API版本(在项目的package.json文件中指定)。

GET /version

GraphQL

Evolutility-Server-Node提供基于与REST API相同模型的GraphQL接口。

在本地运行项目时,garphiQLURLhttp://localhost:2000/graphql

请求的信息

ID获取一条记录

通过Id获取单个记录。

{ 
    contact (id: 1 ){
        firstname
        lastname
        category_txt
        email
  }
}

获得许多记录

所有对象都暴露给带有搜索和过滤器的查询。过滤器使用与REST API相同 的条件语法 (例如:firstname: "sw.A"} 表示名字以A开头)。

“lov”(值列表)类型的字段表示为Id和值的2个字段。

{ 
	urgent_tasks: todos ( complete: "false", priority: "lt.3" ){
	    title
	    description
	    priority
	    priority_txt
	    category
	    category_txt
	    complete
  }
  	ab_a_contacts: contacts (search: "ab", firstname: "sw.A") { 
	    id
	    firstname
	    lastname
	    category_txt
	    email
  }
}

图表数据

对于所有对象,记录可以按字段聚合和计数(对于数字或“lov”类型的字段)。

{ 
  contacts_by_category: contact_charts(fieldId:"category"){
    label 
    value
  }
  task_by_priority: todo_charts(fieldId:"priority") {
    label 
    value
  }
  restaurants_by_cuisine: restaurant_charts(fieldId:"cuisine") {
    label 
    value
  }
}

兴趣点

模型驱动架构(MDA)将使您更快地启动和运行,同时也节省您在项目的进化维护中的时间。

例如,当项目完成时,我们经常需要添加字段。通常,这意味着向数据库添加一列,并在每个使用数据库表的REST端点中手动添加该字段。使用模型驱动的方法,一旦将列添加到数据库中,您只需将字段添加到单个位置(模型),并且使用该模型的每个端点都会公开它。

模型驱动的方法也可以应用于UI。如果你想玩它,我做了两个不同的匹配模型驱动UI的实现,Evolutility-UI-React(用于React)和Evolutility-UI-jQuery(用于jQueryBackboneJS)。

https://www.codeproject.com/Articles/1169060/Model-driven-REST-or-GraphQL-API-for-CRUD-and-More

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值