TypeORM queryBuilder如何按数组字段长度对查询结果排序
你之前的排序逻辑不符合预期,是因为直接对Post.likes字段排序时,数据库会直接对比数组本身的内容,而非数组的长度。
要实现按数组长度排序,你可以直接在orderBy中调用对应数据库的数组长度计算函数,你使用的是支持原生数组类型的PostgreSQL(array: true为PG专属字段配置),可以用cardinality函数实现,示例代码如下:
const posts = await this.postsRepository .createQueryBuilder('post') .leftJoinAndSelect('post.author', 'author') .leftJoinAndSelect('author.avatar', 'avatar') // cardinality会返回数组的元素个数,空数组返回0,不会出现空值导致排序异常 .orderBy('cardinality(post.likes)', 'DESC') .getMany();
如果你的业务数据量较大,每次查询实时计算数组长度性能不足,可以新增预计算的生成列存储点赞数,还可以给该字段加索引进一步提升排序性能:
@Entity() export class Post { @PrimaryGeneratedColumn("uuid") public id?: string; @Column("text", { default: [], array: true }) public likes?: string[]; // 新增自动生成的点赞数字段,数据库会自动同步likes数组的长度 @Column({ type: 'int', generated: 'ALWAYS', asExpression: 'cardinality(likes)', nullable: false }) public likesCount: number; }
后续查询直接对likesCount字段排序即可:
.orderBy('post.likesCount', 'DESC')
如果你使用的是MySQL这类不支持原生数组、用JSON存储likes字段的数据库,可以把长度计算函数替换为JSON_LENGTH(post.likes)即可。
内容的提问来源于stack exchange,提问作者pakut2
相关产品推荐
相关产品推荐

