instead of running a snapshot for all users how do you set up multiple queries to limit the number of users sent to the device?

Edit: This answer is in Firestore, not Realtime Database. However, the concepts are the same.

The question is several questions in one; asking about distance, compound queries and how to query Firebase in general. I will post this answer to address the second two and distance queries are addressed in the comment to the question.

Once the query pattern is understood, they become easier and most importantly; it becomes more obvious that how your data is structured depends on what queries you want to run against that data.

Suppose we have a users collection with user documents – each documentId is the users uid

users
   uid_0
      name: "Leroy"

and then we have the posts for the users – each post contains some text, a timestamp of the post, the uid of the user that posted it, what the topic is and a url of a picture that appears in the post. Notice I am storing posts in a separate collection; why read in a bunch of user data when we only want to know about their post.

posts
   post_id
      postText: "pretty flowers"
      postDate: "20201103"
      postUrl: "www....."
      postUid: "uid_0"
      postTopic: "flowers"

Let suppose we want to get posts from today that are about flowers, and then also get the posters name and output who posted the message and what they said.

To do this we will need a compound query and then a subquery to retrieve the posters name as well.

func getTodaysPostsAboutFlowers() {
    let postsCollection = self.db.collection("posts")
    let query = postsCollection.whereField("postDate", isEqualTo: "20201103").whereField("postTopic", isEqualTo: "flowers")
    query.getDocuments(completion: { snapshot, error in
        if let err = error {
             print(err.localizedDescription)
             return
         }

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

         for doc in docs {
            let postText = doc.get("postText") as? String ?? "No text"
            guard let postersUid = doc.get("postUid") as? String else { return }
            self.outputPostTextAndUserName(withText: postText, andUid: postersUid)
         }
    })
}

The above performs a compound query on both the postDate field as the postTopic field.

The above then calls another function to retrieve the users name and output both the name and what they said

func outputPostTextAndUserName(withText: String, andUid: String) {
    let usersCollection = self.db.collection("users")
    let theUserDoc = usersCollection.document(andUid)
    theUserDoc.getDocument(completion: { documentSnapshot, error in
        if let err = error {
             print(err.localizedDescription)
             return
         }

        if let doc = documentSnapshot {
            let postersName = doc.get("name") as? String ?? "No Name"
            print("\(postersName) posted: \(withText)")
        }
    })
}

and the output

Leroy posted: pretty flowers

As you can see, there’s no need to load all of the users, no need to iterate over results etc. Even if you have a billion users, this will only return a subset of that data which is a best practice when working with huge data sets; only get the data you’re interested in.

Edit. The OP is asking about querying for nodes containing today. The simple solution is to have one child node containing a timestamp which would contains specific date data and then another child node just containing today data in YYYYMMDD format.

people uid_x timetamps: 9023490823498 //Date(timeIntervalSince1970: todaystamp: “20201106” // yyyymmdd format

that makes querying for nodes that contain today very simple.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top