解决SELECT list is not in GROUP BY clause and contains nonaggregated column ‘testdata.logs.id’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
前言:
nest/typeorm报错
SELECT list is not in GROUP BY clause and contains nonaggregated column ‘testdata.logs.id’ which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
1.返回结果区别
getMany()
和 getRawMany()
返回的结果有一些显著的区别,根据你的具体需求,你可以选择使用其中之一。
1.getMany()
返回的结果:
- 返回结果为 TypeORM 实体对象的集合,即经过实体映射(entity mapping)的结果。
- 返回的是符合查询条件的实体对象数组,每个元素都是一个经过 TypeORM 映射的实体对象。这意味着你可以直接从结果中访问实体对象的属性,并对其进行操作。
- 适用于一般的实体查询及与数据库表对应的操作,例如数据的读取、更新、删除等。
2.getRawMany()
返回的结果:
- 返回结果为原始的数据库查询结果,即未经过实体映射的结果。
- 返回的是一组普通的 JavaScript 对象数组,每个元素代表了数据库查询结果中的一行记录。这意味着你需要手动处理和操作这些原始的查询结果。
- 适用于需要执行原生的 SQL 查询、需要对原始数据进行聚合、统计、复杂数据操作等情况。
总的来说,getMany()
适用于从数据库中获取类型化的实体对象集合进行操作,而 getRawMany()
适用于执行原生的 SQL 查询及对原始数据进行操作
2.看个例子:
在TypeORM中,getRawMany()
和 getMany()
是两种执行查询并返回结果的方法,它们之间有一些关键的区别。
getRawMany()
getRawMany()
方法返回的是原始的数据库查询结果,这意味着它返回的是一组普通的 JavaScript 对象,而不是经过实体映射(entity mapping)的 TypeORM 实体对象。这对于复杂的查询或者需要直接操作原始数据的情况非常有用。当你执行原生查询,或者需要聚合函数的结果时,这个方法特别有用。
const result = await entityManager.createQueryBuilder().select("user.name", "userName").addSelect("COUNT(*)", "postCount").from(User, "user").leftJoin("user.posts", "post").groupBy("user.id").getRawMany();
getMany()
getMany()
方法返回的是经过实体映射(entity mapping)的 TypeORM 实体对象的数组。这意味着返回的结果会被 TypeORM 映射为你定义的实体类的实例。这对于常规的数据库操作和数据持久化非常有用。
const users = await userRepository.find();
总的来说,getRawMany()
适用于需要直接操作原始数据或者复杂查询的情况,而 getMany()
适用于常规的数据库操作和通过实体对象进行处理的情况。
当使用 TypeORM 进行查询时,你可以根据具体的需求来选择使用 getMany()
或 getRawMany()
。
1.适合使用 getMany()
的情况:
-
常规查询:当你希望查询并返回和 TypeORM 实体对象对应的结果时,使用
getMany()
是最直接的方法。比如:const users = await userRepository.find();
-
实体关联查询:当你希望获取实体及其关联的其他实体对象时,如一对多关系中的子实体,或使用
LEFT JOIN
和INNER JOIN
查询时,也可以使用getMany()
来获取实体及其关联的多个实体对象。const usersWithPosts = userRepository.find({ relations: ['posts'] });
2.适合使用 getRawMany()
的情况:
-
原生查询:当你需要执行原生的 SQL 查询,或者使用数据库特定的函数或特性时,通常会选择使用
getRawMany()
来获取原始的查询结果。const result = await entityManager.createQueryBuilder().select("user.name", "userName").addSelect("COUNT(*)", "postCount").from(User, "user").leftJoin("user.posts", "post").groupBy("user.id").getRawMany();
-
对于聚合函数的使用:当你需要使用聚合函数(如 COUNT、SUM 等)进行查询时,
getRawMany()
可以直接返回原始的聚合结果。const postCounts = await postRepository.createQueryBuilder().select("COUNT(*)", "postCount").getRawMany();
总的来说,当你需要返回实体对象的集合时,使用 getMany()
;而当需要执行原生的 SQL 查询,或者对原始数据进行操作时,使用 getRawMany()
。
3.我犯的错
-
一号查询
async getLogsList(): Promise<any> {return this.logRepository.createQueryBuilder('logs').select('logs.response').addSelect('COUNT(logs.response)', 'count').leftJoinAndSelect('logs.user', 'user').where('userId = :id', { id: 2 }).groupBy('logs.response').getRawMany(); // 如果你使用原始查询而不是实体的话,使用getRawMany()}
-
二号查询
async getLogsList(): Promise<any> {return (this.logRepository.createQueryBuilder('logs').select('logs.response').addSelect('COUNT(logs.response)', 'count').leftJoinAndSelect('logs.user', 'user').where('userId = :id', { id: 2 }).groupBy('logs.response').getMany());}
二号查询虽然你使用了getMany()
,但是查询语句中使用了聚合函数COUNT
,这是导致使用 getMany()
出现问题的原因。
getMany()
用于获取实体对象的集合,而 COUNT
是一个聚合函数,它会计算匹配条件的行数,并返回一个单独的结果。在TypeORM中,getMany()
适用于简单的实体查询,但并不适用于需要使用聚合函数的情况。
在二号示例中,,addSelect('COUNT(logs.response)', 'count')
使用了聚合函数来统计logs
表中response
字段的数量。因此,使用 getMany()
无法正确地返回聚合后的结果。相反,你应该使用 getRawMany()
来获取原始的查询结果,而不是实体对象的集合。
所以,应该使用 .getRawMany()
来获取聚合函数的结果,就像下面这样:
async getLogsList(): Promise<any> {return (this.logRepository.createQueryBuilder('logs').select('logs.response').addSelect('COUNT(logs.response)', 'count').leftJoinAndSelect('logs.user', 'user').where('userId=:id', { id: 2 }).groupBy('logs.response').getRawMany());
}
通过使用 .getRawMany()
,能够正确地获取到聚合函数的结果,而不是尝试将聚合的结果映射为实体对象的集合。