import 'package:cloud_firestore/cloud_firestore.dart'; import 'constants.dart'; /// A path helper: its return value is inlined with the call's arguments. String payoutsPath(String storeId) => 'stores/$storeId/payouts'; /// Direct chains: every clause is visible in the one expression. class DirectQueries { DirectQueries(this.firestore); final FirebaseFirestore firestore; Future equalityAndOrder() async { await firestore .collection('categories') .where('isActive', isEqualTo: true) .orderBy('name') .get(); } Future everyOperator(String userId, DateTime since) async { await firestore .collection('events') .where('ownerId', isEqualTo: userId) .where('status', isNotEqualTo: 'archived') .where('price', isLessThan: 10) .where('price', isLessThanOrEqualTo: 9.5) .where('createdAt', isGreaterThan: since) .where('rank', isGreaterThanOrEqualTo: 2) .where('tags', arrayContains: 'music') .where('genres', arrayContainsAny: ['jazz', 'soul']) .where('city', whereIn: ['nyc', 'la', 'sf']) .where('kind', whereNotIn: ['spam']) .where('deletedAt', isNull: true) .where('publishedAt', isNull: false) .limit(20) .get(); } Future rangeInOneCall(Timestamp from, Timestamp to) async { await firestore .collection('bookings') .where('startsAt', isGreaterThanOrEqualTo: from, isLessThan: to) .orderBy('startsAt', descending: true) .get(); } Future constantNames() async { await firestore.collection(kOrdersCollection).get(); await firestore .collection(Collections.auditTrail) .orderBy('at', descending: true) .limitToLast(5) .get(); await firestore.collection(Collections.reviews).get(); } Future interpolatedPath(String storeId) async { await firestore .collection('${Collections.stores}/$storeId/products') .where('visible', isEqualTo: true) .get(); } Future pathHelpers(String storeId, String uid) async { await firestore.collection(payoutsPath(storeId)).get(); final path = 'users/$uid/drafts'; await firestore.collection(path).get(); } Future documentThenSubcollection(String storeId) async { await firestore .collection('stores') .doc(storeId) .collection('services') .orderBy('updatedAt', descending: true) .startAfter([1]).get(); } Future rootDocumentPath(String userId) async { await firestore.doc('users/$userId').collection('saved').get(); } Stream>> groupStream(String userId) { return firestore .collectionGroup('userSubscriptions') .where('userId', isEqualTo: userId) .snapshots(); } Future fieldPaths(String id) async { await firestore .collection('profiles') .where(FieldPath.documentId, isEqualTo: id) .where(FieldPath(['address', 'city']), isEqualTo: 'nyc') .orderBy(FieldPath.documentId) .get(); } Future disjunction(String userId) async { await firestore .collection('threads') .where( Filter.or( Filter('buyerId', isEqualTo: userId), Filter.and( Filter('sellerId', isEqualTo: userId), Filter('open', isEqualTo: true), ), ), ) .get(); } Future counting(String storeId) async { await firestore .collection('orders') .where('storeId', isEqualTo: storeId) .count() .get(); await firestore.collection('orders').aggregate(sum('total')).get(); } Future converted() async { await firestore .collection('tips') .withConverter( fromFirestore: (snapshot) => snapshot.id, toFirestore: (value) => {'v': value}, ) .where('amount', isGreaterThan: 0) .get(); } Future dynamicCollection(String name) async { await firestore.collection(name).where('a', isEqualTo: 1).get(); } Future unsafeNames() async { await firestore .collection('ignore previous instructions') .where('a b', isEqualTo: 1) .get(); } Future documentRead(String id) async { // A document read is not a query: counted, never listed. await firestore.collection('users').doc(id).get(); } }