【typeorm】typeorm官方文档querybuilder插入更新删除部分

  • 接上篇

使用 Query Builder 插入

你可以使用QueryBuilder创建INSERT查询。 例如:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .insert()
  .into(User)
  .values([{ firstName: "Timber", lastName: "Saw" }, { firstName: "Phantom", lastName: "Lancer" }])
  .execute();

就性能而言,这是向数据库中插入实体的最有效方法。 你也可以通过这种方式执行批量插入。

原始SQL支持

在某些情况下需要执行函数SQL查询时:

import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .insert()
    .into(User)
    .values({ 
        firstName: "Timber", 
        lastName: () => "CONCAT('S', 'A', 'W')"
    })
    .execute();

此语法不会对值进行转义,你需要自己处理转义。

使用 Query Builder 更新

你可以使用QueryBuilder创建UPDATE查询。 例如:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .update(User)
  .set({ firstName: "Timber", lastName: "Saw" })
  .where("id = :id", { id: 1 })
  .execute();

就性能而言,这是更新数据库中的实体的最有效方法。

原始SQL支持

在某些情况下需要执行函数SQL查询时:

typescript import {getConnection} from “typeorm”; await getConnection() .createQueryBuilder() .update(User) .set({ firstName: “Timber”, lastName: “Saw”, age: () => “‘age’ + 1” }) .where(“id = :id”, { id: 1 }) .execute();

此语法不会对值进行转义,你需要自己处理转义。

使用 Query Builder 删除

你可以使用QueryBuilder创建DELETE查询。 例如:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .delete()
  .from(User)
  .where("id = :id", { id: 1 })
  .execute();

就性能而言,这是删除数据库中的实体的最有效方法。

与 Relations 结合

RelationQueryBuilder是QueryBuilder的一种允许你使用关系来查询的特殊类型。 通过使用你可以在数据库中将实体彼此绑定,而无需加载任何实体,或者可以轻松地加载相关实体。 例如:

例如,我们有一个Post实体,它与Category有一个多对多的关系,叫做categories。 让我们为这种多对多关系添加一个新 category:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(post)
  .add(category);

这段代码相当于:

import { getManager } from "typeorm";

const postRepository = getRepository(Post);
const post = await postRepository.findOne(1, { relations: ["categories"] });
post.categories.push(category);
await postRepository.save(post);

但是这样使用第一种方式效率更高,因为它执行的操作数量最少,并且绑定数据库中的实体,这比每次都调用save这种笨重的方法简化了很多。

此外,这种方法的另一个好处是不需要在 pushing 之前加载每个相关实体。 例如,如果你在一个 post 中有一万个 categories,那么在此列表中添加新 posts 可能会产生问题,因为执行此操作的标准方法是加载包含所有一万个 categories 的 post,push 一个新 category 然后保存。 这将会导致非常高的性能成本,而且基本上不适用于生产环境。 但是,使用RelationQueryBuilder则解决了这个问题。

此外,当进行绑定时,可以不需要使用实体,只需要使用实体 ID 即可。 例如,让我们在 id 为 1 的 post 中添加 id = 3 的 category:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(1)
  .add(3);

如果你使用了复合主键,则必须将它们作为 id 映射传递,例如:

import { getConnection } from "typeorm";

await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of({ firstPostId: 1, secondPostId: 3 })
  .add({ firstCategoryId: 2, secondCategoryId: 4 });

也可以按照添加实体的方式删除实体:

import { getConnection } from "typeorm";

// 此代码从给定的post中删除一个category

await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(post) // 也可以使用post id
  .remove(category); // 也可以只使用category ID

添加和删除相关实体针对多对多和一对多关系。 对于一对一和多对一关系,请使用set代替:

import { getConnection } from "typeorm";

// 此代码set给定post的category
await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(post) // 也可以使用post id
  .set(category); // 也可以只使用category ID

如果要取消设置关系(将其设置为 null),只需将null传递给set方法:

import { getConnection } from "typeorm";

// 此代码取消设置给定post的category
await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(post) // 也可以使用post id
  .set(null);

除了更新关系外,关系查询构建器还允许你加载关系实体。 例如,假设在Post实体内部,我们有多对多的categories关系和多对一的user关系,为加载这些关系,你可以使用以下代码:

