Skip to content

Commit e146492

Browse files
cartantdavideast
authored andcommitted
feat(database): support optional endAt/equalTo key (#838)
Closes #837
1 parent b85147d commit e146492

File tree

3 files changed

+92
-4
lines changed

3 files changed

+92
-4
lines changed

docs/4-querying-lists.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ const queryObservable = af.database.list('/items', {
2525
| `orderByKey` | Boolean to order by Firebase Database keys. |
2626
| `orderByPriority` | Boolean to order by Firebase Database priority. |
2727
| `orderByValue` | Specify a value to order by. |
28-
| `equalTo` | Limit list to items that contain certain value. |
28+
| `equalTo` <sup>1</sup> | Limit list to items that contain certain value. |
2929
| `limitToFirst` | Sets the maximum number of items to return from the beginning of the ordered list of results. |
3030
| `limitToLast` | Sets the maximum number of items to return from the end of the ordered list of results. |
3131
| `startAt` <sup>1</sup> | Return items greater than or equal to the specified key or value, depending on the order-by method chosen. |
32-
| `endAt` | Return items less than or equal to the specified key or value, depending on the order-by method chosen. |
32+
| `endAt` <sup>1</sup> | Return items less than or equal to the specified key or value, depending on the order-by method chosen. |
3333

34-
<sup>1</sup> The Firebase SDK supports [an optional `key` parameter](https://firebase.google.com/docs/reference/js/firebase.database.Reference#startAt) when ordering by child, value, or priority. You can specify the `key` parameter using `startAt: { value: 'some-value', key: 'some-key' }`
34+
<sup>1</sup> The Firebase SDK supports an optional `key` parameter for [`startAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#startAt), [`endAt`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#endAt), and [`equalTo`](https://firebase.google.com/docs/reference/js/firebase.database.Reference#equalTo) when ordering by child, value, or priority. You can specify the `key` parameter using an object literal that contains the `value` and the `key`. For example: `startAt: { value: 'some-value', key: 'some-key' }`.
3535

3636
## Invalid query combinations
3737

src/database/firebase_list_factory.spec.ts

+80
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,86 @@ describe('FirebaseListFactory', () => {
761761

762762
});
763763

764+
describe('equalTo(value, key)', () => {
765+
766+
it('should support the optional key parameter to equalTo', (done) => {
767+
768+
questions.$ref.ref.set({
769+
val1: Object.assign({}, val1, { data: 0 }),
770+
val2: Object.assign({}, val2, { data: 0 }),
771+
val3: Object.assign({}, val3, { data: 0 })
772+
})
773+
.then(() => {
774+
775+
let query1 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
776+
query: {
777+
orderByChild: 'data',
778+
equalTo: { value: 0 }
779+
}
780+
});
781+
query1 = take.call(query1, 1);
782+
query1 = toPromise.call(query1);
783+
784+
let query2 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
785+
query: {
786+
orderByChild: 'data',
787+
equalTo: { value: 0, key: 'val2' }
788+
}
789+
});
790+
query2 = take.call(query2, 1);
791+
query2 = toPromise.call(query2);
792+
793+
Promise.all([query1, query2]).then(([list1, list2]) => {
794+
expect(list1.map(i => i.$key)).toEqual(['val1', 'val2', 'val3']);
795+
expect(list2.map(i => i.$key)).toEqual(['val2']);
796+
done();
797+
});
798+
})
799+
.catch(done.fail);
800+
});
801+
802+
});
803+
804+
describe('endAt(value, key)', () => {
805+
806+
it('should support the optional key parameter to endAt', (done) => {
807+
808+
questions.$ref.ref.set({
809+
val1: Object.assign({}, val1, { data: 0 }),
810+
val2: Object.assign({}, val2, { data: 0 }),
811+
val3: Object.assign({}, val3, { data: 0 })
812+
})
813+
.then(() => {
814+
815+
let query1 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
816+
query: {
817+
orderByChild: 'data',
818+
endAt: { value: 0 }
819+
}
820+
});
821+
query1 = take.call(query1, 1);
822+
query1 = toPromise.call(query1);
823+
824+
let query2 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
825+
query: {
826+
orderByChild: 'data',
827+
endAt: { value: 0, key: 'val2' }
828+
}
829+
});
830+
query2 = take.call(query2, 1);
831+
query2 = toPromise.call(query2);
832+
833+
Promise.all([query1, query2]).then(([list1, list2]) => {
834+
expect(list1.map(i => i.$key)).toEqual(['val1', 'val2', 'val3']);
835+
expect(list2.map(i => i.$key)).toEqual(['val1', 'val2']);
836+
done();
837+
});
838+
})
839+
.catch(done.fail);
840+
});
841+
842+
});
843+
764844
describe('observable queries (issue #830)', () => {
765845

766846
it('should not emit the results of previous queries', (done) => {

src/database/firebase_list_factory.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ export function FirebaseListFactory (
5050

5151
// check equalTo
5252
if (utils.hasKey(query, "equalTo")) {
53-
queried = queried.equalTo(query.equalTo);
53+
if (utils.hasKey(query.equalTo, "value")) {
54+
queried = queried.equalTo(query.equalTo.value, query.equalTo.key);
55+
} else {
56+
queried = queried.equalTo(query.equalTo);
57+
}
5458

5559
if (utils.hasKey(query, "startAt") || utils.hasKey(query, "endAt")) {
5660
throw new Error('Query Error: Cannot use startAt or endAt with equalTo.');
@@ -78,7 +82,11 @@ export function FirebaseListFactory (
7882
}
7983

8084
if (utils.hasKey(query, "endAt")) {
85+
if (utils.hasKey(query.endAt, "value")) {
86+
queried = queried.endAt(query.endAt.value, query.endAt.key);
87+
} else {
8188
queried = queried.endAt(query.endAt);
89+
}
8290
}
8391

8492
if (!utils.isNil(query.limitToFirst) && query.limitToLast) {

0 commit comments

Comments
 (0)