Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.6k views
in Technique[技术] by (71.8m points)

firebase - How to merge two queries using Firestore - Swift

I need to merge two queries with firebase firestore and then order the results using the timestamp field of the documents. Online I didn't find much information regarding Swift and Firestore. This is what I did so far:

db.collection("Notes").whereField("fromUid", isEqualTo: currentUserUid as Any).whereField("toUid", isEqualTo: chatUserUid as Any).getDocuments { (snapshot, error) in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        db.collection("Notes").whereField("fromUid", isEqualTo: self.chatUserUid as Any).whereField("toUid", isEqualTo: self.currentUserUid as Any).getDocuments { (snaphot1, error1) in
            if let err = error1{
                print(err.localizedDescription)
                return
            }
        }
    }

I added the second query inside the first one on completion but now I don't know how to merge them and order them through the field of timestamp.

On this insightful question It is explained that it's recommended to use a Task object but I don't find anything similar with swift.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There are many ways to accomplish this; here's one option.

To provide an answer, we have to make a couple of additions; first, we need somewhere to store the data retrieved from firebase so here's a class to contains some chat information

class ChatClass {
    var from = ""
    var to = ""
    var msg = ""
    var timestamp = 0

    convenience init(withDoc: DocumentSnapshot) {
        self.init()
        self.from = withDoc.get("from") as! String
        self.to = withDoc.get("to") as! String
        self.msg = withDoc.get("msg") as! String
        self.timestamp = withDoc.get("timestamp") as! Int
    }
}

then we need a class level array to store it so we can use it later - perhaps as a tableView dataSource

class ViewController: NSViewController {
    var sortedChatArray = [ChatClass]()

The setup is we have two users, Jay and Cindy and we want to retrieve all of the chats between them and sort by timestamp (just an Int in this case).

Here's the code that reads in all of the chats from one user to another creates ChatClass objects and adds them to an array. When complete that array is passed back to the calling completion handler for further processing.

func chatQuery(from: String, to: String, completion: @escaping( [ChatClass] ) -> Void) {
    let chatsColl = self.db.collection("chats") //self.db points to my Firestore
    chatsColl.whereField("from", isEqualTo: from).whereField("to", isEqualTo: to).getDocuments(completion: { snapshot, error in
        if let err = error {
            print(err.localizedDescription)
            return
        }

        guard let docs = snapshot?.documents else { return }

        var chatArray = [ChatClass]()

        for doc in docs {
            let chat = ChatClass(withDoc: doc)
            chatArray.append(chat)
        }

        completion(chatArray)
    })
}

Then the tricky bit. The code calls the above code which returns an array The above code is called again, returning another array. The arrays are combined, sorted and printed to console.

func buildChatArray() {
    self.chatQuery(from: "Jay", to: "Cindy", completion: { jayCindyArray in
        self.chatQuery(from: "Cindy", to: "Jay", completion: { cindyJayArray in
            let unsortedArray = jayCindyArray + cindyJayArray
            self.sortedChatArray = unsortedArray.sorted(by: { $0.timestamp < $1.timestamp })

            for chat in self.sortedChatArray {
                print(chat.timestamp, chat.from, chat.to, chat.msg)
            }
        })
    })
}

and the output

ts: 2  from: Cindy  to: Jay  msg: Hey Jay, Sup.
ts: 3  from: Jay    to: Cindy  msg: Hi Cindy. Not much
ts: 9  from: Jay    to: Cindy  msg: Talk to you later

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...