找回密码
 立即注册
首页 业界区 业界 Vona ORM分表全攻略

Vona ORM分表全攻略

胁冉右 7 天前
分表

针对高并发、数据量大的场景,通常会考虑采用分表机制进行优化。下面以 Model User/Order 为例,通过查询用户的订单列表,来演示分表的使用方法
分表规则

比如需要对订单表进行分表操作。可以根据实际业务需求设计分表规则,在这里,根据用户Id取模动态生成表名。比如,拆分为16张表,用户Id为129,对应的表名如下:
  1. const tableName = `Order_${129 % 16}`;  // Order_1
复制代码
准备Models

先准备两个 Models:User/Order

  • Model Order
  1. @Model({
  2.   entity: EntityOrder,
  3. })
  4. class ModelOrder{}
复制代码

  • Model User
  1. @Model({
  2.   entity: EntityUser,
  3.   relations: {
  4.     orders: $relation.hasMany(() => ModelOrder, 'userId'),
  5.   },
  6. })
  7. class ModelUser {}
复制代码
查询数据

1. 直接查询订单列表
  1. class ServiceOrder {
  2.   async selectOrdersDirectly() {
  3.     const userId = 129;
  4.     const orders = await this.scope.model.order.select({
  5.       where: {
  6.         userId,
  7.       },
  8.     });
  9.   }
  10. }  
复制代码
到目前为止,使用默认表名查询userId=129的订单列表
2. 基于关系查询订单列表
  1. class ServiceOrder {
  2.   async selectOrdersByRelation() {
  3.     const userId = 129;
  4.     const userAndOrders = await this.scope.model.user.get({
  5.       id: userId,
  6.     }, {
  7.       include: {
  8.         orders: true,
  9.       },
  10.     });
  11.   }
  12. }  
复制代码
到目前为止,使用默认表名查询userId=129的用户信息,使用默认表名查询该用户的订单列表
使用分表:动态方式

可以在代码中动态使用分表:
  1. class ServiceOrder {
  2.   async selectOrdersDirectly() {
  3.     const userId = 129;
  4. +   const tableName = `Order_${userId % 16}`;
  5. +   const modelOrder = this.scope.model.order.newInstance(undefined, tableName as any);
  6.     const orders = await modelOrder.select({
  7.       where: {
  8.         userId,
  9.       },
  10.     });
  11.   }
  12. }  
复制代码

  • newInstance: 传入要使用的表名,返回新的 Model 实例
到目前为止,使用分表查询userId=129的订单列表
使用分表:Relation动态选项

可以在 relation 选项中动态指定表名:
  1. class ServiceOrder {
  2.   async selectOrdersByRelation() {
  3.     const userId = 129;
  4. +   const tableName = `Order_${userId % 16}`;
  5.     const userAndOrders = await this.scope.model.user.get({
  6.       id: userId,
  7.     }, {
  8.       include: {
  9.         orders: {
  10. +         meta: {
  11. +           table: tableName as any,
  12. +         },
  13.         },
  14.       },
  15.     });
  16.   }
  17. }  
复制代码

  • meta.table: 指定 relation orders要使用的表名
到目前为止,使用默认表名查询userId=129的用户信息,使用分表查询该用户的订单列表
使用分表:Model配置

也可以直接在 Model 中配置分表规则,从而简化查询代码

  • Model Order
  1. @Model({
  2.   entity: EntityOrder,
  3. + table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
  4. +   const userId = where?.userId;
  5. +   if (!userId) return defaultTable;
  6. +   return `Order_${Number(userId) % 16}`;
  7. + },
  8. })
  9. class ModelOrder{}
复制代码

  • table: 指定函数,实现分表规则

  • 查询数据
现在,又可以使用常规的方式查询用户的订单列表
  1. class ServiceOrder {
  2.   async selectOrdersDirectly() {
  3.     const userId = 129;
  4.     const orders = await this.scope.model.order.select({
  5.       where: {
  6.         userId,
  7.       },
  8.     });
  9.   }
  10. }  
复制代码
  1. class ServiceOrder {
  2.   async selectOrdersByRelation() {
  3.     const userId = 129;
  4.     const userAndOrders = await this.scope.model.user.get({
  5.       id: userId,
  6.     }, {
  7.       include: {
  8.         orders: true,
  9.       },
  10.     });
  11.   }
  12. }  
复制代码
使用分表:App Config配置

也可以在 App config 中配置 Model options:
src/backend/config/config/config.ts
  1. // onions
  2. config.onions = {
  3.   model: {
  4.     'test-vona:order': {
  5.       table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
  6.         const userId = where?.userId;
  7.         if (!userId) return defaultTable;
  8.         return `Order_${Number(userId) % 16}`;
  9.       },
  10.     },
  11.   },
  12. };
复制代码
于是,也可以使用常规的方式查询用户的订单列表
使用分表:Relation静态选项

也可以在定义 Relation 时指定静态选项:
  1. @Model({
  2.   entity: EntityUser,
  3.   relations: {
  4.     orders: $relation.hasMany(() => ModelOrder, 'userId', {
  5. +     meta: {
  6. +       table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
  7. +         const userId = where?.userId;
  8. +         if (!userId) return defaultTable;
  9. +         return `Order_${Number(userId) % 16}`;
  10. +       },
  11. +     },
  12.     }),
  13.   },
  14. })
  15. class ModelUser {}
复制代码
同样,也可以使用常规的方式查询用户的订单列表
Vona ORM已开源:github.com/vonajs/vona

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册