Milly Alfaro
Milly Alfaro

Reputation: 309

How to sort data with a limit filter Firestore

I'm using pagination and therefore using a limit filter. I basically have two functions. A getData() and a updateData(). getData() is called when the app opens to get the first 10 documents of data, sorting them based on a time interval. If the user scrolls down, updateData() is called to retrieve the next 10 documents sorted by the time interval and so on. The sorting is made so that the latest document appears at the top and so on. The problem is that since the data is being limited, it is sorting the first 10 random documents it retrieves from firestore, and not the first 10 documents created out of all the documents. For example, lets say we have documents, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]. When the app loads it would show something like [15, 14, 12, 9, 7, 5, 4, 3, 2, 1]. This is good because it's sorting the data how I want it with the latest document appearing first, but not getting the correct order of documents. Rather it should show [15, 14, 13, 12, 11, 10, 9, 8, 7, 6] What should I do so that when the function runs, out of all the documents surpassing the limit query it receives the actual latest documents in the correct order, and when I update for pagination it continues the process.

getData function:

func getData(){
        let db = Firestore.firestore()
        
        let uid = Auth.auth().currentUser!.uid
        
        
        db.collection("References").whereField("followers", arrayContains: uid).limit(to: 10).getDocuments{ (snap, err) in
            if err != nil{
                print((err?.localizedDescription)!)
                return
            }
            
            //Remove shimmer effect
            self.data.removeAll()
            
            for i in snap!.documents {
              
                let snippetRef = i.get("ref") as! DocumentReference
                let snippetId = i.get("snippetId") as! String
                
                fetchSnippets(id: snippetRef.documentID) { (snippet) in
                    let data = FeedModel(id: i.documentID, name: i.get("name") as! String, snippet: snippet, snippetId: snippetId, show: false)
                    
                    self.data.append(data)
                    
                    //Sort based on time
                    
                    self.data.sort { (p1, p2) -> Bool in

                        return p1.snippet.time > p2.snippet.time

                    }
                }

            }
            
            self.lastDoc = snap!.documents.last
            
        }
        
        
    }

updateData function:

func updateData(){
        let currentDateTime = Date().timeIntervalSince1970
        
        let user = UserModel(userName: "", profilePic: "", bio: "", displayName: "", snippets: 0, followers: 0, following: 0, mood: "", uid: "", isPublic: false)
        
        let snippet = SnippetModel(caption: "", time: currentDateTime, pic: "", mood: "", uid: "", likes: 0, comments: 0, user: user)
        
        self.data.append(FeedModel(id: "\(self.data.count)", name: "", snippet: snippet, snippetId: "", show: false))

        withAnimation(Animation.linear(duration: 1.5).repeatForever(autoreverses: false)){
            self.data[self.data.count - 1].show.toggle()
        }
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1){
            let db = Firestore.firestore()
            
            let uid = Auth.auth().currentUser!.uid
            
            db.collection("References").whereField("followers", arrayContains: uid).start(afterDocument: self.lastDoc).limit(to: 10).getDocuments { (snap, err) in
                if err != nil {
                    print((err?.localizedDescription)!)
                    return
                }
                
                self.data.removeLast()
                
                if !snap!.documents.isEmpty{
                    for i in snap!.documents{
                    
                        let snippetRef = i.get("ref") as! DocumentReference
                        let snippetId = i.get("snippetId") as! String
                        
                        fetchSnippets(id: snippetRef.documentID) { (snippet) in
                            let data = FeedModel(id: i.documentID, name: i.get("name") as! String, snippet: snippet, snippetId: snippetId, show: false)
                            
                            self.data.append(data)
                            
                            //Sort based on time
                            
                            self.data.sort { (p1, p2) -> Bool in

                                return p1.snippet.time > p2.snippet.time

                            }
                        }
   
                    }
                    
                    self.lastDoc = snap!.documents.last
                }
                
            }
        }
    }

Upvotes: 1

Views: 549

Answers (1)

ChrisTech44
ChrisTech44

Reputation: 106

I suggest giving each document a timestamp field. I would modify your query to look something more like this.

db.collection("References").whereField("followers", arrayContains: uid).order(by: "timestamp", descending: true).limit(to: 10)

//put the timeStamp in a global variable 
var lastTimestamp: Timestamp?
lastTimeStamp = snapshot.documents?.data()["timestamp"] as! Timestamp

Then, when you make your next request, your query should look something like this

db.collection("References").whereField("followers", arrayContains: uid).whereField("timestamp", isLessThan: lastTimestamp).order(by: "timestamp", descending: true).limit(to: 10)

//then repeat by putting the last documents timestamp into the global variable
lastTimeStamp = snapshot.documents?.data()["timestamp"] as! Timestamp

Upvotes: 2

Related Questions