简介

Leoric 是一个 Node.js 的关系对象映射库(ORM),使用 Leoric 操作数据库的方式大致如下:

const { Bone, connect } = require('leoric')

// 基于 Bone 定义模型,映射关系表
class Post extends Bone {
  static initialize() {
    this.belongsTo('author', { Model: 'User' })
    this.hasMany('comments')
  }
}

async function() {
  // 连接模型到数据库,获取对应表结构信息
  await connect({ host: 'example.com', models: [Post], /* among other options */ })

  // CRUD
  await Post.create({ title: 'New Post' })
  const post = await Post.findOne({ title: 'New Post' })
  post.title = 'Untitled'
  await post.save()

  // 也可以批量更新
  await Post.update({ title: 'Untitled' }, { title: 'New Post' })

  // 获取模型中定义的关联数据
  await Post.include('comments').where('posts.title = ?', 'New Post')
  // => Post { id: 1, title: 'New Post', ...,
  //           comments: [ Comment { id, content }, ... ] }
}

目录

  1. 在 Web 开发框架中使用
  2. 语法对照表
  3. 上手指南
    1. 入门
    2. 核心指南
    3. 进阶
    4. 参考
  4. 参与贡献
  5. 插件 & 组件

在 Web 开发框架中使用

Leoric 支持在 Koa、Express、Egg 等 Node.js 社区常见的 Web 开发框架中使用,特别推荐 Egg 开发者使用 egg-orm 插件:

/* config/plugin.js */
exports.orm = {
  enable: true,
  package: 'egg-orm',
};

/* config/config.default.js */
exports.orm = {
  client: 'mysql',
  database: 'temp',
  host: 'localhost',
};

通过 ctx.model 使用 app/model 下定义的数据模型,例如 ctx.model.User

// app/controller/home.js
const { Controller } = require('egg');
module.exports = class HomeController extends Controller {
  async index() {
    const users = await ctx.model.User.find({
      corpId: ctx.model.Corp.findOne({ name: 'alipay' }),
    });
    ctx.body = users;
  }
};

语法对照表

JavaScript SQL
Post.create({ title: 'New Post' })
INSERT INTO posts (title) VALUES ('New Post');
Post.all
SELECT * FROM posts;
Post.find({ title: 'New Post' })
SELECT * FROM posts WHERE title = 'New Post';
Post.find(42)
SELECT * FROM posts WHERE id = 42;
Post.order('title')
SELECT * FROM posts ORDER BY title;
Post.order('title', 'desc')
SELECT * FROM posts ORDER BY title DESC;
Post.limit(20)
SELECT * FROM posts LIMIT 0, 20;
Post.update({ id: 42 }, { title: 'Untitled' })
UPDATE posts SET title = 'Untitled' WHERE id = 42;
Post.remove({ id: 42 })
DELETE FROM posts WHERE id = 42;
Post.find({ id: [1, 2, 3] })
SELECT * FROM posts WHERE id IN (1, 2, 3);
Post.select('id, title').where('title like ?', '%Post%')
SELECT id, title FROM posts WHERE title LIKE '%Post%';
Post.where('title like ? || authorId = ?', '%Post%', 42)
SELECT *
  FROM posts
 WHERE title LIKE '%Post%' OR author_id = 42;
Post
  .select('count(id) as count')
  .group('authorId')
  .having('count > 0')
  .order('count', 'desc')
  SELECT count(id) AS count, author_id
    FROM posts
GROUP BY author_id
  HAVING count > 0
ORDER BY count DESC;
Book.average('price').group('genre').having('average > 50')
  SELECT AVG('price') AS average, genre
    FROM books
GROUP BY genre
  HAVING average > 50;
Post.find({
  id: TagMap.select('targetId').where({ tagId: 1 }),
})
SELECT *
  FROM posts
 WHERE id
    IN (SELECT target_id FROM tag_maps WHERE tag_id = 1);
Post.include('author', 'comments')
   SELECT *
     FROM posts AS posts
LEFT JOIN users ON users.id = posts.author_id
LEFT JOIN comments ON comments.post_id = posts.id;
Post.join(Attachment, 'attachments.postId = posts.id')
   SELECT *
     FROM posts AS posts
LEFT JOIN attachments ON attachments.post_id = posts.id;
Post
  .join(TagMap,
    'tagMaps.targetId = posts.id and tagMaps.targetType = 0')
  .join(Tag, 'targetMaps.tagId = tags.id')
   SELECT *
     FROM posts AS posts
LEFT JOIN tag_maps AS tagMaps
       ON tagMaps.target_id = posts.id AND tag_maps.target_type = 0
LEFT JOIN tags
       ON tagMaps.tag_id = tags.id;

上手指南

入门

  1. 快速开始
  2. 基础
  3. 环境配置

核心指南

  1. 查询接口
  2. 关联关系
  3. 表结构变更
  4. 校验
  5. 钩子
  6. 事务

进阶

  1. Realm API
  2. 原始查询
  3. JSON 字段
  4. 软删除
  5. 索引提示
  6. 最佳实践

参考

  1. 数据类型
  2. TypeScript 支持
  3. 日志
  4. Sequelize 适配器
  5. 错误排查

参与贡献

有许多种参与贡献的方式,比如:

如果有兴趣贡献代码修复已知问题,参考我们的如何贡献代码一文,大致包含如下内容:

插件 & 组件

使用 Egg 框架 的开发者,不妨通过 egg-orm 插件来使用 Leoric,可以参考 egg-orm 仓库中已经包含的示例项目

使用 Midway 的开发者也可以选择我们为 Midway 专门开发的连接组件 @midwayjs/leoric,可以参考文档快速上手,也可以浏览 仓库目录 了解更多使用示例。