Skip to content

Commit

Permalink
feat(database): support optional endAt/equalTo key (#838)
Browse files Browse the repository at this point in the history
Closes #837
  • Loading branch information
cartant authored and davideast committed Feb 21, 2017
1 parent b85147d commit e146492
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 4 deletions.
6 changes: 3 additions & 3 deletions docs/4-querying-lists.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ const queryObservable = af.database.list('/items', {
| `orderByKey` | Boolean to order by Firebase Database keys. |
| `orderByPriority` | Boolean to order by Firebase Database priority. |
| `orderByValue` | Specify a value to order by. |
| `equalTo` | Limit list to items that contain certain value. |
| `equalTo` <sup>1</sup> | Limit list to items that contain certain value. |
| `limitToFirst` | Sets the maximum number of items to return from the beginning of the ordered list of results. |
| `limitToLast` | Sets the maximum number of items to return from the end of the ordered list of results. |
| `startAt` <sup>1</sup> | Return items greater than or equal to the specified key or value, depending on the order-by method chosen. |
| `endAt` | Return items less than or equal to the specified key or value, depending on the order-by method chosen. |
| `endAt` <sup>1</sup> | Return items less than or equal to the specified key or value, depending on the order-by method chosen. |

<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' }`
<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' }`.

## Invalid query combinations

Expand Down
80 changes: 80 additions & 0 deletions src/database/firebase_list_factory.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,86 @@ describe('FirebaseListFactory', () => {

});

describe('equalTo(value, key)', () => {

it('should support the optional key parameter to equalTo', (done) => {

questions.$ref.ref.set({
val1: Object.assign({}, val1, { data: 0 }),
val2: Object.assign({}, val2, { data: 0 }),
val3: Object.assign({}, val3, { data: 0 })
})
.then(() => {

let query1 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
query: {
orderByChild: 'data',
equalTo: { value: 0 }
}
});
query1 = take.call(query1, 1);
query1 = toPromise.call(query1);

let query2 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
query: {
orderByChild: 'data',
equalTo: { value: 0, key: 'val2' }
}
});
query2 = take.call(query2, 1);
query2 = toPromise.call(query2);

Promise.all([query1, query2]).then(([list1, list2]) => {
expect(list1.map(i => i.$key)).toEqual(['val1', 'val2', 'val3']);
expect(list2.map(i => i.$key)).toEqual(['val2']);
done();
});
})
.catch(done.fail);
});

});

describe('endAt(value, key)', () => {

it('should support the optional key parameter to endAt', (done) => {

questions.$ref.ref.set({
val1: Object.assign({}, val1, { data: 0 }),
val2: Object.assign({}, val2, { data: 0 }),
val3: Object.assign({}, val3, { data: 0 })
})
.then(() => {

let query1 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
query: {
orderByChild: 'data',
endAt: { value: 0 }
}
});
query1 = take.call(query1, 1);
query1 = toPromise.call(query1);

let query2 = FirebaseListFactory(`${rootDatabaseUrl}/questions`, {
query: {
orderByChild: 'data',
endAt: { value: 0, key: 'val2' }
}
});
query2 = take.call(query2, 1);
query2 = toPromise.call(query2);

Promise.all([query1, query2]).then(([list1, list2]) => {
expect(list1.map(i => i.$key)).toEqual(['val1', 'val2', 'val3']);
expect(list2.map(i => i.$key)).toEqual(['val1', 'val2']);
done();
});
})
.catch(done.fail);
});

});

describe('observable queries (issue #830)', () => {

it('should not emit the results of previous queries', (done) => {
Expand Down
10 changes: 9 additions & 1 deletion src/database/firebase_list_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ export function FirebaseListFactory (

// check equalTo
if (utils.hasKey(query, "equalTo")) {
queried = queried.equalTo(query.equalTo);
if (utils.hasKey(query.equalTo, "value")) {
queried = queried.equalTo(query.equalTo.value, query.equalTo.key);
} else {
queried = queried.equalTo(query.equalTo);
}

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

if (utils.hasKey(query, "endAt")) {
if (utils.hasKey(query.endAt, "value")) {
queried = queried.endAt(query.endAt.value, query.endAt.key);
} else {
queried = queried.endAt(query.endAt);
}
}

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

0 comments on commit e146492

Please sign in to comment.