简介

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. 上手指南
  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;

上手指南

推荐依次阅读如下文档了解有关 Leoric 的详细信息

  1. 基础
  2. 表结构变更
  3. 校验
  4. 关联关系
  5. 查询接口
  6. 钩子
  7. TypeScript 支持
  8. Sequelize 适配器

参与贡献

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

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

插件 & 组件

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

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