0
func fetchNextPage() async {
    guard !isLoading, !reachedEnd else { return }
    isLoading = true
    defer { isLoading = false }
    
    let excluded = Array(BlockService.shared.blocked.prefix(10))
    
    var query = db.collection("posts")
        .whereField("isReply", isEqualTo: false)
        .order(by: "timestamp", descending: true)
    
    if !excluded.isEmpty {
        query = query.whereField("ownerUid", notIn: excluded)
    }
    
    if let lastDoc { query = query.start(afterDocument: lastDoc) }
    query = query.limit(to: pageSize)
    
    do {
        let snap = try await query.getDocuments()
        
        guard !snap.documents.isEmpty else {
            reachedEnd = true
            return
        }
        
        let items = snap.documents.compactMap { try? $0.data(as: Post.self) }
        let posts = await PostService.hydratePosts(items)
        
        self.posts.append(contentsOf: posts)
        lastDoc = snap.documents.last
        if snap.documents.count < pageSize { reachedEnd = true }
    } catch {
        Crashlytics.crashlytics().record(error: error)
        
        #if DEBUG
            print("DEBUG: Unable to fetch posts with error: \(error.localizedDescription)")
        #endif
    }
}

Currently, Firestore’s not-in operator is limited to 10 values, which restricts users from blocking more than 10 others. Is there an efficient way to work around this limitation and support unlimited blocked users? I don't want to filter client side. I want to keep everything a query so I can implement Firestore rules.

1

1 Answer 1

1

The only alternative is to store the feed for the current user in the database, rather than querying it live. That way you can exclude the posts from blocked users when you're writing the data, rather than doing it at read-time.

This is one of the most common trade-offs you have to do when using a NoSQL database such as Firestore, where the query capabilities are often more limited than for a relational database. If you have a use-case that can't be met with the query capabilities, you'll have to modify your data model to allow the use-case.

Duplicating data such as I describe above (often also called fanning out data) is a common approach. While it makes the write operation more complex, the assumption when using a NoSQL database is that write operations are much less frequent than reads - so a more complicated write and storing duplicated data balances out over the multitude of reads.

If this strikes you as "unnatural" or "wrong", consider using a relational database instead. There is nothing wrong with that - as long as you also keep in mind that most social networks use a mix of the above and relational techniques.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.