简体   繁体   中英

How to fetch the latest document in collection from Firebase Cloud Firestore using Swift

I'm successfully retrieving documents from a Firebase Firestore collection using the code below. This is being used to create a list of food items for each user. The user manually adds the date when the food item is being added. The date is being used to order the fetched data alongside the userId only retrieving the documents for that user.

However, I'd like to be able to fetch the latest food item added for a separate view that displays only that latest item. This latest item will change as the user adds more items.

I'm struggling to find the best way to achieve this. Assigning foodItems[0] to a separate @Published variable 'latestFoodItem' straight after all foodItems are fetched doesn't seem to be working.

I might be thinking along the wrong lines as a beginner... foodItems could also be empty, which is causing me problems!

func fetchFoodItemsData() {
let userId = Auth.auth().currentUser?.uid
  db.collection("foodItems")
    .whereField("userId", isEqualTo: userId)
    .order(by: "date", descending: true)
    .addSnapshotListener { (querySnapshot, error) in
    guard let documents = querySnapshot?.documents else {
      print("No documents")
      return
    }
    self.foodItems = documents.compactMap { queryDocumentSnapshot -> FoodItem? in
      return try? queryDocumentSnapshot.data(as: FoodItem.self)
    }
  }
}

Here is the structure of my Cloud Firestore with some fake data:

在此处输入图像描述

Since you're already fetching all the items, I would recommend using a local transformation.

In your view model (or repository), use Combine to add a new subscriber to your foodItems . Then, set up a pipeline that transforms the collection of food items by sorting them and then picking the first element. Finally, assign this value to a new published property.

Here is some sample code I adapted from one of my own apps:

public class FoodItemsRepository: ObservableObject {

  // MARK: - Publishers
  @Published public var foodItems = [FoodItem]()
  @Published public var mostRecentFoodItem: FoodItem?

  init() {
    // ... other setup

    $foodItems.map { items in
      items
        .sorted { $0.dateAdded > $1.dateAdded }
        .first
    }
    .assign(to: \.mostRecentFoodItem, on: self)
    .store(in: &cancellables)
  }
}

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