@dudousxd/nestjs-filter-drizzle

中文文档
0.3.0发布于 2026/11/12MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 2101

@dudousxd/nestjs-filter的 Drizzle ORM适配器.

中文使用文档
文档目录12 节
  1. 安装
  2. 快速启动
  3. 它如何映射到 Drizzle 上
  4. DrizzleQuery API 密码
  5. 双倍关系过滤器
  6. 已计算字段
  7. 测试
  8. 限制
  9. API 参考
  10. DrizzleFilter<TTable>
  11. DrizzleFilterModule.forRoot({ connection | db, schema?, dia…
  12. DrizzleAdapter

@dudousxd/nestjs-filter-dryzzle (英语)

Drizzle ORM 适应器 @dudousxd/nestjs-filter。 。 。 .

提供 DrizzleFilter, (中文(简体) ), DrizzleAdapter, (中文(简体) ), DrizzleQuery,以及 DrizzleFilterModule。 。 。 . Postgres,MySQL和SQLite得到支持(每个方言都运行着交叉适应器合同套件).

安装

pnpm add @dudousxd/nestjs-filter @dudousxd/nestjs-filter-drizzle

同伴依赖性 : drizzle-orm 0.40 < 1.0, (中文(简体) ), @nestjs/common >=10, @nestjs/core 十点. 可选 : @nestjs/drizzle ^ 0.0.2 < 1.0,适配器默认使用其数据库.

快速启动

// schema.ts — the table object IS the entity
import { relations } from 'drizzle-orm';
import { integer, pgTable, serial, text } from 'drizzle-orm/pg-core';

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  age: integer('age').notNull(),
  role: text('role').notNull(),
});

export const posts = pgTable('posts', {
  id: serial('id').primaryKey(),
  title: text('title').notNull(),
  status: text('status').notNull(),
  authorId: integer('author_id').notNull(),
});

// relations() powers includes, dot-notation filters, whereHas(), aggregates and describe()
export const usersRelations = relations(users, ({ many }) => ({ posts: many(posts) }));
export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));

export const schema = { users, posts, usersRelations, postsRelations };
// user.filter.ts
import { Injectable } from '@nestjs/common';
import { Filterable, FilterFor } from '@dudousxd/nestjs-filter';
import { DrizzleFilter } from '@dudousxd/nestjs-filter-drizzle';
import { eq, gte } from 'drizzle-orm';
import { posts, users } from './schema.js';

@Injectable()
@Filterable({ entity: users })
export class UserFilter extends DrizzleFilter<typeof users> {
  static readonly sort = ['name', 'age', 'posts.$count'];
  static readonly search = ['name'];
  static readonly includes = ['posts'];

  @FilterFor('minAge')
  applyMinAge(value: number) {
    this.$query.where(gte(users.age, value));
  }

  @FilterFor('name')
  applyName(value: string) {
    this.whereILike('name', value); // escaped; ILIKE on Postgres, lower() LIKE elsewhere
  }

  @FilterFor('hasPublished')
  applyHasPublished(value: boolean) {
    if (value) this.$query.whereHas('posts', (p) => eq((p as typeof posts).status, 'published'));
  }
}
// app.module.ts — the database comes from NestJS's @nestjs/drizzle (https://docs.nestjs.com/data/drizzle)
import { Module } from '@nestjs/common';
import { DrizzleModule } from '@nestjs/drizzle';
import { FilterModule } from '@dudousxd/nestjs-filter';
import { drizzleAdapter } from '@dudousxd/nestjs-filter-drizzle';
import { drizzle } from 'drizzle-orm/node-postgres';
import { schema } from './schema.js';

@Module({
  imports: [
    DrizzleModule.forRoot({ drizzle, connection: process.env.DATABASE_URL!, schema }),
    // no `connection`/`db`: injects getDrizzleToken(name) from @nestjs/drizzle
    FilterModule.forRoot({ inputNormalizer: 'camelCase', adapter: drizzleAdapter() }),
    FilterModule.forFeature([UserFilter]),
  ],
  controllers: [UsersController],
})
export class AppModule {}

