简体   繁体   中英

How to fetch a `DocumentReference` from a Firebase `get()`

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 a List<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?

I'm not 100% certain, but I think the result of your getFromCategory function should be list of Future s because loading each user is an asynchronous operation too:

Future<List<FutureClassifiedAd>>>

So you have two levels of asynchronous operations, each of which results in a Future in your method signature:

  1. Loading the list of ads, which is the outer Future of the method.
  2. The loading of each user document, which causes each element in the list to also be a Future .

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;
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM