Skip to content

Commit c6b6198

Browse files
update sequence aggregation doc to use extension properties
1 parent 6c074d9 commit c6b6198

File tree

2 files changed

+18
-36
lines changed

2 files changed

+18
-36
lines changed

docs/source/en/sequence-aggregation.md

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ inline fun <E : Any, T : BaseTable<E>, C : Any> EntitySequence<E, T>.aggregateCo
2121
It's a terminal operation, and it accepts a closure as its parameter, in which we need to return an aggregate expression. Ktorm will create an aggregate query, using the current filter condition and selecting the aggregate expression specified by us, then execute the query and obtain the aggregate result. The following code obtains the max salary in department 1:
2222

2323
```kotlin
24-
val max = database
25-
.sequenceOf(Employees, withReferences = false)
24+
val max = database.employees
2625
.filter { it.departmentId eq 1 }
2726
.aggregateColumns { max(it.salary) }
2827
```
2928

3029
If we want to aggregate two or more columns, we can change to `aggregateColumns2` or `aggregateColumns3`, then we need to wrap our aggregate expressions by `Pair` or `Triple` in the closure, and the function's return type becomes `Pair<C1?, C2?>` or `Triple<C1?, C2?, C3?>`. The example below obtains the average and the range of salaries in department 1:
3130

