3

I want to build a method that can accommodate all cases of my query.

so I want to search for an event from my events collection. it can be searched based on filter whether it is free events or not, and also if it needs to search specific event type or show all events regardless of the event type.

I assumed that I can build a query like this, but the result is wrong. is the way I write the query right?

Here the code of my method:

   fun searchEventByParameters(onlyFreeEvents: Boolean, startDate: Date, endDate: Date, selectedCity: String, selectedEventType: String, limit: Long, lastDocument: DocumentSnapshot?, completion: (errorMessage:String?, events: ArrayList<Event>?, lastDocument: DocumentSnapshot?) -> Unit) {

        val ref = db.collection("events")
        lateinit var query : Query

        query = ref
            .whereEqualTo(FIRESTORE_EVENT_FIELD_CITY,selectedCity)
            .whereEqualTo(FIRESTORE_EVENT_FIELD_IS_ACTIVE,true)
            .whereEqualTo(FIRESTORE_EVENT_FIELD_HAS_BEEN_APPROVED,true)


        if (onlyFreeEvents) {
            query.whereEqualTo(FIRESTORE_EVENT_FIELD_PRICE,0)
        }

        if (selectedEventType == "show specific event type") {
            query.whereEqualTo(FIRESTORE_EVENT_FIELD_EVENT_TYPE, selectedEventType)
        }

        query.whereGreaterThan(FIRESTORE_EVENT_FIELD_DATE_START_TIME,startDate)
            .whereLessThan(FIRESTORE_EVENT_FIELD_DATE_START_TIME,endDate)
            .orderBy(FIRESTORE_EVENT_FIELD_DATE_START_TIME, Query.Direction.ASCENDING)
            .limit(limit)

        if (lastDocument != null) {
            query.startAfter(lastDocument)
        }



        query.get()
            .addOnSuccessListener { snapshot ->

                val eventDocuments = snapshot.documents

                if (eventDocuments.isEmpty()) {

                    completion("Tidak ada event",null,null)

                } else {

                    val lastDocument = snapshot.documents.last()
                    val eventArray = ArrayList<Event>()

                    for (document in eventDocuments) {
                        val eventData = document.data
                        val event = Event(dataEvent = eventData)
                        eventArray.add(event)
                    }

                    completion(null,eventArray,lastDocument)

                }



            }.addOnFailureListener {
                completion(it.localizedMessage,null, null)
            }




    }

here is the screenshot of my database

enter image description here

I assume I can chaining the query like that, but the result is weird. no matter I choose the filter, say I want only show only free events or only music event (event type), the result seems always show all the events in the collection, and the pagination is also failed, seems never-ending.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
Alexa289
  • 8,089
  • 10
  • 74
  • 178
  • Why do you say it's wrong? What is not working the way you expect? – Alex Mamo Dec 20 '19 at 09:53
  • I mean, the documents showed are not the same as I expect. so currently I try to investigate where the location I make mistake. I suspect the problem is in the code I write the query. I am not sure the way i write the query like that is right or wrong. is the way I write the code like that valid ? – Alexa289 Dec 20 '19 at 09:57
  • Please provide us a concrete example of a particular query that doesn't return the result you are expecting. Please also add your database structure as a screenshot. – Alex Mamo Dec 20 '19 at 10:22
  • @AlexMamo I have added the complete code and also the screenshot of my database – Alexa289 Dec 20 '19 at 10:51
  • Oh, I see now. I'll write you an answer right away. – Alex Mamo Dec 20 '19 at 11:00
  • You can do what you asked, but you can't have greater than and less than on different fields (so even with Alex's fix, you need a different strategy). – charles-allen Dec 20 '19 at 11:10
  • You have to reassign `query` with each new filter that you want to add to it. The marked duplicate shows a general pattern that works for all client platforms. – Doug Stevenson Dec 20 '19 at 16:14

1 Answers1

2

Cloud Firestore queries are immutable! This means that you can not change the properties of an existing query. If you change the value by calling for instance:

query.whereEqualTo(FIRESTORE_EVENT_FIELD_PRICE,0)

It becomes a new query. So to solve this, you need to save the new query in the original object:

query = query.whereEqualTo(FIRESTORE_EVENT_FIELD_PRICE,0)

Now your query will filter the elements using the following four whereEqualTo() calls cumulative:

.whereEqualTo(FIRESTORE_EVENT_FIELD_CITY,selectedCity)
.whereEqualTo(FIRESTORE_EVENT_FIELD_IS_ACTIVE,true)
.whereEqualTo(FIRESTORE_EVENT_FIELD_HAS_BEEN_APPROVED,true)
.whereEqualTo(FIRESTORE_EVENT_FIELD_PRICE,0)
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193