Firestore/Flutter:查询文档的子集合

时间:2020-12-31 20:52:05

标签: firebase flutter dart google-cloud-firestore

我正在开发一个 Flutter 应用程序并使用 firestore 作为后端: 我的数据库结构是:

  • 用户(集合)
    • userid(用户属性)
    • 书籍(子集)
      • booksList(对象数组(或地图作为 firestore 调用它们))

从 booksList 数组中检索每本书的函数是:

Future<List<Book>> bookshelf(String userId) async {
  return await FirebaseFirestore.instance
      .collection('Users')
      .where('userId', isEqualTo: userId)
      .get()
      .then((querySnapshot) => querySnapshot.docs.map((doc) => doc.reference
          .collection('Books')
          .get()
          .then((querySnapshot) => querySnapshot.docs.forEach((doc) {
                var books = doc.data()['bookList'];
                return books
                    .map<Book>((elem) => Book(title: elem['title']));
              }))).toList());

我的问题是我无法返回 Future>;
我尝试创建一个数组并在第 12 行(我实际上正确获取书籍的位置)向其中添加元素,但它不起作用,因为 return 语句没有等待查询完成。
基本上,我无法将我得到的对象转换为 Future ,因为我需要该功能。 现在我得到一个“MappedListIterable”。
谢谢。

1 个答案:

答案 0 :(得分:0)

错误是由嵌套最多的 Promise 回调中的 forEach 方法引起的,因为 forEach 方法总是返回 void,但是 Book 是预期的。嵌套列表也会出现错误,可以通过使用expand方法展平嵌套列表来解决。我已修改您的代码示例以删除 forEach 方法并减少 Promise 回调嵌套:

Future<List<Book>> bookshelf(String userId) async {
  return await FirebaseFirestore.instance
      .collection('Users')
      .where('userId', isEqualTo: userId)
      .get()
      // Maps each user query snapshot to a list of book query snapshots.
      .then(
        (snapshot) => Future.wait(
          snapshot.docs.map((doc) => doc.reference.collection('Books').get()),
        ),
      )
      // Maps each list of book query snapshots to a list of book document snapshots.
      .then(
        (snapshots) => snapshots.expand((snapshot) => snapshot.docs),
      )
      // Maps each list of book document snapshots to a list of raw books.
      .then(
        (docs) => docs.expand((doc) => doc.data()['bookList'] as List),
      )
      // Maps each list of raw books to a list of books.
      .then(
        (books) => books.map((book) => Book(title: book['title'])).toList(),
      );
}