0
# Querying & Filtering
1
2
Advanced query capabilities with filtering, ordering, pagination, and aggregation. Supports both simple field queries and complex composite filters.
3
4
## Capabilities
5
6
### Basic Query Operations
7
8
Execute queries to retrieve documents with optional source specification.
9
10
```typescript { .api }
11
interface Query<T = FirebaseFirestoreTypes.DocumentData> {
12
/**
13
* Execute the query and get results
14
* @param options - Optional get options to specify data source
15
* @returns Promise resolving to query snapshot
16
*/
17
get(options?: FirebaseFirestoreTypes.GetOptions): Promise<FirebaseFirestoreTypes.QuerySnapshot<T>>;
18
19
/**
20
* Check if two queries are equal
21
* @param other - Other query to compare
22
* @returns True if queries are equal
23
*/
24
isEqual(other: FirebaseFirestoreTypes.Query): boolean;
25
}
26
27
interface QuerySnapshot<T = FirebaseFirestoreTypes.DocumentData> {
28
readonly docs: FirebaseFirestoreTypes.QueryDocumentSnapshot<T>[];
29
readonly empty: boolean;
30
readonly metadata: FirebaseFirestoreTypes.SnapshotMetadata;
31
readonly query: FirebaseFirestoreTypes.Query<T>;
32
readonly size: number;
33
34
/**
35
* Get array of document changes since last snapshot
36
* @param options - Optional listen options
37
* @returns Array of document changes
38
*/
39
docChanges(options?: FirebaseFirestoreTypes.SnapshotListenOptions): FirebaseFirestoreTypes.DocumentChange<T>[];
40
41
/**
42
* Iterate over all documents in the snapshot
43
* @param callback - Function to call for each document
44
* @param thisArg - Optional this context
45
*/
46
forEach(callback: (result: FirebaseFirestoreTypes.QueryDocumentSnapshot<T>) => void, thisArg?: any): void;
47
}
48
```
49
50
**Usage Examples:**
51
52
```typescript
53
import firestore from '@react-native-firebase/firestore';
54
55
// Execute basic query
56
const snapshot = await firestore().collection('users').get();
57
58
// Process results
59
snapshot.forEach(doc => {
60
console.log(doc.id, '=>', doc.data());
61
});
62
63
// Check if query returned results
64
if (!snapshot.empty) {
65
console.log(`Found ${snapshot.size} users`);
66
}
67
68
// Get from specific source
69
const serverSnapshot = await firestore()
70
.collection('users')
71
.get({ source: 'server' });
72
```
73
74
### Where Clauses
75
76
Filter documents based on field values using various comparison operators.
77
78
```typescript { .api }
79
/**
80
* Filter query results based on field values
81
* @param fieldPath - Field to filter on (string or FieldPath)
82
* @param opStr - Comparison operator
83
* @param value - Value to compare against
84
* @returns New query with filter applied
85
*/
86
where(fieldPath: keyof T | FirebaseFirestoreTypes.FieldPath, opStr: FirebaseFirestoreTypes.WhereFilterOp, value: any): FirebaseFirestoreTypes.Query<T>;
87
88
/**
89
* Apply a filter constraint to the query
90
* @param filter - Query filter constraint
91
* @returns New query with filter applied
92
*/
93
where(filter: FirebaseFirestoreTypes.QueryFilterConstraint): FirebaseFirestoreTypes.Query<T>;
94
95
type WhereFilterOp =
96
| '<' | '<=' | '==' | '>' | '>=' | '!='
97
| 'array-contains' | 'array-contains-any'
98
| 'in' | 'not-in';
99
```
100
101
**Usage Examples:**
102
103
```typescript
104
import firestore from '@react-native-firebase/firestore';
105
106
// Equal comparison
107
const activeUsers = await firestore()
108
.collection('users')
109
.where('active', '==', true)
110
.get();
111
112
// Numeric comparisons
113
const adultsQuery = firestore()
114
.collection('users')
115
.where('age', '>=', 18);
116
117
// Array operations
118
const moderatorsQuery = firestore()
119
.collection('users')
120
.where('roles', 'array-contains', 'moderator');
121
122
// In operator for multiple values
123
const specificUsersQuery = firestore()
124
.collection('users')
125
.where('userId', 'in', ['user1', 'user2', 'user3']);
126
127
// Not equal (requires composite index)
128
const nonAdminQuery = firestore()
129
.collection('users')
130
.where('role', '!=', 'admin');
131
132
// Using FieldPath for nested fields
133
const verifiedEmailQuery = firestore()
134
.collection('users')
135
.where(new firestore.FieldPath('profile', 'emailVerified'), '==', true);
136
137
// Chain multiple where clauses
138
const queryResults = await firestore()
139
.collection('users')
140
.where('active', '==', true)
141
.where('age', '>=', 18)
142
.where('city', '==', 'New York')
143
.get();
144
```
145
146
### Composite Filters
147
148
Combine multiple filter conditions using AND/OR logic.
149
150
```typescript { .api }
151
/**
152
* Create field filter constraint
153
* @param fieldPath - Field to filter on
154
* @param operator - Comparison operator
155
* @param value - Value to compare against
156
* @returns Query field filter constraint
157
*/
158
Filter(fieldPath: keyof T | FirebaseFirestoreTypes.FieldPath, operator: FirebaseFirestoreTypes.WhereFilterOp, value: any): FirebaseFirestoreTypes.QueryFieldFilterConstraint;
159
160
/**
161
* Combine filter constraints with AND logic
162
* @param queries - Filter constraints to combine
163
* @returns Composite AND filter constraint
164
*/
165
Filter.and(...queries: FirebaseFirestoreTypes.QueryFilterConstraint[]): FirebaseFirestoreTypes.QueryCompositeFilterConstraint;
166
167
/**
168
* Combine filter constraints with OR logic
169
* @param queries - Filter constraints to combine
170
* @returns Composite OR filter constraint
171
*/
172
Filter.or(...queries: FirebaseFirestoreTypes.QueryFilterConstraint[]): FirebaseFirestoreTypes.QueryCompositeFilterConstraint;
173
```
174
175
**Usage Examples:**
176
177
```typescript
178
import firestore, { Filter } from '@react-native-firebase/firestore';
179
180
// OR filter - users who are either admin or moderator
181
const adminOrModeratorQuery = firestore()
182
.collection('users')
183
.where(
184
Filter.or(
185
Filter('role', '==', 'admin'),
186
Filter('role', '==', 'moderator')
187
)
188
);
189
190
// AND filter - active users in New York
191
const activeNYUsersQuery = firestore()
192
.collection('users')
193
.where(
194
Filter.and(
195
Filter('active', '==', true),
196
Filter('city', '==', 'New York')
197
)
198
);
199
200
// Complex nested filters - (admin OR moderator) AND active
201
const complexQuery = firestore()
202
.collection('users')
203
.where(
204
Filter.and(
205
Filter.or(
206
Filter('role', '==', 'admin'),
207
Filter('role', '==', 'moderator')
208
),
209
Filter('active', '==', true)
210
)
211
);
212
```
213
214
### Ordering
215
216
Sort query results by one or more fields in ascending or descending order.
217
218
```typescript { .api }
219
/**
220
* Order query results by a field
221
* @param fieldPath - Field to order by (string or FieldPath)
222
* @param directionStr - Sort direction ('asc' or 'desc')
223
* @returns New query with ordering applied
224
*/
225
orderBy(fieldPath: keyof T | string | FirebaseFirestoreTypes.FieldPath, directionStr?: 'asc' | 'desc'): FirebaseFirestoreTypes.Query<T>;
226
```
227
228
**Usage Examples:**
229
230
```typescript
231
import firestore from '@react-native-firebase/firestore';
232
233
// Order by creation date (ascending by default)
234
const chronologicalQuery = firestore()
235
.collection('posts')
236
.orderBy('createdAt');
237
238
// Order by creation date descending (most recent first)
239
const recentPostsQuery = firestore()
240
.collection('posts')
241
.orderBy('createdAt', 'desc');
242
243
// Multiple ordering criteria
244
const sortedUsersQuery = firestore()
245
.collection('users')
246
.orderBy('lastName')
247
.orderBy('firstName')
248
.orderBy('createdAt', 'desc');
249
250
// Order by nested field
251
const sortedByProfileQuery = firestore()
252
.collection('users')
253
.orderBy(new firestore.FieldPath('profile', 'displayName'));
254
255
// Combine with filtering (requires composite index)
256
const filteredAndSortedQuery = await firestore()
257
.collection('users')
258
.where('active', '==', true)
259
.orderBy('lastLoginAt', 'desc')
260
.get();
261
```
262
263
### Pagination
264
265
Limit result sets and implement cursor-based pagination for large datasets.
266
267
```typescript { .api }
268
/**
269
* Limit the number of documents returned
270
* @param limit - Maximum number of documents to return
271
* @returns New query with limit applied
272
*/
273
limit(limit: number): FirebaseFirestoreTypes.Query<T>;
274
275
/**
276
* Limit to last N documents (requires orderBy)
277
* @param limitToLast - Number of documents from the end
278
* @returns New query with limit applied
279
*/
280
limitToLast(limitToLast: number): FirebaseFirestoreTypes.Query<T>;
281
282
/**
283
* Start results at a document snapshot
284
* @param snapshot - Document snapshot to start at
285
* @returns New query with cursor applied
286
*/
287
startAt(snapshot: FirebaseFirestoreTypes.DocumentSnapshot<T>): FirebaseFirestoreTypes.Query<T>;
288
289
/**
290
* Start results at field values
291
* @param fieldValues - Field values to start at
292
* @returns New query with cursor applied
293
*/
294
startAt(...fieldValues: any[]): FirebaseFirestoreTypes.Query<T>;
295
296
/**
297
* Start results after a document snapshot
298
* @param snapshot - Document snapshot to start after
299
* @returns New query with cursor applied
300
*/
301
startAfter(snapshot: FirebaseFirestoreTypes.DocumentSnapshot<T>): FirebaseFirestoreTypes.Query<T>;
302
303
/**
304
* Start results after field values
305
* @param fieldValues - Field values to start after
306
* @returns New query with cursor applied
307
*/
308
startAfter(...fieldValues: any[]): FirebaseFirestoreTypes.Query<T>;
309
310
/**
311
* End results at a document snapshot
312
* @param snapshot - Document snapshot to end at
313
* @returns New query with cursor applied
314
*/
315
endAt(snapshot: FirebaseFirestoreTypes.DocumentSnapshot<T>): FirebaseFirestoreTypes.Query<T>;
316
317
/**
318
* End results at field values
319
* @param fieldValues - Field values to end at
320
* @returns New query with cursor applied
321
*/
322
endAt(...fieldValues: any[]): FirebaseFirestoreTypes.Query<T>;
323
324
/**
325
* End results before a document snapshot
326
* @param snapshot - Document snapshot to end before
327
* @returns New query with cursor applied
328
*/
329
endBefore(snapshot: FirebaseFirestoreTypes.DocumentSnapshot<T>): FirebaseFirestoreTypes.Query<T>;
330
331
/**
332
* End results before field values
333
* @param fieldValues - Field values to end before
334
* @returns New query with cursor applied
335
*/
336
endBefore(...fieldValues: any[]): FirebaseFirestoreTypes.Query<T>;
337
```
338
339
**Usage Examples:**
340
341
```typescript
342
import firestore from '@react-native-firebase/firestore';
343
344
// Basic pagination - first page
345
const firstPageQuery = firestore()
346
.collection('posts')
347
.orderBy('createdAt', 'desc')
348
.limit(10);
349
350
const firstPage = await firstPageQuery.get();
351
352
// Next page using last document as cursor
353
if (!firstPage.empty) {
354
const lastDoc = firstPage.docs[firstPage.docs.length - 1];
355
356
const nextPageQuery = firestore()
357
.collection('posts')
358
.orderBy('createdAt', 'desc')
359
.startAfter(lastDoc)
360
.limit(10);
361
362
const nextPage = await nextPageQuery.get();
363
}
364
365
// Get last N documents
366
const lastPostsQuery = firestore()
367
.collection('posts')
368
.orderBy('createdAt')
369
.limitToLast(5);
370
371
// Pagination with field values
372
const postsAfterDateQuery = firestore()
373
.collection('posts')
374
.orderBy('createdAt')
375
.startAfter(new Date('2023-01-01'))
376
.limit(10);
377
378
// Range queries using cursors
379
const specificRangeQuery = firestore()
380
.collection('users')
381
.orderBy('age')
382
.startAt(18)
383
.endBefore(65)
384
.limit(50);
385
```
386
387
### Aggregation Queries
388
389
Perform server-side aggregations like counting documents without downloading all data.
390
391
```typescript { .api }
392
/**
393
* Count the number of documents in the query
394
* @returns Aggregate query for counting documents
395
*/
396
count(): FirebaseFirestoreTypes.AggregateQuery<{ count: FirebaseFirestoreTypes.AggregateField<number> }>;
397
398
/**
399
* Count the number of documents on the server
400
* @returns Aggregate query for server-side counting
401
*/
402
countFromServer(): FirebaseFirestoreTypes.AggregateQuery<{ count: FirebaseFirestoreTypes.AggregateField<number> }>;
403
404
interface AggregateQuery<T> {
405
/**
406
* Execute the aggregate query
407
* @returns Promise resolving to aggregate query snapshot
408
*/
409
get(): Promise<FirebaseFirestoreTypes.AggregateQuerySnapshot<T>>;
410
}
411
412
interface AggregateQuerySnapshot<T> {
413
/**
414
* Get aggregate data
415
* @returns Aggregate data object
416
*/
417
data(): T;
418
}
419
```
420
421
**Usage Examples:**
422
423
```typescript
424
import firestore from '@react-native-firebase/firestore';
425
426
// Count all users
427
const allUsersCount = await firestore()
428
.collection('users')
429
.count()
430
.get();
431
432
console.log('Total users:', allUsersCount.data().count);
433
434
// Count with filters
435
const activeUsersCount = await firestore()
436
.collection('users')
437
.where('active', '==', true)
438
.count()
439
.get();
440
441
console.log('Active users:', activeUsersCount.data().count);
442
443
// Server-side counting (bypasses cache)
444
const serverCount = await firestore()
445
.collection('posts')
446
.where('published', '==', true)
447
.countFromServer()
448
.get();
449
450
console.log('Published posts:', serverCount.data().count);
451
```
452
453
## Types
454
455
```typescript { .api }
456
interface DocumentChange<T = FirebaseFirestoreTypes.DocumentData> {
457
readonly doc: FirebaseFirestoreTypes.QueryDocumentSnapshot<T>;
458
readonly newIndex: number;
459
readonly oldIndex: number;
460
readonly type: FirebaseFirestoreTypes.DocumentChangeType;
461
}
462
463
type DocumentChangeType = 'added' | 'removed' | 'modified';
464
465
interface QueryDocumentSnapshot<T = FirebaseFirestoreTypes.DocumentData> extends DocumentSnapshot<T> {
466
/**
467
* QueryDocumentSnapshot always contains data (exists is always true)
468
*/
469
data(options?: FirebaseFirestoreTypes.SnapshotOptions): T;
470
}
471
472
interface AggregateField<T> {
473
/**
474
* Get the aggregate field value
475
* @returns The aggregated value
476
*/
477
value(): T;
478
}
479
```