npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

card-query

v4.1.0

Published

基于卡片元数据模型的数据查询方案

Downloads

3

Readme

card-query

基于卡片元数据模型的数据查询方案

安装

npm i card-query

使用

const query = require('card-query');

query.configure(config);

async function test() {
  let data = await query.cardr('卡片名称', ['名称', '编码'], { filter, order });
}

功能列表

configure(config)

配置数据库连接参数. 支持Oracle和Mysql两种数据库.

@ config参数

{
  [name]: {
    driver: '',       // 'oracle'或者'mysql'
    connectString: 'localhost/orcl',    // oracle专用
    host: '',         // mysql专用
    database: '',     // mysql专用
    user: '',         // 用户名
    password: '',     // 密码
  }
}

至少要有一个name为'default'的连接. 加载元数据会使用该连接

更多配置项请参考oracledbmysql2

getDatabase(name)

获取指定名称的数据库连接对象

@ name参数

对应出现在config中的key值

@ 返回值

根据连接的数据库类型, 可能为Oracle或者Mysql对象的实例. 两者都具有如下属性:

  • driver
    • 只读属性, 取值为'oracle'或者'mysql'
    • 可以用来判断连接的数据库类型
  • async getConnection()
    • 这是用来访问oracledbmysql2的连接对象的, 一般不推荐使用
    • 这个方法从连接池中获取一个连接对象. 如果是Oracle数据库, 连接对象是oracledb提供的. 如果是MySQL数据库, 连接对象是mysql2提供的.
    • 获取的连接, 用完后需要归还给连接池. 两个数据库的归还接口不一样, Oracle数据库需要调用conn.close()方法, MySQL数据库需要调用conn.release()方法.
    let db = getDatabase('AmyDB');
    let conn = await db.getConnection();
    conn.execute('select 1 from dual');
    conn.close(); // 如果是mysql则需要用conn.release()
  • async execute(sql, values = [])
    • 执行一个SQL语句
    • 支持以 ? 表达的参数化查询. 比如: execute('select ? from dual', [1]) . 如果是Oracle数据库, 会自动将 ? 转为 : 格式
    • 参数是数组格式. 顺序与sql文本中 ? 出现的顺序一致
  • async trans(callback)
    • 启动一个事务, 然后执行 callback 指定的回调函数. 如果没有错误发生, 则提交事务. 如果抛出了异常, 则回滚事务.
    • 如果成功提交了, 则返回Promise<null>, 如果失败回滚了, 则返回Promise<Error>
  • format_result(result)
    • 用来将oracledbmysql2的SQL结果集规范化到统一的格式: { rows, fields, affected, insertId }
      • rows: 返回的行数组
      • fields: 每个列的类型描述
      • affected: 影响的行数
      • insertId: 插入的ID. 如果是自增ID, 可以从这里拿到插入后生成的ID

middleware()

提供koa中间件支持. 调用后会返回一个koa中间件, 用来为ctx对象增加db属性. 可以通过db属性访问所有的功能.

const App = require('koa');
const query = require('card-query');

// 初始化数据库连接配置
query.configure(config);

const app = new App();
// 引入中间件
app.use(query.middleware());

app.use(async (ctx, next) => {
  // 执行SQL
  let d = await ctx.db('conn_name').execute('select * from user where id=?', [123]);

  // 调用cardr接口获取卡片的数据
  let data = await ctx.db.cardr('some card', [], 'some id');
  // 输出到浏览器
  ctx.body = JSON.stringify(data);
});

app.listen(3000);

async cardr(name, model, options)

提供基于卡片的数据查询功能

@ name参数: string

卡片名称

@ model参数: string[]

字段的数组. 可以用 . 多级连接引用的字段. 以下都是合法的写法:

['名称', '描述', '上级.名称', '持有人.所属部门.名称']

不需要显式添加 'ID' 字段

特殊地, 如果model参数传递 '*', [], null, undefined 表示使用卡片的全部字段(卡片数据+卡片引用).

@ options参数: string | number | object

可以传递一个ID值, 来直接查询对应ID的单条记录.

支持以下属性

  • filter - 筛选条件
  • order - 排序
  • rows - 每页行数
  • page - 页码

filter

格式为 { 'and/or': [ [三元组], { 'and/or': [] }, ... ] }

特殊地, 也支持 [ [三元组], { 'and/or': [] } ... ] 格式. 默认为 and 连接

其中, [三元组] 表示一个形如 [a,b,c] 由三个元素组成的数组. 第一个元素是字段名(model数组中的元素), 第二个元素是比较运算符, 第三个元素是值.

支持的比较运算符有:

=, <>, >, >=, <, <=
IS
IN, NOT IN
LIKE, NOT LIKE
BETWEEN, NOT BETWEEN

如果是 IN, BETWEEN 这样需要多个参数值的情况, 第三个元素要传递一个数组类型. 比如 ['序号', 'BETWEEN', [100,200]]

order

格式为 { '字段名': 'asc/desc', ... }

字段名是model数组中的元素

如果未提供此参数, 则默认为model中的 '记录时间' 降序. 如果model中没有 '记录时间', 就默认为 'ID' 升序

rows

如果不指定该参数, 或者指定为0, 都会被强制覆盖为默认的100. 这是为了避免一次性加载海量数据从而导致node因达到内存上限而崩溃.

如果确实需要一次性加载大量数据, 可以指定一个足够大的数值.

最佳实践是少量多次加载数据, 并且每次加载后根据rows和返回的行数是否相等来判断还有没有下一页数据等待加载.

page

请求的页码, 默认为 1

@ 返回值

数组类型, 查询到的所有记录

async cardw(name, model, records)

提供基于卡片的数据保存功能

@ name参数

卡片名称

@ model参数

请参考 cardr 中的model参数

@ records参数

要保存到数据库的记录数组

所有记录都会在一个事务中处理, 要么都成功, 要么都失败.

@ 返回值

返回经过修改的records参数:

如果记录没有指定ID, 则自动在插入数据库时生成新的ID并更新到记录上

async cardd(name, ids)

提供基于卡片的数据删除功能

@ name参数

卡片名称

@ ids参数

类型为 string[]

要删除记录的ID数组

@ 返回值

类型为 string[]

删除成功了的ID数组

async treer(name, model, parent, options)

基于cardr的结果集, 根据praent参数指定的上级字段名, 将结果集重组为children树的形式.

默认情况下, 上级记录不在cardr结果集中的记录都将作为树的顶级节点. 这在某些情况下这可能有问题, 可以通过指定options.root参数, 来指定成为顶级记录的必要条件.

async treed(name, ids)

提供基于卡片的数据树删除功能

参数与返回值都与cardd兼容.

相比cardd, treed可以自动删除ids对应记录的所有子记录.