3231
```kotlin
33-
val (avg, diff) = database
34-
.sequenceOf(Employees, withReferences = false)
32+
val (avg, diff) = database.employees
3533
.filter { it.departmentId eq 1 }
3634
.aggregateColumns2 { Pair(avg(it.salary), max(it.salary) - min(it.salary)) }
3735
```
@@ -74,14 +72,13 @@ inline fun <E : Any, K> EntitySequence<E, *>.groupBy(
7472
Obviously, `groupBy` is a terminal operation, it will execute the internal query and iterate the query results right now, then extract a grouping key by the `keySelector` closure for each element, finally collect them into the groups they are belonging to. The following code obtains all the employees and groups them by their departments:
7573

7674
```kotlin
77-
val employees = database.sequenceOf(Employees).groupBy { it.department.id }
75+
val employees = database.employees.groupBy { it.department.id }
7876
```
7977

8078
Here, the type of `employees` is `Map<Int, List<Employee>>`, in which the keys are departments' IDs, and the values are the lists of employees belonging to the departments. Now we have the employees' data for every department, we are able to do some aggregate calculations over the data. The following code calculates the average salaries for each department:
8179

8280
```kotlin
83-
val averageSalaries = database
84-
.sequenceOf(Employees)
81+
val averageSalaries = database.employees
8582
.groupBy { it.department.id }
8683
.mapValues { (_, employees) -> employees.map { it.salary }.average() }
8784
```
@@ -91,7 +88,6 @@ But, unfortunately, the aggregate calculation here is performed inside the JVM,
9188
```sql
9289
select *
9390
from t_employee
94-
left join t_department _ref0 on t_employee.department_id = _ref0.id
9591
```
9692

9793
Here, the only thing we need is the average salaries, but we still have to obtain all the employees' data from the database. The performance issue may be intolerable in most cases. It'll be better for us to generate proper SQLs using *group by* clauses and aggregate functions, and move the aggregate calculations back to the database. To solve this problem, we need to use the `groupingBy` function.
@@ -130,8 +126,7 @@ inline fun <E : Any, T : BaseTable<E>, K : Any, C : Any> EntityGrouping<E, T, K>
130126
Similar to the `aggregateColumns` of `EntitySequence`, it's a terminal operation, and it accepts a closure as its parameter, in which we should return an aggregate expression. Ktorm will create an aggregate query, using the current filter condition and the grouping key, selecting the aggregate expression specified by us, then execute the query and obtain the aggregate results. Its return type is `Map<K?, C?>`, in which the keys are our grouping keys, and the values are the aggregate results for the groups. The following code obtains the average salaries for each department:
131127

132128
```kotlin
133-
val averageSalaries = database
134-
.sequenceOf(Employees, withReferences = false)
129+
val averageSalaries = database.employees
135130
.groupingBy { it.departmentId }
136131
.aggregateColumns { avg(it.salary) }
137132
```
@@ -147,8 +142,7 @@ group by t_employee.department_id
147142
If we want to aggregate two or more columns, we can change to `aggregateColumns2` or `aggregateColumns3`, then we need to wrap our aggregate expressions by `Pair` or `Triple` in the closure, and the function’s return type becomes `Map<K?, Pair<C1?, C2?>>` or `Map<K?, Triple<C1?, C2?, C3?>>`. The following code prints the averages and the ranges of salaries for each department:
148143

149144
```kotlin
150-
database
151-
.sequenceOf(Employees, withReferences = false)
145+
database.employees
152146
.groupingBy { it.departmentId }
153147
.aggregateColumns2 { Pair(avg(it.salary), max(it.salary) - min(it.salary)) }
154148
.forEach { departmentId, (avg, diff) ->
@@ -177,17 +171,15 @@ Additionally, Ktorm also provides many convenient helper functions, they are all
177171
With these functions, we can write the code below to obtain average salaries for each department:
178172

179173
```kotlin
180-
val averageSalaries = database
181-
.sequenceOf(Employees)
174+
val averageSalaries = database.employees
182175
.groupingBy { it.departmentId }
183176
.eachAverageBy { it.salary }
184177
```
185178

186179
Besides, Ktorm also provides `aggregate`, `fold`, `reduce`, they have the same names as the extension functions of `kotlin.collections.Grouping`, and the usages are totally the same. The following code calculates the total salaries for each department:
187180

188181
```kotlin
189-
val totalSalaries = database
190-
.sequenceOf(Employees)
182+
val totalSalaries = database.employees
191183
.groupingBy { it.departmentId }
192184
.fold(0L) { acc, employee ->
193185
acc + employee.salary
@@ -197,8 +189,7 @@ val totalSalaries = database
197189
Of course, if only the total salaries are needed, we don’t have to write codes in that way. Because the performance is really poor, as all employees are obtained from the database. Here we just show you the usage of the `fold` function. It’s better to use `eachSumBy`:
198190

199191
```kotlin
200-
val totalSalaries = database
201-
.sequenceOf(Employees)
192+
val totalSalaries = database.employees
202193
.groupingBy { it.departmentId }
203194
.eachSumBy { it.salary }
204195
```

docs/source/zh-cn/sequence-aggregation.md

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,15 @@ inline fun <E : Any, T : BaseTable<E>, C : Any> EntitySequence<E, T>.aggregateCo
2121
这是一个终止操作,它接收一个闭包作为参数,在闭包中,我们需要返回一个聚合表达式。Ktorm 会使用我们返回的聚合表达式,根据当前序列的查询条件创建一个聚合查询, 然后执行这个查询,获取聚合的结果。下面的代码获取部门 1 中工资的最大值:
2222

2323
```kotlin
24-
val max = database
25-
.sequenceOf(Employees, withReferences = false)
24+
val max = database.employees
2625
.filter { it.departmentId eq 1 }
2726
.aggregateColumns { max(it.salary) }
2827
```
2928

3029
如果你希望同时获取多个聚合结果,可以改用 `aggregateColumns2``aggregateColumns3` 函数,这时我们需要在闭包中使用 `Pair``Triple` 包装我们的这些聚合表达式,函数的返回值也相应变成了 `Pair<C1?, C2?>``Triple<C1?, C2?, C3?>`。下面的例子获取部门 1 中工资的平均值和极差:
3130

3231
```kotlin
33-
val (avg, diff) = database
34-
.sequenceOf(Employees, withReferences = false)
32+
val (avg, diff) = database.employees
3533
.filter { it.departmentId eq 1 }
3634
.aggregateColumns2 { Pair(avg(it.salary), max(it.salary) - min(it.salary)) }
3735
```
@@ -74,14 +72,13 @@ inline fun <E : Any, K> EntitySequence<E, *>.groupBy(
7472
很明显,这是一个终止操作,它会马上执行查询,迭代所有返回的实体对象,通过闭包传入的 `keySelector` 获取实体对象的分组 key,按照这个 key 对它们进行分组,将每个元素添加到所属组的集合中。下面的代码获取所有员工对象,并按部门进行分组:
7573

7674
```kotlin
77-
val employees = database.sequenceOf(Employees).groupBy { it.department.id }
75+
val employees = database.employees.groupBy { it.department.id }
7876
```
7977

8078
在这里,`employees` 的类型是 `Map<Int, List<Employee>>`,其中,key 是部门 ID,value 是在这个部门下的所有员工的列表。现在我们已经有了所有部门下的员工列表,然后就可以使用这些数据进行一些聚合计算。比如下面的代码可以计算出所有部门的平均工资:
8179

8280
```kotlin
83-
val averageSalaries = database
84-
.sequenceOf(Employees)
81+
val averageSalaries = database.employees
8582
.groupBy { it.department.id }
8683
.mapValues { (_, employees) -> employees.map { it.salary }.average() }
8784
```
@@ -91,7 +88,6 @@ val averageSalaries = database
9188
````sql
9289
select *
9390
from t_employee
94-
left join t_department _ref0 on t_employee.department_id = _ref0.id
9591
````
9692

9793
如果仅仅需要计算平均工资,却不得不获取数据库中的所有员工数据,这个性能开销在大多数时候都是不可忍受的。那么我们能不能利用 SQL 中自带的 group by 和聚合功能,生成恰当的 SQL,让数据库来帮我们进行聚合计算呢?这时我们应该使用下面将要介绍的 `groupingBy` 函数。
@@ -130,8 +126,7 @@ inline fun <E : Any, T : BaseTable<E>, K : Any, C : Any> EntityGrouping<E, T, K>
130126
`EntitySequence``aggregateColumns` 函数类似,这是一个终止操作,它接收一个闭包作为参数,在闭包中,我们需要返回一个聚合表达式。Ktorm 会使用我们返回的聚合表达式,根据当前序列的查询条件和分组条件创建一个聚合查询,然后执行这个查询,获取聚合的结果。它的返回值是 `Map<K?, C?>`,其中,key 是我们的分组列的值,value 是该组中的聚合结果。下面的代码可以获取所有部门的平均工资:
131127

132128
```kotlin
133-
val averageSalaries = database
134-
.sequenceOf(Employees, withReferences = false)
129+
val averageSalaries = database.employees
135130
.groupingBy { it.departmentId }
136131
.aggregateColumns { avg(it.salary) }
137132
```
@@ -147,8 +142,7 @@ group by t_employee.department_id
147142
如果你希望同时获取多个聚合结果,可以改用 `aggregateColumns2``aggregateColumns3` 函数,这时我们需要在闭包中使用 `Pair``Triple` 包装我们的这些聚合表达式,函数的返回值也相应变成了 `Map<K?, Pair<C1?, C2?>>``Map<K?, Triple<C1?, C2?, C3?>>`。下面的例子会打印出所有部门工资的平均值和极差:
148143

149144
```kotlin
150-
database
151-
.sequenceOf(Employees, withReferences = false)
145+
database.employees
152146
.groupingBy { it.departmentId }
153147
.aggregateColumns2 { Pair(avg(it.salary), max(it.salary) - min(it.salary)) }
154148
.forEach { departmentId, (avg, diff) ->
@@ -177,17 +171,15 @@ group by t_employee.department_id
177171
有了这些辅助函数,上面获取所有部门平均工资的代码就可以改写成:
178172

179173
```kotlin
180-
val averageSalaries = database
181-
.sequenceOf(Employees)
174+
val averageSalaries = database.employees
182175
.groupingBy { it.departmentId }
183176
.eachAverageBy { it.salary }
184177
```
185178

186179
除此之外,Ktorm 还提供了 `aggregate``fold``reduce` 等函数,它们与 `kotlin.collections.Grouping` 的相应函数同名,功能也完全一样。下面的代码使用 `fold` 函数计算每个部门工资的总和:
187180

188181
```kotlin
189-
val totalSalaries = database
190-
.sequenceOf(Employees)
182+
val totalSalaries = database.employees
191183
.groupingBy { it.departmentId }
192184
.fold(0L) { acc, employee ->
193185
acc + employee.salary
@@ -197,8 +189,7 @@ val totalSalaries = database
197189
当然,如果仅仅为了获得工资总和,我们没必要这样做。这是性能低下的写法,它会查询出所有员工的数据,然后对它们进行迭代,这里仅用作示范,更好的写法是使用 `eachSumBy` 函数:
198190

199191
```kotlin
200-
val totalSalaries = database
201-
.sequenceOf(Employees)
192+
val totalSalaries = database.employees
202193
.groupingBy { it.departmentId }
203194
.eachSumBy { it.salary }
204195
```

0 commit comments

Comments
 (0)