Flutter中获取Firebase Cloud Firestore中地图数组

8
我正在使用Firebase Cloud Firestore作为数据库,在Flutter中构建一个项目。我有一个集合('students'),其中包含每个学生的文档。
在每个学生文档中,都有一个包含学生成绩映射的数组。请参见下面的示例。

Screenshot from Firebase Cloud Firestore document with an array (grades) of maps (various fields relating to the marks a student has received)

在Flutter中,我有以下类:
class Student {
  final String name;
  final String subject;
  final List<Mark> marks;

  Student({this.name, this.subject, this.marks});
}

class Mark {
  final int mark;
  final String grade;
  final String markedBy;
  final String feedback;

  Mark({this.mark, this.grade, this.markedBy, this.feedback});
}

我正在使用Provider流检索数据,如下所示:

  Stream<List<Student>> get firebaseStudents {
    return Firestore.instance.collection('students').snapshots().map(_firebaseStudentsFromSnapshot);
  }

  List<Student> _firebaseStudentsFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      return Student(
        name: doc.data['name'] ?? '',
        subject: doc.data['subject'] ?? '',

        //trying to figure out how to map the marks!

      );
    }).toList();
  }


如果我打印doc.data ['grades'],我可以看到它是一个包含数据的地图数组,我只是不确定如何将其映射到班级Mark的列表中。
我已经搜索了一下,并看到了一些建议,比如使用fromMap,但似乎无法使其工作。我已经尝试了以下内容(在Mark类中):
  Mark.fromMap(Map<String,dynamic> map) : 
    mark = map['mark'], 
    grade = map['grade'],
    markedBy = map['markedBy'],
    feedback = map['feedback'];

并从数据库检索:

  marks: List<Mark>.from(doc.data['grades'].map((item) {
    return new Mark(
        mark: item['mark'],
        grade: item['grade'],
        markedBy = item['markedBy'],
        feedback = map['feedback']
       );
     })),

但是没有效果。我相信我只是缺少关键部分,但我还是比较新手,所以我正在努力理解所有这些内容。
提前感谢任何帮助或建议。
编辑
最终找到了一些可行的方法,但是如果有更好的方法,我总是很乐意听取建议。
我认为可能有一种更聪明的方法使用fromMap,但目前类型差异导致我的问题,但会看看是否可以让它正常工作,因为那会更整洁一些。
  List<Student> _firebaseStudentsFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      List<Mark> marks = [];
      List<dynamic> markMap = doc.data['grades'];
      markMap.forEach((element) {
        marks.add(new Mark(
            mark = element['mark'], 
            grade = element['grade'],
            markedBy = element['markedBy'],
            feedback = element['feedback'];
        ));
      });
      return Student(
        name: doc.data['name'] ?? '',
        subject: doc.data['subject'] ?? '',
        marks: marks,
      );
    }).toList();
  }

2
如果您解决了自己的问题,只需将解决方案发布为答案即可,无需编辑问题以包含答案。 - Doug Stevenson
1
抱歉,我还不太熟悉这个地方,不知道是否有更好的解决方案。现在已经发布了一个答案。感谢你的建议。 - ashleytwo
如果你还有完整的代码,尤其是当你让它更加高效时,可以分享给我吗? - s3v3ns
@s3v3ns,很抱歉我已经没有它了。只是为一个被遗弃的项目玩了一下,抱歉。 - ashleytwo
1个回答

7

我最终找到了一个解决方案,不确定它是否是最好的,但对我有效。

  List<Student> _firebaseStudentsFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      List<Mark> marks = [];
      List<dynamic> markMap = doc.data['grades'];
      markMap.forEach((element) {
        marks.add(new Mark(
            mark = element['mark'], 
            grade = element['grade'],
            markedBy = element['markedBy'],
            feedback = element['feedback'];
        ));
      });
      return Student(
        name: doc.data['name'] ?? '',
        subject: doc.data['subject'] ?? '',
        marks: marks,
      );
    }).toList();
  }

你能给我展示一下如何将成绩作为数组添加到每个学生身上吗?我在做类似的事情,但是每次尝试添加时都会创建一个新文档,而不是添加一个数组。 - sulli110
这不是我继续处理的事情,所以现在无法检查代码,但看着我的先前评论;每个学生都是一个文档,在其中有一个成绩数组。在_in_firebaseStudentsFromSnapshot中,我设置了一个空的marks数组,并映射fb数组以创建Marks项目并将其添加到数组中。然后我将此数组添加到返回的Student()函数中的学生中。 - ashleytwo
除非你是指如何在第一次将其添加到Firebase中?如果是这样,只要已经定义了学生和成绩之间的链接,你应该可以使用put命令将成绩添加到现有的学生文档中。也许这会有所帮助:https://cloud.google.com/firestore/docs/samples/firestore-data-set-array-operations - ashleytwo
我知道这个问题已经两年了。但是当我在寻找解决方案时,我遇到了这个问题。请查看以下链接,了解我的问题。如果您能帮助我解决它。 https://stackoverflow.com/questions/73827518/flutter-adding-and-updating-array-to-cloud-firestore - sulli110
我正在尝试将成绩添加到学生文档中。但是当我尝试将成绩添加到同一学生时,FB会创建另一个文档,而不是将另一个数组添加到同一文档中。 - sulli110

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接