Solution required for firebase query limit of <=10
One solution is to partition your array into sets of 10.
And iterate through each partition and make a firebase in
query.
Aggregate and add results back to a list.
Here is some psuedo-code:
function queryMoreThan10(query, list) {
partitions; // this is an array of arrays
for ( i = 0; i < list.size; i += 10) {
// this aggregates and transforms the array into 10 elements
// for each partition
partitions.add(list.slice(i, i + partition));
}
// Now make the query for each partition and map-reduce to
// obtain a unified list of results
}
Osamah Atif
Updated on January 03, 2023Comments
-
Osamah Atif over 1 year
I have a small function for my application that fetches cart items from firebase and displays them. The application was working fine till Flutter version 2.5.2 but when I moved 2.8.1 the application crashed if the number of items in the cart collection are more than 10 because of the firebase query limit of "<=10"
[Unhandled promise rejection: FirebaseError: Invalid Query. 'in' filters support a maximum of 10 elements in the value array.]
If you can suggest a workaround for this, that would be really helpful.
I am currently using the following functions to get data from firebase.
///Get products Stream<List<Product>> getProducts(List<CartItem> cartItems) { List<String> ids = cartItems.map((e) => e.reference).toList(); return database.getDataWithArrayCondition('products', ids).map( (snapshots) => snapshots.docs .map((snapshot) => Product.fromMap( snapshot.data() as Map<String, dynamic>, snapshot.id)) .toList()); } ///Get cart items Stream<List<CartItem>> _getCartItems() { return database .getDataFromCollection("users/${auth.uid}/cart") .map((snapshots) => snapshots.docs.map((snapshot) { return CartItem.fromMap( snapshot.data() as Map<String, dynamic>, snapshot.id); }).toList()); }
Error
The following assertion was thrown building StreamBuilder<List<CartItem>>(dirty, state: _StreamBuilderBaseState<List<CartItem>, AsyncSnapshot<List<CartItem>>>#978e8): 'in' filters support a maximum of 10 elements in the value [List]. 'package:cloud_firestore/src/query.dart': Failed assertion: line 702 pos 11: '(value as List).length <= 10' The relevant error-causing widget was: StreamBuilder<List<CartItem>> StreamBuilder:file:///Users/Osamah/Downloads/grocery_user_fixed-master/lib/ui/home/cart/cart.dart:265:12 When the exception was thrown, this was the stack: #2 _JsonQuery.where (package:cloud_firestore/src/query.dart:702:11) #3 FirestoreDatabase.getDataWithArrayCondition (package:grocery/services/database.dart:150:10) #4 CartBloc.getProducts (package:grocery/blocs/cart_bloc.dart:32:21) #5 _CartState.build.<anonymous closure> (package:grocery/ui/home/cart/cart.dart:292:37) #6 StreamBuilder.build (package:flutter/src/widgets/async.dart:442:81) #7 _StreamBuilderBaseState.build (package:flutter/src/widgets/async.dart:124:48) #8 StatefulElement.build (package:flutter/src/widgets/framework.dart:4705:27) #9 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4588:15) #10 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4763:11) #11 Element.rebuild (package:flutter/src/widgets/framework.dart:4311:5) #12 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2578:33) #13 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21) #14 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5) #15 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1145:15) #16 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1082:9) #17 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5) #21 _invoke (dart:ui/hooks.dart:150:10) #22 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5) #23 _drawFrame (dart:ui/hooks.dart:114:31) (elided 5 frames from class _AssertionError and dart:async)
Here is the relevant code
return StreamBuilder<List<CartItem>>( stream: widget.bloc.cartItems, builder: (context, snapshot) { if (snapshot.hasData && snapshot.data != null) { List<CartItem> cartItems = snapshot.data!; if (cartItems.length == 0) { return FadeIn( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ SvgPicture.asset( 'images/state_images/empty_cart.svg', width: width * 0.5, fit: BoxFit.cover, ), Padding( padding: EdgeInsets.only(top: 30), child: Texts.headline3( 'Nothing found here\nGo and enjoy shopping!', themeModel.accentColor, alignment: TextAlign.center), ) ]), ); } else { return StreamBuilder<List<Product>>( stream: widget.bloc.getProducts(cartItems), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data != null) { List<Product> products = snapshot.data!; cartItems = cartItems.where((cartItem) { if (products.where((product) { if (cartItem.reference == product.reference) { cartItem.product = product; return true; } else { return false; } }).length == 0) { return false; } else { return true; } }).toList();