Skip to content

Commit 3323467

Browse files
authored
Release Query.limitToLast(n) (#2321)
* [1/3] Query/Target split -- create Target and make remote/ and local/ work with Target. (#2254) * [2/3] Query/Target split: make SyncEngine able to handle the mapping between Target and Query. (#2281) * [2.8/3] Add limitToLast implementation and tests. (#2296) * [3/3] Spec tests for limitToLast+multi-tab (#2300) * Add spec test for single client (#2313) * add change log for limitToLast * Address comments
1 parent ad9dc8d commit 3323467

36 files changed

+1499
-540
lines changed

packages/firebase/index.d.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8118,14 +8118,26 @@ declare namespace firebase.firestore {
81188118
): Query;
81198119

81208120
/**
8121-
* Creates and returns a new Query where the results are limited to the
8122-
* specified number of documents.
8121+
* Creates and returns a new Query that only returns the first matching
8122+
* documents.
81238123
*
81248124
* @param limit The maximum number of items to return.
81258125
* @return The created Query.
81268126
*/
81278127
limit(limit: number): Query;
81288128

8129+
/**
8130+
* Creates and returns a new Query that only returns the last matching
8131+
* documents.
8132+
*
8133+
* You must specify at least one `orderBy` clause for `limitToLast` queries,
8134+
* otherwise an exception will be thrown during execution.
8135+
*
8136+
* @param limit The maximum number of items to return.
8137+
* @return The created Query.
8138+
*/
8139+
limitToLast(limit: number): Query;
8140+
81298141
/**
81308142
* Creates and returns a new Query that starts at the provided document
81318143
* (inclusive). The starting position is relative to the order of the query.

packages/firestore-types/index.d.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,14 +1089,26 @@ export class Query {
10891089
): Query;
10901090

10911091
/**
1092-
* Creates and returns a new Query that's additionally limited to only
1093-
* return up to the specified number of documents.
1092+
* Creates and returns a new Query that only returns the first matching
1093+
* documents.
10941094
*
10951095
* @param limit The maximum number of items to return.
10961096
* @return The created Query.
10971097
*/
10981098
limit(limit: number): Query;
10991099

1100+
/**
1101+
* Creates and returns a new Query that only returns the last matching
1102+
* documents.
1103+
*
1104+
* Queries with `limitToLast` must have at least one `orderBy` clause on
1105+
* one of the document fields, or an Exception will be thrown during execution.
1106+
*
1107+
* @param limit The maximum number of items to return.
1108+
* @return The created Query.
1109+
*/
1110+
limitToLast(limit: number): Query;
1111+
11001112
/**
11011113
* Creates and returns a new Query that starts at the provided document
11021114
* (inclusive). The starting position is relative to the order of the query.

packages/firestore/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
`.where()`. `in` finds documents where a specified field’s value is IN a
66
specified array. `array-contains-any` finds documents where a specified field
77
is an array and contains ANY element of a specified array.
8+
- [feature] Added `Query.limitToLast(n: number)` , which returns the last
9+
`n` documents as the result.
810

911
# 1.6.3
1012
- [changed] Improved iOS 13 support by eliminating an additional crash in our

packages/firestore/src/api/database.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import {
7171
validateOptionalArgType,
7272
validateOptionalArrayElements,
7373
validateOptionNames,
74+
validatePositiveNumber,
7475
validateStringEnum,
7576
valueDescription
7677
} from '../util/input_validation';
@@ -1542,14 +1543,15 @@ export class Query implements firestore.Query {
15421543
limit(n: number): firestore.Query {
15431544
validateExactNumberOfArgs('Query.limit', arguments, 1);
15441545
validateArgType('Query.limit', 'number', 1, n);
1545-
if (n <= 0) {
1546-
throw new FirestoreError(
1547-
Code.INVALID_ARGUMENT,
1548-
`Invalid Query. Query limit (${n}) is invalid. Limit must be ` +
1549-
'positive.'
1550-
);
1551-
}
1552-
return new Query(this._query.withLimit(n), this.firestore);
1546+
validatePositiveNumber('Query.limit', 1, n);
1547+
return new Query(this._query.withLimitToFirst(n), this.firestore);
1548+
}
1549+
1550+
limitToLast(n: number): firestore.Query {
1551+
validateExactNumberOfArgs('Query.limitToLast', arguments, 1);
1552+
validateArgType('Query.limitToLast', 'number', 1, n);
1553+
validatePositiveNumber('Query.limitToLast', 1, n);
1554+
return new Query(this._query.withLimitToLast(n), this.firestore);
15531555
}
15541556

15551557
startAt(
@@ -1829,6 +1831,7 @@ export class Query implements firestore.Query {
18291831
complete: args[currArg + 2] as CompleteFn
18301832
};
18311833
}
1834+
this.validateHasExplicitOrderByForLimitToLast(this._query);
18321835
return this.onSnapshotInternal(options, observer);
18331836
}
18341837

@@ -1864,9 +1867,19 @@ export class Query implements firestore.Query {
18641867
};
18651868
}
18661869

1870+
private validateHasExplicitOrderByForLimitToLast(query: InternalQuery): void {
1871+
if (query.hasLimitToLast() && query.explicitOrderBy.length === 0) {
1872+
throw new FirestoreError(
1873+
Code.UNIMPLEMENTED,
1874+
'limitToLast() queries require specifying at least one orderBy() clause'
1875+
);
1876+
}
1877+
}
1878+
18671879
get(options?: firestore.GetOptions): Promise<firestore.QuerySnapshot> {
18681880
validateBetweenNumberOfArgs('Query.get', arguments, 0, 1);
18691881
validateGetOptions('Query.get', options);
1882+
this.validateHasExplicitOrderByForLimitToLast(this._query);
18701883
return new Promise(
18711884
(resolve: Resolver<firestore.QuerySnapshot>, reject: Rejecter) => {
18721885
if (options && options.source === 'cache') {

0 commit comments

Comments
 (0)