Home > Enterprise >  How to fetch a `DocumentReference` from a Firebase `get()`
How to fetch a `DocumentReference` from a Firebase `get()`

Time:12-28

I have a collection ads that contains a DocumentReference as ownerId.

With the code below, I am able to fetch the 10 most recent ads as aList<Ad>:

  /// Returns a list of ads of the given [category]
  static Future<List<ClassifiedAd>> getFromCategory(
      ClassifiedAdCategory category,
      {int max = 10}) async {
    return FirebaseFirestore.instance
            .collection('ads')
            .where('category', isEqualTo: category.name)
            .orderBy('creationDate', descending: true)
            .limit(max)
            .get()
            .then((snapshot) {

      return snapshot.docs.map((doc) {
        final data = doc.data();
        return Ad.fromMap(data);
      }).toList();

    });

But now I'd like to fetch the owner (collection users) from the DocumentReference I was talking about above. But I am a but puzzled about how to do that.

My modified code below does not compile:

The return type 'List' isn't a 'FutureOr<List>', as required by the closure's context.

  /// Returns a list of ads of the given [category]
  static Future<List<ClassifiedAd>> getFromCategory(
      ClassifiedAdCategory category,
      {int max = 10}) async {
    return FirebaseFirestore.instance
            .collection('ads')
            .where('category', isEqualTo: category.name)
            .orderBy('creationDate', descending: true)
            .limit(max)
            .get()
            .then((snapshot) {
      // <<<< Error starts right here down to the removeWhere()
      return snapshot.docs.map((doc) {
        final data = doc.data();
        final DocumentReference docRef = data["ownerId"];
     
        return docRef.get().<ClassifiedAd?>then((snapshot) {
          if (snapshot.exists) {
            return ClassifiedAd.fromMap(data);
          }
          return null;
        });
      }).toList()
      // Don't take into account potential nulls
      ..removeWhere((a) => a == null);

    });

How should I do that?

CodePudding user response:

I would say that the wrong thing that you're doing is you're trying to get a snapshot asynchronously inside the map() method which is synchronous, for such cases like yours, I recommend using await/async and to not return anything until you guarantee that you got it, try this:

static Future<List<ClassifiedAd>> getFromCategory(
      ClassifiedAdCategory category,
      {int max = 10}) async {
    final snapshot = await FirebaseFirestore.instance
        .collection('ads')
        .where('category', isEqualTo: category.name)
        .orderBy('creationDate', descending: true)
        .limit(max)
        .get();

    List<ClassifiedAd> result = [];

    for (int index = 0; index < snapshot.docs.length; index  ) {
      final doc = snapshot.docs[index];
      final data = doc.data();
      final DocumentReference docRef = data["ownerId"];

      final docOwnerSnapshot = await docRef.get();
      if (docOwnerSnapshot.exists) {
        result.add(ClassifiedAd.fromMap(data));
      }
    }

    return result;
  }
  • Related