0

I'm trying to query multiple child values for the search term in the search bar using swift and firebase. Currently, I'm querying just for the "title" attribute which works exceptionally well but is there a way that I can query for the "title" and the "category" and show the results?

func fetchSearchedPosts(searchTerm: String) {

    self.collectionView.refreshControl?.endRefreshing()
    let ref = Database.database().reference().child("posts").queryOrdered(byChild: "title").queryStarting(atValue: searchTerm).queryEnding(atValue: "\(searchTerm)\u{f8ff}")
   ref.observeSingleEvent(of: .value) { (snapshot) in

    if !snapshot.exists() { return }

    guard let dictionaries = snapshot.value as? [String: Any] else { return }
    self.posts.removeAll()
    let g = DispatchGroup()   ///// 1

    dictionaries.forEach({ (key, value) in

        guard let postDictionary = value as? [String: Any] else { return }
        guard let uid = postDictionary["uid"] as? String else { return }

        g.enter()   ///// 2
        Database.fetchUserWithUID(uid: uid, completion: { (user) in

            let post = Post(postId: key, user: user, dictionary: postDictionary)

            let nowTimeStamp = Date().timeIntervalSince1970
            let dateTime = post.endTimeDate
            let timeStamp = dateTime.timeIntervalSince1970

                if nowTimeStamp < timeStamp {

                    post.id = key
                    self.posts.append(post)

                } else {
                    g.leave()   ///// 3.a
                    return
                }
            g.leave()   ///// 3.b
        })
    })

    g.notify(queue:.main) {    ///// 4
      self.posts.sort(by: { (post1, post2) -> Bool in
           return post1.title.compare(post2.title) == .orderedAscending
       })
       self.collectionView.reloadData()
     }
  }
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
user
  • 345
  • 2
  • 8
  • 32
  • 1
    Firebase Database queries can only order/filter on a single property. In many cases it is possible to combine the values you want to filter on into a single (synthetic) property. For an example of this and other approaches, see my answer here: https://stackoverflow.com/questions/26700924/query-based-on-multiple-where-clauses-in-firebase – Frank van Puffelen Mar 16 '20 at 03:59

1 Answers1

0

In Firebase, queries on multiple fields at a time isn't possible as mentioned in the queries limitations in the documentation of Firebase Firestore.

Cloud Firestore provides limited support for logical OR queries. The in and array contains-any operators support a logical OR of up to 10 equality (==) or array-contains conditions on a single field. For other cases, create a separate query for each OR condition and merge the query results in your app.

https://firebase.google.com/docs/firestore/query-data/queries

Please refer to the query limitations section.

Now looking at the limitations what you can do is:

  1. query multiple times for each fields and merge the outputs.
  2. If you have less fields to query like in your case 2 (title and category) query initially using the field that would give you the smallest result and then perform a simple search on that output based on the other field in order to get the desired output.

There could be other ways to optimise the filtering process, but for a small database it wont be a problem.

halfer
  • 19,824
  • 17
  • 99
  • 186
Milan Lakhani
  • 528
  • 3
  • 13