Firestore订单和限制数据返回丢失的结果



当我在Firestore中获取用户记录时,我想做一些事情:

  • 筛选年龄范围内的用户
  • 根据性别、位置筛选用户
  • 获取最近加入的6个用户
  • 获取在今天之前创建的用户
func observeUsers(){
let location = "Paris"
let gender = "male"
let startAge = 15
let endAge = 30
let today: Double = Date().timeIntervalSince1970
var query = db.collection("users") as Query
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())
})
}
}

我只有一个启用了location Ascending gender Ascending age Descending created Descending的复合索引

每个用户都有相同的字段:["gender": male, "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将返回的前六个用户

问题是反向分页还是索引?是因为我按两个字段对数据进行排序吗?查询光标是否不够唯一?

非常感谢您的帮助!

在问题中,fruits数组为空,这实际上会导致查询崩溃。因此,我更新了代码,向该数组中添加了一些水果,每个用户集合中都有一个水果,这样它们就能匹配查询。

我在Firestore中用您的确切数据填充了COLLECTION_USERS集合,但有一个例外,即文档id是uid_0、uid_1和uid_2,但字段完全匹配。

然后我运行了更新后的代码,它会返回所有三个用户。

这是更新后的代码,除了这几处更改外,其他代码都是相同的。(我还在今天的var中添加了评论中提到的(

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添加水果(,问题中的代码是有效的。

编辑:

OP还希望返回没有最喜欢的水果的用户,因此Firestore中的数组将为空。不能查询空数组,因为"arrayContainerAny"筛选器需要非空数组。因此,简单的解决方案是添加一个占位符(在NoSQL数据库中很常见(,指示用户没有喜欢的水果。所以Firestore中的数组看起来是这样的:

favoriteFruits
0: "none"

并且查询将包括这个

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

这将返回所有拥有那些喜爱的水果或没有喜爱的水果的用户。

最新更新