Данные о заказе и ограничении при пожаре возвращают отсутствующие результаты - PullRequest
1 голос
/ 23 марта 2020

Я хочу сделать несколько вещей, когда выбираю записи о пользователях в Firestore:

  • фильтрует пользователей по возрасту
  • фильтрует пользователей по полу, местоположению и избранным fruits
  • получить последних 6 недавно присоединившихся пользователей
  • получить пользователей, созданных до сегодняшнего дня
func observeUsers(){
let fruits: [String] = ["none"] 
let location = "Paris"
let gender = "male"
let startAge = 15
let endAge = 30
let today: Double = Date().timeIntervalSince1970

var query = db.collection("users") as Query
if(!fruits.isEmpty) {
   query = query.whereField("favoriteFruits", arrayContainsAny: fruits)
}

query
.whereField("location", isEqualTo: location)
.whereField("age", isGreaterThanOrEqualTo: startAge)
.whereField("age", isLessThanOrEqualTo: endAge)
.order(by: "age", descending: true) 
.order(by: "created", descending: true)
.start(at: [today])
.limit(to: 6)
.getDocuments { (querySnapshot, error) in
            if let err = error {
                print(err.localizedDescription)
                return
            }
            guard let docs = querySnapshot?.documents else {
                return
            }
            docs.forEach({ (doc) in
                print(doc.data())
            })
}
}

У меня включен только один составной индекс favoriteFruits Arrays location Ascending gender Ascending age Descending created Descending

Каждый пользователь имеет одинаковые поля: ["gender": male, "favoriteFruits": <__NSArrayM 0x600003745590>(none), "created": 1585606054.78943, "firstname": Seven, "location": Paris, "age": 22 ]

Если запрос ограничен 12, возвращаются все пользователи: Seven, Brian, Aaron, Chuck, Sally, Marty, Jessie, Trevor, Riley, Boren, Michael, France

Если запрос ограничен 6, следующие пользователи возвращаются в следующем порядке: Chuck, Sally, Marty, Jessie, Riley, Boren

ОЖИДАЕМЫЕ: Seven, Brian, Aaron, Chuck, Sally, Marty первые шесть пользователей, которые должны быть возвращены

Проблема с обратным разбиением на страницы или индексацией? Это потому, что я упорядочиваю данные по двум полям? Является ли курсор запроса недостаточно уникальным?

Помощь очень ценится!

Ниже приведен скриншот пользователя в Firestore: enter image description here

1 Ответ

1 голос
/ 26 марта 2020

В вопросе массив fruits пуст, и это фактически привело бы к тому, что запрос cra sh. Поэтому я обновил код, добавив несколько фруктов в этот массив по одному из каждой пользовательской коллекции, чтобы они соответствовали запросу.

Я заполнил коллекцию COLLECTION_USERS в Firestore вашими точными данными - с одним исключением в том, что документ идентификаторы были uid_0, uid_1, uid_2, но поля точно совпадают.

Затем я запустил мой обновленный код, он возвращает всех трех пользователей.

Вот обновленный код, который идентичен, за исключением тех, что пару изменений. (Я также добавил в сегодняшнюю переменную, как упомянуто в комментариях)

func querySomeData() {
    var fruits: [String] = []
    let location = "New York"
    let gender = "male"
    let startAge = 20
    let endAge = 30
    let today: Double = Date().timeIntervalSince1970

    fruits.append(contentsOf: ["ea", "et", "id"])

    let collectionUsers = self.db.collection("COLLECTION_USERS")
    collectionUsers
        .whereField("favoriteFruits", arrayContainsAny: fruits)
        .whereField("location", isEqualTo: location)
        .whereField("gender", isEqualTo: gender)
        .whereField("age", isGreaterThanOrEqualTo: startAge)
        .whereField("age", isLessThanOrEqualTo: endAge)
        .order(by: "age", descending: true) // or ascending
        .order(by: "created", descending: true)
        .start(at: [today])
        .limit(to: 6)
        .getDocuments() { querySnapshot, error in

            if let err = error {
                print(err.localizedDescription)
                return
            }

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

            for doc in docs {
                print(doc.documentID)
            }

    }
}

и вывод

uid_0
uid_2
uid_1

Таким образом, исключая эту пару различий (добавление фруктов в массив и documentID ) код в вопросе работает.

РЕДАКТИРОВАТЬ:

ОП также хочет вернуть пользователей, у которых нет любимого фрукта, поэтому массив в Firestore будет быть пустым Вы не можете запросить пустой массив, так как непустой массив требуется для фильтров 'arrayContainsAny'. Таким образом, простое решение состоит в том, чтобы добавить заполнитель (очень распространенный в базах данных No SQL), указывающий, что у пользователя нет любимого фрукта. Таким образом, массив в Firestore будет выглядеть следующим образом:

favoriteFruits
   0: "none"

, и запрос будет включать этот

fruits.append(contentsOf: ["ea", "et", "id", "none"])

, который будет возвращать всех пользователей, у которых есть эти любимые фрукты или нет любимых фруктов.

...