【问题标题】:How to read nested fields from Firebase Firestore如何从 Firebase Firestore 读取嵌套字段
【发布时间】:2022-01-05 17:10:38
【问题描述】:

我想从我的 Firestore 中读取嵌套字段。字段的层次结构是

cmets

|__ c_id

|__ c_text

|_________回复

|____________ r_id

|____________ r_text

我尝试了以下代码:

var documentSnapshot = await FirebaseFirestore.instance
        .collection("article_engagements")
        .doc(id.toString())
        .get();
var comments = await FirebaseFirestore.instance
        .collection("article_engagements")
        .doc(id.toString())
        .collection("comments")
        .get();
    
comments.docs.forEach((element) {
      var replies = element.get('replies');
      commentsList.add(Comment(
        id: element.get('c_id'),
        text: element.get('c_text'),
        replies: ,
      ));
    });


article = new ArticleEngagement(
            id: id,
            likes: documentSnapshot.get('likes'),
            shares: documentSnapshot.get('shares'),
            comments: commentsList,
        );

但我被困在回复字段中。 firestore文档截图如下:

ArticleEngagement、评论和回复模型如下:

class ArticleEngagement {
  int? id;
  int? likes;
  int? shares;
  List<Comment>? comments;

  ArticleEngagement({
    this.id,
    this.likes,
    this.shares,
    this.comments,
  });
}

class Comment {
  String? id;
  String? text;
  List<Reply>? replies;
  Comment({
    this.id,
    this.replies,
    this.text,
  });
}

class Reply {
  String? id;
  String? reply;

  Reply({
    this.id,
    this.reply,
  });
}

【问题讨论】:

  • 您能否编辑您的问题并从您的代码中分享更多信息?专门针对Comment 和ArticleEngagement 类,以便拥有minimal code that reproduces the problem
  • @RogelioMonter 我已经添加了代码。您可以立即查看
  • 您有机会查看我的answer吗?

标签: firebase flutter google-cloud-firestore


【解决方案1】:

问题是您想访问comments 字段,就好像它是article_engagements 文档的子集合一样,但实际上它是一个数组。

要访问给定id 的文档中的所有字段,我建议将您的字段映射为反映您的实际数据结构的嵌套类。正如answer所指出的,

您可以使用json_serializable 包,它会生成用于序列化/反序列化的代码。

Creating model classes the json_serializable way

确保您的类属性与 Cloud Firebase 中的字段匹配

import 'package:json_annotation/json_annotation.dart';

/// This allows the `ArticleEngagement` class to access private members in
/// the generated file. The value for this is *.g.dart, where
/// the star denotes the source file name.
part 'test.g.dart';

/// An annotation for the code generator to know that this class needs the
/// JSON serialization logic to be generated.
@JsonSerializable()
class ArticleEngagement {
  int? article_id;
  int? likes;
  int? shares;
  List<Comment>? comment;

  ArticleEngagement({
    this.article_id,
    this.likes,
    this.shares,
    this.comment,
  });

  /// A necessary factory constructor for creating a new ArticleEngagement instance
  /// from a map. Pass the map to the generated `_ArticleEngagement()` constructor.
  /// The constructor is named after the source class, in this case, ArticleEngagement.
  factory ArticleEngagement.fromJson(Map<String, dynamic> json) =>
      _$ArticleEngagementFromJson(json);

  /// `toJson` is the convention for a class to declare support for serialization
  /// to JSON. The implementation simply calls the private, generated
  /// helper method `_$ArticleEngagementToJson`.
  Map<String, dynamic> toJson() => _$ArticleEngagementToJson(this);
}

@JsonSerializable()
class Comment {
  String? c_id;
  String? c_text;
  List<Reply>? replies;
  Comment({
    this.c_id,
    this.replies,
    this.c_text,
  });

  factory Comment.fromJson(Map<String, dynamic> json) =>
      _$CommentFromJson(json);

  Map<String, dynamic> toJson() => _$CommentToJson(this);
}

@JsonSerializable()
class Reply {
  String? r_id;
  String? r_text;

  Reply({
    this.r_id,
    this.r_text,
  });

  factory Reply.fromJson(Map<String, dynamic> json) => _$ReplyFromJson(json);

  Map<String, dynamic> toJson() => _$ReplyToJson(this);
}

那你必须run the code generation utility。

一次性代码生成

通过在项目根目录中运行 flutter pub run build_runner build,您可以在需要时为模型生成 JSON 序列化代码。

最后,你可以consume json_serializable models,像这样:

  var document = await FirebaseFirestore.instance
      .collection("article_engagements")
      .doc(id.toString())
      .get();

  ArticleEngagement article =
      ArticleEngagement.fromJson(document.data() as Map<String, dynamic>);

  print(article.comment?.first.c_id);

另见:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多