In essence, what I am doing is similar to snapchat stories. That said, I am creating a document for each story under the same collection "Stories". The problems begin in that I need to be able to request stories by different fields at the same time.
Ex. of story data model:
struct StoryModel: Identifiable {
var id: String
var isLive: Bool?
var name: String?
var description: String?
var isPrivate: Bool?
var userIDsJoined: [String]?
var userIDsWatching: [String]?
var startDate: Date?
var endDate: Date?
var hostInfoRef: DocumentReference?
}
I want to be able to do a whereField on isLive, but also sortBy userIDsWatching in the same query. How can I still do this sort of query:
Firestore.firestore()
.collection("Stories")
.whereField("isLive", isEqualTo: true)
.order(by: "userIDsWatching", descending: true)
.limitTo(5)
This query is invalid, see this link on why.
My only alternative is to create a separate collection to store stories in that are live and move them to "Stories" collection when isLive is false.
CodePudding user response:
As you wrote, you have an error: "You cannot use whereField
and sortBy
on different fields." Firestore queries with sortBy
method need to have first whereField
method same as sortBy
method.
So you can write code like this:
Firestore.firestore()
.collection("Stories")
.whereField("created") // it cannot be boolean value same as array like you have in userIdsWatching field.
.sortBy("created", descending: true)
.limitTo(5)
Or I'm pretty sure it can work like that:
Firestore.firestore()
.collection("Stories")
.whereField("created")
.whereField("isLive", isEqualTo: true)
.sortBy("created", descending: true)
.limitTo(5)
In the second example, important might be the order of .whereFields
functions. First need to be same as in sortBy
method. Before you start to learn programming, learn how to read with understanding text. Your error exactly says what you have wrong in code.
And Firestore are not filtering anything. Firestore just pick and sorts documents from database. Filtering word is not correct that why you have whereField
method, no filterByField
method.
I found one thing. Did you know that examples in swift are different from yours?
citiesRef
.whereField("population", isGreaterThan: 100000)
.order(by: "population") // this line is diferent same as bellow
.limit(to: 2)
CodePudding user response:
With the help of @Mises I was pointed in a better direction and finally got an error to print. The error was "Listen for query at Stories failed: The query requires an index. You can create it here..."
The solution to my problem was to:
- create a new field in StoryModel such as "totalViewing: Int?"
- Create an index for the Stories collection
The first fix was because orderBy on an field array returns values like this: sort and order I thought orderBy on a field like "userIDsWatching" would order them by the document with the largest amount of values in an array. This is wrong according to the above link @Doug Stevenson provided.
The second fix was something I was unaware you can even do. I created an index and now by running this query it works as it should.
Firestore.firestore()
.collection("Stories")
.whereField("isLive", isEqualTo: true)
.order(by: "totalViewing", descending" true)
.limit(to: 5)
Between those two changes I have found a way to orderBy one field and do whereField on a completely different field.