likes
comments
collection
share

TypeORM框架中的 Find查询中的基础选项和进阶选项

作者站长头像
站长
· 阅读数 20

所有存储库和管理器find方法都接受,可用于查询所需数据的特殊选项,而无需使用QueryBuilder

就像语法糖,但是不是真的语法糖,方便使用

find()方法用于查询数据库中的实体对象,它的参数是一个对象,包含查询的条件、排序方式、返回的实体数量、返回的实体的偏移量等信息。

基础选项

  • select - 指定要查询的实体对象的属性

如果省略select属性,则默认查询所有实体对象的所有属性

import { createConnection } from "typeorm";
import { User } from "./entity/User";

// 创建数据库
createConnection().then(async (connection) => {
  // 获取数据库中的数据
  const userRepository = connection.Repository(User);
  // 查询User表中名为 firstName 和 lastName 列的数据,并返回
  userRepository.find({ select: ["firstName", "lastName"] });
});
  • relations - 查询结果中包含的关联实体对象

在返回的结果中,包含关联的实体对象(返回的是整个实体对象)

import { createConnection } from "typeorm";
import { User } from "./entity/User";

// 创建数据库
createConnection().then(async (connection) => {
  // 获取数据库中的数据
  const userRepository = connection.Repository(User);
  // 查询与主实体对象(User)关联的`profile`、`photos`和`videos`实体对象
  userRepository.find({ relations: ["profile", "photos", "videos"] });
});

如果需要在查询时,同时想加载关联的实体对象和它们的属性,用外连接leftJoinAndSelect()方法或内连接innerJoinAndSelect()方法,就会在结果中得到关联表对象的值。

  • join - 指定关联实体对象的查询方式

alias属性指定主实体对象的别名

leftJoinAndSelect属性是一个对象,用于指定要查询的关联实体对象及其属性

import { createConnection } from "typeorm";
import { User } from "./entity/User";

// 创建数据库
createConnection().then(async (connection) => {
  // 获取数据库中的数据
  const userRepository = connection.Repository(User);
  
  userRepository.find({
      join: {
        alias: "user",
        leftJoinAndSelect: {
            profile: "user.profile",
            photo: "user.photos",
            video: "user.videos"
        }
      }
  });
});

在这个例子中,alias属性的值为user,表示查询的是userRepository所管理的实体对象。leftJoinAndSelect属性是一个包含profilephotovideo属性的对象,每个属性都表示要查询的关联实体对象及其在查询结果中的别名。例如,"user.profile"表示查询与user实体对象关联的profile实体对象,并将其在查询结果中的别名设置为profile

  • where -查询实体的简单条件

where的值是一个包含一个或多个查询条件的数组,每个条件可以是一个简单的对象,也可以是一个包含运算符的对象,还可以使用逻辑运算符和括号来组合多个条件。

// 查询 firstName 为 Timber 同时 lastName 为 Saw 的数据
userRepository.find({ where: { firstName: "Timber", lastName: "Saw" } });

查询嵌入实体列应该根据定义它的层次结构来完成

// 查询属性中的属性值,符合条件的数据
userRepository.find({ where: { name: { first: "Timber", last: "Saw" } } });

使用 OR 运算符查询

userRepository.find({
    // 表示查询结果为,满足两个对象条件的其中一个即可
    where: [{ firstName: "Timber", lastName: "Saw" }, { firstName: "Stan", lastName: "Lee" }]
    // 表示要查询`age`大于18的实体对象
    where: { age: MoreThan(18) }
});
  • order - 选择排序

排序方式有两种:升序(ASC)和降序(DESC)

order方法接受一个字符串、对象或数组参数,用于指定排序方式

// 按照`firstName`属性的升序排列查询结果
userRepository.find({ order: "firstName" })

// 按照`firstName`属性的升序和`lastName`属性的降序排列查询结果
userRepository.find({ order: { firstName: "ASC", lastName: "DESC" } })

// 按照`firstName`属性的升序和`lastName`属性的升序排列查询结果
userRepository.find({ order: ["firstName", "lastName"] })
  • skip - 指定查询结果的起始位置

它的值为一个数字,表示要跳过的记录数,设置为0表示从查询结果的第一条记录开始返回结果。

  • take - 指定查询结果的数量(分页,设置每一页返回多少)

它的值为一个数字,表示要返回的记录数。设置为10表示返回最多10条记录。

需要注意的是,分页查询时应根据实际情况设置skiptake属性的值。如果不设置take属性,则将返回所有满足条件的记录。如果设置skip属性的值大于查询结果的总记录数,则将返回一个空数组。

userRepository.find({
    order: {
        columnName: "ASC"
    },
    skip: 0,
    take: 10
});
  • cache -启用或禁用查询结果缓存
userRepository.find({
    // true查询结果缓存,false不缓存
    cache: true
});

进阶选项

TypeORM 提供了许多内置运算符,可用于创建更复杂的查询

  • Not - 表示不等于指定值
import { Not } from "typeorm";

// 查询 `Post` 实体对象中 `title` 不等于 `"About"` 的所有记录
const loadedPosts = await connection.getRepository(Post).find({
    title: Not("About")
});
  • LessThan - 小于指定值
import { LessThan } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `likes` 小于 `10` 的所有记录
    likes: LessThan(10)
});
  • LessThanOrEqual - 小于等于指定值
import { LessThanOrEqual } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `LessThanOrEqual` 小于等于 `10` 的所有记录
    likes: LessThanOrEqual(10)
});
  • MoreThan - 大于指定值
import { MoreThan } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `likes` 大于 `5` 的所有记录
    likes: MoreThan(5)
});
  • MoreThanOrEqual - 大于等于指定值
import { MoreThanOrEqual } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `likes` 大于等于 `5` 的所有记录
    likes: MoreThanOrEqual(5)
});
  • Equal - 等于指定值
import { Equal } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `likes` 等于 `8` 的所有记录
    likes: Equal(8)
});
  • Like - 指定字符串模式匹配
import { Like } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `title` 字符串中包含 `abc` 的所有记录
    title: Like("% abc %")
});
  • ILike - 表示指定(忽略字符串的大小写)模式匹配
import { ILike } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `title` 字符串中 忽略大小写后 包含 `abc` 的所有记录
    title: ILike("% abc %")
});
  • Between - 表示在指定范围内
import { Between } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `math`数值在 1到10 之间的所有记录
    math: Between(1, 10)
});
  • In - 表示查询属性值,是In数组中选项的记录
import { In } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `title`属性值为 "About2"和"About3" 的所有记录
    title: In(["About2", "About3"])
});
  • Any - 表示查询属性值等于指定数组中任意一个元素的记录
import { Any } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `Post` 实体对象中 `title`属性值为 "About2"或"About3" 的所有记录
    title: Any(["About2", "About3"])
});
  • IsNull表示为空
  • NotNull表示不为空
  • Raw内置运算符可以直接接受 SQL 字符串作为查询条件,可以实现更复杂的查询条件
import { Raw } from "typeorm";

const loadedPosts = await connection.getRepository(Post).find({
    // 查询 `likes` 属性值加 1 等于 4 的所有记录
    likes: Raw("1 + likes = 4")
});

总结性案例:

const queryBuild = db.manager
      .getRepository(user)
      .createQueryBuilder("f")
      // 连接faqAnswers表,别名为 a,将user的tenantIds属性值,传入faqAnswers表
      .leftJoinAndSelect("f.faqAnswers", "a", "a.tenantId in (:...tenantIds)", {
        tenantIds,
      })
      // 连接faqRelations表,取别名为 r
      .leftJoin("f.faqRelations", "r")
      .leftJoin("a.faqLabels", "al")
      // 查询`user`实体类的`id`属性等于`id`
      .where("f.id = :id", { id })
      // 指定查询返回的结果,就是几天表中的 下面的属性
      .select([
        "f.id",
        "f.question",
        "f.validBeginTime",
        "f.validEndTime",
        "f.link",
        "f.status",
        "f.CategoryId",
        "f.tenantId",
        "a.id",
        "a.answer",
        "a.link",
        "a.status",
        "a.FaqId",
        "a.tenantId",
        "al.LabelId",
      ]);
    const faq: any & Faq = await queryBuild.getOne();
  1. .getRepository(user) 使用user实体类的仓库对象作为查询的起点,返回一个QueryBuilder对象。

  2. .createQueryBuilder("f")user实体类的仓库对象上创建一个查询构建器对象,并指定别名为f

  3. .leftJoinAndSelect("f.faqAnswers", "a", "a.tenantId in (:...tenantIds)", {tenantIds}) 执行一个左连接,连接user实体类的faqAnswers属性,使用别名a表示连接后的结果,"a.tenantId in (:...tenantIds)"表示连接条件,将tenantIds中的值作为连接条件的参数传入。

  4. .leftJoin("f.faqRelations", "r") 执行一个左连接,连接user实体类的faqRelations属性,使用别名r表示连接后的结果。

  5. .leftJoin("a.faqLabels", "al") 执行一个左连接,连接faqAnswers实体类的faqLabels属性,使用别名al表示连接后的结果。

  6. .where("f.id = :id", { id }) 添加查询条件,查询user实体类的id属性等于id

  7. .select([...]) 指定查询的结果集,包含了Faq实体类和faqAnswers实体类的所有属性,以及faqLabels实体类的LabelId属性。

  8. const fff: any & user = await queryBuild.getOne(); 执行查询并获取查询结果,将查询结果赋值给fff变量。getOne()方法表示只获取一条满足查询条件的数据,返回一个Promise对象,查询结果的类型为any & user,即user实体类的所有属性加上any类型。

如何连接到数据库