已命名的连接 : drizzleAdapter({ name: 'reports' }) 页:1 DrizzleModule.forRoot({ name: 'reports', ... })。 。 。 . @nestjs/drizzle 是一个可选的对等点:没有它,就通过自己的标志(drizzleAdapter({ connection: DRIZZLE }), (中文(简体) ), 提供来源a @Global() 模块)或实例(drizzleAdapter({ db })) (中文(简体) ).

// users.controller.ts
import { Controller, Get } from '@nestjs/common';
import { ApplyFilter } from '@dudousxd/nestjs-filter';
import type { DrizzleQuery } from '@dudousxd/nestjs-filter-drizzle';

@Controller('users')
export class UsersController {
  @Get()
  list(@ApplyFilter(UserFilter) q: DrizzleQuery<typeof users>) {
    return q.execute(); // or q.executeAndCount(), q.count(), q.toSelect(), q.toSQL()
  }
}

GET /users?minAge=18&name=al&sort=-age&include=posts&paginate[page]=0&paginate[size]=20

它如何映射到 Drizzle 上

概念MikroORM / TypeORM 适配器滴滴适配器
实体装饰类(User(中文(简体) )表格对象 (users(中文(简体) )
元数据ORM 元数据登记册getTableColumns(table) +该 relations() 在你的计划
this.$queryoRM 的查询构建器DrizzleQuery - 累积器 SQL 条件、顺序、窗口、投影和包括,作为 " 一体行动 " 实现 db.select().from(table) 执行时
关系过滤器( E)posts.status, (中文(简体) ), @Relations, (中文(简体) ), related()(中文(简体) )联 合关联 EXISTS (…) 子点
排序/ 区分于一个路径( O) (manager.name(中文(简体) )联 合相關相關相關相關相關相關相關相關分母
include加入/ ORM 填充批次 SELECT … WHERE fk IN (…) 按关系分列 row.posts[] 编号 : row.author (形状) db.query…findMany({ with }) 返回)
findAndCount 共计ORM 计数count(*) 平起平起平起地 distinct(中文(简体) )
合计数(posts.$count(中文(简体) )关联子点关联子点

根查询从不加入, 因此它总是每个匹配的父返回一行 : LIMIT编号 :OFFSET 财务报告和审定财务报表 COUNT(*) 不管请求涉及什么关系 都要保持精确.

DrizzleQuery API 密码

成员
where(...conds)和SQL条件undefined 被忽略 —— 作曲 and()编号 :or() 自由参加)
andWhere(cond | { col: value })也接受平等地图(阵列) – IN, (中文(简体) ), null → IS NULL(中文(简体) )
whereHas(path, (target) => cond?) 编号 : whereDoesntHave(...)关联 EXISTS 超过关系路径( e)'posts.comments'(中文(简体) )
orderBy(...terms), (中文(简体) ), clearOrderBy(), (中文(简体) ), limit(n), (中文(简体) ), offset(n)顺序和窗口
select(fields), (中文(简体) ), addSelect(fields), (中文(简体) ), distinct()预测
include(...paths)已装入的关系 execute()
columns, (中文(简体) ), table, (中文(简体) ), db, (中文(简体) ), dialect表格的列(可能别名)和执行上下文
execute(), (中文(简体) ), count(), (中文(简体) ), executeAndCount()运行它
toSelect(), (中文(简体) ), toSQL()已成形的细管构建器 / SQL + 参数

双倍关系过滤器

当过滤器通过时 @Relations (或 this.related(...)页:1 $query 目标a 别名 内部的表格 EXISTS 亚克瑞. 读取列通过 this.columns (或 whereHas而不是此类过滤器中导入的表格对象:

@FilterFor('postStatus')
applyStatus(value: string) {
  this.$query.where(eq(this.columns.status, value));
}

已计算字段

与其他适配器相同的三个源形式. 因为适配器从来没有加入,一个 字符串源中的不合格列总是表示根表的列; 一个函数 来源收到 { alias: <table name>, em: db } 并可能返回 SQL 字符串、 细雨 sql 片段,或选择的构建器(用作平板子:

@Filterable({
  entity: users,
  computed: {
    doubleAge: '(age * 2)',
    label: { source: `name || ' <' || role || '>'`, project: true },
  },
})
export class UserFilter extends DrizzleFilter<typeof users> {
  @Computed({ type: 'number' })
  postCount() {
    return sql`(select count(*) from ${posts} where ${posts.authorId} = ${users.id})`;
  }
}

测试

不需要数据库:对照一个过滤器运行 DrizzleQuery 结束 drizzle.mock() 并申明SQL.

import { drizzle } from 'drizzle-orm/node-postgres';

const q = new DrizzleAdapter(drizzle.mock()).query(users);
await runner.apply(UserFilter, { name: 'al', minAge: 18 }, q);
expect(q.toSQL()).toEqual({
  sql: 'select "id", "name", "age" from "users" where ("users"."name" ilike $1 and "users"."age" >= $2)',
  params: ['%al%', 18],
});

FilterTestingModule + 键 makeMockQueryBuilder 也工作:模拟记录 ['where', SQL] 调用,您可以用方言调用new PgDialect().sqlToQuery(sql)) (中文(简体) ).

限制

  • 仅细流 0.x (单位:千美元)relations() (原始内容存档于2017-10-01). Drizzle 1.0's defineRelations 尚未读取.
  • 无多对多 关系类型: 细雨模型化为相交表, 因此显示 作为一对一的接合点(user.userTags[].tag) (中文(简体) ).
  • JSON 子路径 (单位:千美元)metadata.tier)不能解决(MikroORM适配器支持它们).
  • 复合-关键关系 被跳过 include;过滤通过它们有效.
  • 矢量搜索 (单位:千美元)search = { vector })是只使用 Postgres .
  • 代码 (单位:千美元)@dudousxd/nestjs-filter-codegen通过TypeScript AST读取实体类; 它还没有得到 filterFields 从Drizzle桌子.

API 参考

DrizzleFilter<TTable>

抽象基础类. this.$query 是一个 DrizzleQuery<TTable>。帮助者: columns, (中文(简体) ), whereLike, (中文(简体) ), whereILike, (中文(简体) ), whereBeginsWith, (中文(简体) ), whereEndsWith (都逃脱了价值).

DrizzleFilterModule.forRoot({ connection | db, schema?, dialect?, imports? })

登记册 DrizzleAdapter 作为过滤器适配器. connection 您的注射符号 细雨实例(由全球提供,或由以下所列模块提供) imports(三); db 通过 直接出现. schema 默认为该实例的设定. drizzleAdapter(options) 和描述词一样 FilterModule.forRoot({ adapter })。 。 。 .

DrizzleAdapter

执行 FilterAdapter。 。 。 . adapter.query(table) 创建一个 DrizzleQuery 服务:

const q = adapter.query(users);
await runner.apply(UserFilter, input, q);
const { rows, total } = await q.executeAndCount();

版本与发布记录

@dudousxd/nestjs-filter-drizzle 共发布 8 个版本,首次发布于 2026/09/29;过去 12 个月发布了 8 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.3.0latest2026/11/122 天前
0.2.12026/11/095 天前
0.2.02026/11/086 天前
0.1.32026/11/0212 天前
1.0.02026/11/0112 天前
0.1.22026/10/2718 天前

关于 @dudousxd/nestjs-filter-drizzle 的常见问题

@dudousxd/nestjs-filter-drizzle 是什么?

@dudousxd/nestjs-filter的 Drizzle ORM适配器.

如何安装 @dudousxd/nestjs-filter-drizzle?

在项目目录运行 npm install @dudousxd/nestjs-filter-drizzle,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:drizzle-orm(>=0.40.0 <1.0.0)、@nestjs/core(>=10.0.0)、@nestjs/common(>=10.0.0)、reflect-metadata(>=0.1.13)、@dudousxd/nestjs-filter(^2.0.1)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@dudousxd/nestjs-filter-drizzle 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dudousxd/nestjs-filter-drizzle 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@dudousxd/nestjs-filter-drizzle 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dudousxd/nestjs-filter-drizzle 可以商用吗?

@dudousxd/nestjs-filter-drizzle 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dudousxd/nestjs-filter-drizzle 的下载量有多少?

根据 npm 官方下载统计,@dudousxd/nestjs-filter-drizzle 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,101 次,日均约 70 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dudousxd/nestjs-filter-drizzle 还在维护吗?

最新版本 0.3.0 发布于 2026/11/12(2 天前);至今共发布 8 个版本,其中过去 12 个月发布了 8 个;首次发布于 2026/09/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。