Skip to content

Commit 6fba9bc

Browse files
committed
feat: add order by feature
1 parent a033a40 commit 6fba9bc

File tree

4 files changed

+145
-2
lines changed

4 files changed

+145
-2
lines changed

src/query/Options.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ export interface WhereGroup {
1111
or?: Where[]
1212
}
1313

14+
export interface Order {
15+
field: string
16+
direction: OrderDirection
17+
}
18+
19+
export type OrderDirection = 'asc' | 'desc'
20+
1421
export interface EagerLoad {
1522
[name: string]: EagerLoadConstraint
1623
}

src/query/Query.ts

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
import { Store } from 'vuex'
2-
import { isArray, isEmpty, groupBy } from '../support/Utils'
2+
import { isArray, isEmpty, orderBy, groupBy } from '../support/Utils'
33
import { Element, Item, Collection } from '../data/Data'
44
import { Relation } from '../model/attributes/relations/Relation'
55
import { Model } from '../model/Model'
66
import { Connection } from '../connection/Connection'
7-
import { Where, EagerLoad, EagerLoadConstraint } from './Options'
7+
import {
8+
Where,
9+
Order,
10+
OrderDirection,
11+
EagerLoad,
12+
EagerLoadConstraint
13+
} from './Options'
814

915
export class Query<M extends Model = Model> {
1016
/**
@@ -22,6 +28,11 @@ export class Query<M extends Model = Model> {
2228
*/
2329
protected wheres: Where[] = []
2430

31+
/**
32+
* The orderings for the query.
33+
*/
34+
protected orders: Order[] = []
35+
2536
/**
2637
* The maximum number of records to return.
2738
*/
@@ -93,6 +104,15 @@ export class Query<M extends Model = Model> {
93104
return this
94105
}
95106

107+
/**
108+
* Add an "order by" clause to the query.
109+
*/
110+
orderBy(field: string, direction: OrderDirection = 'asc'): Query<M> {
111+
this.orders.push({ field, direction })
112+
113+
return this
114+
}
115+
96116
/**
97117
* Set the "take" value of the query.
98118
*/
@@ -203,6 +223,7 @@ export class Query<M extends Model = Model> {
203223
let models = this.getModels()
204224

205225
models = this.filterWhere(models)
226+
models = this.filterOrder(models)
206227
models = this.filterLimit(models)
207228

208229
return models
@@ -248,6 +269,20 @@ export class Query<M extends Model = Model> {
248269
return model[where.field] === where.value
249270
}
250271

272+
/**
273+
* Filter the given collection by the registered order conditions.
274+
*/
275+
protected filterOrder(models: Collection<M>): Collection<M> {
276+
if (this.orders.length === 0) {
277+
return models
278+
}
279+
280+
const fields = this.orders.map((order) => order.field)
281+
const directions = this.orders.map((order) => order.direction)
282+
283+
return orderBy(models, fields, directions)
284+
}
285+
251286
/**
252287
* Filter the given collection by the registered limit and offset values.
253288
*/

src/repository/Repository.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import { Model } from '../model/Model'
1212
import { Interpretation } from '../interpretation/Interpretation'
1313
import { Query } from '../query/Query'
14+
import { OrderDirection } from '../query/Options'
1415

1516
export type PersistMethod = 'insert' | 'merge'
1617

@@ -76,6 +77,13 @@ export class Repository<M extends Model> {
7677
return this.query().orWhere(field, value)
7778
}
7879

80+
/**
81+
* Add an "order by" clause to the query.
82+
*/
83+
orderBy(field: string, direction?: OrderDirection): Query<M> {
84+
return this.query().orderBy(field, direction)
85+
}
86+
7987
/**
8088
* Set the relationships that should be eager loaded.
8189
*/
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import {
2+
createStore,
3+
fillState,
4+
assertInstanceOf,
5+
assertModels
6+
} from 'test/Helpers'
7+
import { Model, Attr, Str, Num } from '@/index'
8+
9+
describe('feature/repository/retrieves_order_by', () => {
10+
class User extends Model {
11+
static entity = 'users'
12+
13+
@Attr() id!: any
14+
@Str('') name!: string
15+
@Num(0) age!: number
16+
}
17+
18+
it('can sort the records by the `order by` clause', () => {
19+
const store = createStore([User])
20+
21+
fillState(store, {
22+
users: {
23+
1: { id: 1, name: 'James', age: 40 },
24+
2: { id: 2, name: 'Andy', age: 30 },
25+
3: { id: 3, name: 'David', age: 20 }
26+
}
27+
})
28+
29+
const users = store.$repo(User).orderBy('name').get()
30+
31+
const expected = [
32+
{ id: 2, name: 'Andy', age: 30 },
33+
{ id: 3, name: 'David', age: 20 },
34+
{ id: 1, name: 'James', age: 40 }
35+
]
36+
37+
expect(users.length).toBe(3)
38+
assertInstanceOf(users, User)
39+
assertModels(users, expected)
40+
})
41+
42+
it('can sort the records by "desc" order', () => {
43+
const store = createStore([User])
44+
45+
fillState(store, {
46+
users: {
47+
1: { id: 1, name: 'James', age: 40 },
48+
2: { id: 2, name: 'Andy', age: 30 },
49+
3: { id: 3, name: 'David', age: 20 }
50+
}
51+
})
52+
53+
const users = store.$repo(User).orderBy('name', 'desc').get()
54+
55+
const expected = [
56+
{ id: 1, name: 'James', age: 40 },
57+
{ id: 3, name: 'David', age: 20 },
58+
{ id: 2, name: 'Andy', age: 30 }
59+
]
60+
61+
expect(users.length).toBe(3)
62+
assertInstanceOf(users, User)
63+
assertModels(users, expected)
64+
})
65+
66+
it('can combine multiple orders', () => {
67+
const store = createStore([User])
68+
69+
fillState(store, {
70+
users: {
71+
1: { id: 1, name: 'James', age: 40 },
72+
2: { id: 2, name: 'Andy', age: 30 },
73+
3: { id: 3, name: 'Andy', age: 20 },
74+
4: { id: 4, name: 'David', age: 20 },
75+
5: { id: 5, name: 'David', age: 50 }
76+
}
77+
})
78+
79+
const users = store.$repo(User).orderBy('name', 'desc').orderBy('age').get()
80+
81+
const expected = [
82+
{ id: 1, name: 'James', age: 40 },
83+
{ id: 4, name: 'David', age: 20 },
84+
{ id: 5, name: 'David', age: 50 },
85+
{ id: 3, name: 'Andy', age: 20 },
86+
{ id: 2, name: 'Andy', age: 30 }
87+
]
88+
89+
expect(users.length).toBe(5)
90+
assertInstanceOf(users, User)
91+
assertModels(users, expected)
92+
})
93+
})

0 commit comments

Comments
 (0)