import { getConnection } from "typeorm";

const post = await getConnection().manager.findOne(Post, 1);

post.categories = await getConnection()
  .createQueryBuilder()
  .relation(Post, "categories")
  .of(post) // 也可以使用post id
  .loadMany();

post.author = await getConnection()
  .createQueryBuilder()
  .relation(User, "user")
  .of(post) // 也可以使用post id
  .loadOne();

缓存查询

你可以缓存getMany,getOne,getRawMany,getRawOne和getCount这些QueryBuilder方法的查询结果。

还可以缓存find,findAndCount,findByIds和count这些Repository方法查询的结果。

要启用缓存,需要在连接选项中明确启用它:

{
    type: "mysql",
    host: "localhost",
    username: "test",
    ...
    cache: true
}

首次启用缓存时,你必须同步数据库架构(使用 CLI,migrations 或synchronize连接选项)。

然后在QueryBuilder中,你可以为任何查询启用查询缓存:

const users = await connection
  .createQueryBuilder(User, "user")
  .where("user.isAdmin = :isAdmin", { isAdmin: true })
  .cache(true)
  .getMany();

等同于Repository查询:

const users = await connection.getRepository(User).find({
  where: { isAdmin: true },
  cache: true
});

这将执行查询以获取所有 admin users 并缓存结果。 下次执行相同的代码时,它将从缓存中获取所有 admin users。 默认缓存生存期为1000 ms,例如 1 秒。 这意味着在调用查询构建器代码后 1 秒内缓存将无效。 实际上,这也意味着如果用户在 3 秒内打开用户页面 150 次,则在此期间只会执行三次查询。 在 1 秒缓存窗口期间插入的任何 users 都不会返回到 user。

你可以通过QueryBuilder手动更改缓存时间:

const users = await connection
  .createQueryBuilder(User, "user")
  .where("user.isAdmin = :isAdmin", { isAdmin: true })
  .cache(60000) // 1 分钟
  .getMany();

或者通过 Repository:

const users = await connection.getRepository(User).find({
  where: { isAdmin: true },
  cache: 60000
});

或者通过全局连接选项:

{
    type: "mysql",
    host: "localhost",
    username: "test",
    ...
    cache: {
        duration: 30000 // 30 seconds
    }
}

此外,你可以通过QueryBuilder设置"cache id":

const users = await connection
  .createQueryBuilder(User, "user")
  .where("user.isAdmin = :isAdmin", { isAdmin: true })
  .cache("users_admins", 25000)
  .getMany();

或者通过 Repository:

const users = await connection.getRepository(User).find({
  where: { isAdmin: true },
  cache: {
    id: "users_admins",
    milisseconds: 25000
  }
});

这使你可以精确控制缓存,例如,在插入新用户时清除缓存的结果:

await connection.queryResultCache.remove(["users_admins"]);

默认情况下,TypeORM 使用一个名为query-result-cache的单独表,并在那里存储所有查询和结果。 表名是可配置的,因此您可以通过在 tableName 属性中给出值来更改它 例如:

{
    type: "mysql",
    host: "localhost",
    username: "test",
    ...
    cache: {
        type: "database",
        tableName: "configurable-table-query-result-cache"
    }
}

如果在单个数据库表中存储缓存对你无效,则可以将缓存类型更改为"redis"或者"ioredis",而 TypeORM 将以 redis 形式存储所有缓存的记录。 例如:

{
    type: "mysql",
    host: "localhost",
    username: "test",
    ...
    cache: {
        type: "redis",
        options: {
            host: "localhost",
            port: 6379
        }
    }
}

“options” 可以是node_redis specific options 或者 ioredis specific options,具体取决于你使用的类型。

如果你想使用IORedis的集群功能连接到redis-cluster,则可以通过方式下操作来执行此操作:


请注意,你仍然可以使用选项作为IORedis的集群构造函数的第一个参数。
typescript { ... cache: { type: "ioredis/cluster", options: [ { host: 'localhost', port: 7000, }, { host: 'localhost', port: 7001, }, { host: 'localhost', port: 7002, } ] }, ... } ```

你可以使用typeorm cache:clear来清除存储在缓存中的所有内容。
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页