使用切换流时如何处理 firestore whereIn 限制为 10?
How can I deal with the firestore whereIn limit of 10 when using a switch stream?
我有以下 Stream,它接受一个组的 Stream 和 returns 它的成员的一个 Stream。我使用 switchmap 从组快照中获取成员。
但是我有以下问题。我使用带有 whereIn
过滤器的 where 查询。但问题是,根据 firestore 文档
,whereIn
只能接收包含 10 个或更少条目的列表
Limitations Note the following limitations for in and
array-contains-any:
in and array-contains-any support up to 10 comparison values.
https://firebase.google.com/docs/firestore/query-data/queries#limitations
所以我在处理这个问题时遇到了一些困难。
Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
return groupStream.switchMap(
(value) => _fireStore
.collection(APIRoutes.users)
.where(FieldPath.documentId, whereIn: value.members.keys.toList(growable: false))
.snapshots()
.map((snapshot) =>
snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false)),
);
}
因为我需要组成员 ID 作为开头,所以我需要一个 switchMap。所以我不能简单地拆分组成员列表,然后对 10 个 ID 的每个块进行单独查询。
那我该如何处理呢?
我最后是这样的
Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
return groupStream.switchMap(
(value) => _chunckSizeGroupMembersStream(value),
);
}
Stream<List<UserModel>> _chunckSizeGroupMembersStream(GroupModel group) {
final List<List<String>> memberChunks = chunkSizeCollection(group.members.keys.toList(growable: false), 10);
List<Stream<List<UserModel>>> streams = List<Stream<List<UserModel>>>();
memberChunks.forEach((chunck) => streams.add(_fireStore
.collection(APIRoutes.userCollection)
.where(FieldPath.documentId, whereIn: chunck)
.snapshots()
.map((snapshot) =>
snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false))));
return ZipStream(streams, (value) => value.last);
}
另一种可能的解决方案(使用 Quiver & RxDart 包)
Future<List<QueryDocumentSnapshot>> listItems(
List<dynamic> itemIds) async {
final chunks = partition(itemIds, 10);
final querySnapshots = await Future.wait(chunks.map((chunk) {
Query itemsQuery = FirebaseFirestore.instance
.collection('collection')
.where("id", whereIn: chunk);
return itemsQuery.get();
}).toList());
return querySnapshots == null
? []
: await Stream.fromIterable(querySnapshots)
.flatMap((qs) => Stream.fromIterable(qs.docs))
.toList();
}
这样看起来更通用(您甚至可以使用供应商函数提取查询)。
我有以下 Stream,它接受一个组的 Stream 和 returns 它的成员的一个 Stream。我使用 switchmap 从组快照中获取成员。
但是我有以下问题。我使用带有 whereIn
过滤器的 where 查询。但问题是,根据 firestore 文档
whereIn
只能接收包含 10 个或更少条目的列表
Limitations Note the following limitations for in and array-contains-any:
in and array-contains-any support up to 10 comparison values.
https://firebase.google.com/docs/firestore/query-data/queries#limitations
所以我在处理这个问题时遇到了一些困难。
Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
return groupStream.switchMap(
(value) => _fireStore
.collection(APIRoutes.users)
.where(FieldPath.documentId, whereIn: value.members.keys.toList(growable: false))
.snapshots()
.map((snapshot) =>
snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false)),
);
}
因为我需要组成员 ID 作为开头,所以我需要一个 switchMap。所以我不能简单地拆分组成员列表,然后对 10 个 ID 的每个块进行单独查询。
那我该如何处理呢?
我最后是这样的
Stream<List<UserModel>> groupMembersStream(Stream<GroupModel> groupStream) {
return groupStream.switchMap(
(value) => _chunckSizeGroupMembersStream(value),
);
}
Stream<List<UserModel>> _chunckSizeGroupMembersStream(GroupModel group) {
final List<List<String>> memberChunks = chunkSizeCollection(group.members.keys.toList(growable: false), 10);
List<Stream<List<UserModel>>> streams = List<Stream<List<UserModel>>>();
memberChunks.forEach((chunck) => streams.add(_fireStore
.collection(APIRoutes.userCollection)
.where(FieldPath.documentId, whereIn: chunck)
.snapshots()
.map((snapshot) =>
snapshot.documents.map((document) => UserModel.fromFirestore(document)).toList(growable: false))));
return ZipStream(streams, (value) => value.last);
}
另一种可能的解决方案(使用 Quiver & RxDart 包)
Future<List<QueryDocumentSnapshot>> listItems(
List<dynamic> itemIds) async {
final chunks = partition(itemIds, 10);
final querySnapshots = await Future.wait(chunks.map((chunk) {
Query itemsQuery = FirebaseFirestore.instance
.collection('collection')
.where("id", whereIn: chunk);
return itemsQuery.get();
}).toList());
return querySnapshots == null
? []
: await Stream.fromIterable(querySnapshots)
.flatMap((qs) => Stream.fromIterable(qs.docs))
.toList();
}
这样看起来更通用(您甚至可以使用供应商函数提取查询)。