Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add start and end query cursors #286

Merged
merged 12 commits into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,13 @@ external object firebase {
fun orderBy(field: String, direction: Any): Query
fun orderBy(field: FieldPath, direction: Any): Query
fun startAfter(document: DocumentSnapshot): Query
fun startAfter(vararg fieldValues: Any): Query
fun startAt(document: DocumentSnapshot): Query
fun startAt(vararg fieldValues: Any): Query
fun endBefore(document: DocumentSnapshot): Query
fun endBefore(vararg fieldValues: Any): Query
fun endAt(document: DocumentSnapshot): Query
fun endAt(vararg fieldValues: Any): Query
}

open class CollectionReference : Query {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,14 @@ actual open class Query(open val android: com.google.firebase.firestore.Query) {
internal actual fun _orderBy(field: FieldPath, direction: Direction) = Query(android.orderBy(field.android, direction))

internal actual fun _startAfter(document: DocumentSnapshot) = Query(android.startAfter(document.android))
internal actual fun _startAfter(vararg fieldValues: Any) = Query(android.startAfter(*fieldValues))
internal actual fun _startAt(document: DocumentSnapshot) = Query(android.startAt(document.android))
internal actual fun _startAt(vararg fieldValues: Any) = Query(android.startAt(*fieldValues))

internal actual fun _endBefore(document: DocumentSnapshot) = Query(android.endBefore(document.android))
internal actual fun _endBefore(vararg fieldValues: Any) = Query(android.endBefore(*fieldValues))
internal actual fun _endAt(document: DocumentSnapshot) = Query(android.endAt(document.android))
internal actual fun _endAt(vararg fieldValues: Any) = Query(android.endAt(*fieldValues))
}

actual typealias Direction = com.google.firebase.firestore.Query.Direction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ expect open class Query {
internal fun _orderBy(field: FieldPath, direction: Direction): Query

internal fun _startAfter(document: DocumentSnapshot): Query
internal fun _startAfter(vararg fieldValues: Any): Query
internal fun _startAt(document: DocumentSnapshot): Query
internal fun _startAt(vararg fieldValues: Any): Query

internal fun _endBefore(document: DocumentSnapshot): Query
internal fun _endBefore(vararg fieldValues: Any): Query
internal fun _endAt(document: DocumentSnapshot): Query
internal fun _endAt(vararg fieldValues: Any): Query
}

fun Query.where(field: String, equalTo: Any?) = _where(field, equalTo)
Expand All @@ -85,6 +93,14 @@ fun Query.orderBy(field: String, direction: Direction = Direction.ASCENDING) = _
fun Query.orderBy(field: FieldPath, direction: Direction = Direction.ASCENDING) = _orderBy(field, direction)

fun Query.startAfter(document: DocumentSnapshot) = _startAfter(document)
fun Query.startAfter(vararg fieldValues: Any) = _startAfter(*fieldValues)
fun Query.startAt(document: DocumentSnapshot) = _startAt(document)
fun Query.startAt(vararg fieldValues: Any) = _startAt(*fieldValues)

fun Query.endBefore(document: DocumentSnapshot) = _endBefore(document)
fun Query.endBefore(vararg fieldValues: Any) = _endBefore(*fieldValues)
fun Query.endAt(document: DocumentSnapshot) = _endAt(document)
fun Query.endAt(vararg fieldValues: Any) = _endAt(*fieldValues)

expect class WriteBatch {
inline fun <reified T> set(documentRef: DocumentReference, data: T, encodeDefaults: Boolean = true, merge: Boolean = false): WriteBatch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,148 @@ class FirebaseFirestoreTest {

val lastDocumentSnapshot = firstPage.lastOrNull()
assertNotNull(lastDocumentSnapshot)
val secondPage = query.startAfter(lastDocumentSnapshot).limit(2).get().documents // Second 2 results (only one left)

val secondPage = query.startAfter(lastDocumentSnapshot).get().documents
assertEquals(1, secondPage.size)
assertEquals("ccc", secondPage[0].get("prop1"))
}

@Test
fun testStartAfterFieldValues() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.get().documents
assertEquals(3, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))
assertEquals("ccc", firstPage[2].get("prop1"))

val secondPage = query.startAfter("bbb").get().documents
assertEquals(1, secondPage.size)
assertEquals("ccc", secondPage[0].get("prop1"))
}

@Test
fun testStartAtDocumentSnapshot() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.limit(2).get().documents // First 2 results
assertEquals(2, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))

val lastDocumentSnapshot = firstPage.lastOrNull()
assertNotNull(lastDocumentSnapshot)

val secondPage = query.startAt(lastDocumentSnapshot).get().documents
assertEquals(2, secondPage.size)
assertEquals("bbb", secondPage[0].get("prop1"))
assertEquals("ccc", secondPage[1].get("prop1"))
}

@Test
fun testStartAtFieldValues() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.get().documents // First 2 results
assertEquals(3, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))
assertEquals("ccc", firstPage[2].get("prop1"))

val secondPage = query.startAt("bbb").get().documents
assertEquals(2, secondPage.size)
assertEquals("bbb", secondPage[0].get("prop1"))
assertEquals("ccc", secondPage[1].get("prop1"))
}

@Test
fun testEndBeforeDocumentSnapshot() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.limit(2).get().documents // First 2 results
assertEquals(2, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))

val lastDocumentSnapshot = firstPage.lastOrNull()
assertNotNull(lastDocumentSnapshot)

val secondPage = query.endBefore(lastDocumentSnapshot).get().documents
assertEquals(1, secondPage.size)
assertEquals("aaa", secondPage[0].get("prop1"))
}

@Test
fun testEndBeforeFieldValues() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.get().documents
assertEquals(3, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))
assertEquals("ccc", firstPage[2].get("prop1"))

val secondPage = query.endBefore("bbb").get().documents
assertEquals(1, secondPage.size)
assertEquals("aaa", secondPage[0].get("prop1"))
}

@Test
fun testEndAtDocumentSnapshot() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.limit(2).get().documents // First 2 results
assertEquals(2, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))

val lastDocumentSnapshot = firstPage.lastOrNull()
assertNotNull(lastDocumentSnapshot)

val secondPage = query.endAt(lastDocumentSnapshot).get().documents
assertEquals(2, secondPage.size)
assertEquals("aaa", secondPage[0].get("prop1"))
assertEquals("bbb", secondPage[1].get("prop1"))
}

@Test
fun testEndAtFieldValues() = runTest {
setupFirestoreData()
val query = Firebase.firestore
.collection("testFirestoreQuerying")
.orderBy("prop1", Direction.ASCENDING)

val firstPage = query.get().documents // First 2 results
assertEquals(3, firstPage.size)
assertEquals("aaa", firstPage[0].get("prop1"))
assertEquals("bbb", firstPage[1].get("prop1"))
assertEquals("ccc", firstPage[2].get("prop1"))

val secondPage = query.endAt("bbb").get().documents
assertEquals(2, secondPage.size)
assertEquals("aaa", secondPage[0].get("prop1"))
assertEquals("bbb", secondPage[1].get("prop1"))
}

@Test
fun testIncrementFieldValue() = runTest {
val doc = Firebase.firestore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ actual open class Query(open val ios: FIRQuery) {
internal actual fun _orderBy(field: FieldPath, direction: Direction) = Query(ios.queryOrderedByFieldPath(field.ios, direction == Direction.DESCENDING))

internal actual fun _startAfter(document: DocumentSnapshot) = Query(ios.queryStartingAfterDocument(document.ios))
internal actual fun _startAfter(vararg fieldValues: Any) = Query(ios.queryStartingAfterValues(fieldValues.asList()))
internal actual fun _startAt(document: DocumentSnapshot) = Query(ios.queryStartingAtDocument(document.ios))
internal actual fun _startAt(vararg fieldValues: Any) = Query(ios.queryStartingAtValues(fieldValues.asList()))

internal actual fun _endBefore(document: DocumentSnapshot) = Query(ios.queryEndingBeforeDocument(document.ios))
internal actual fun _endBefore(vararg fieldValues: Any) = Query(ios.queryEndingBeforeValues(fieldValues.asList()))
internal actual fun _endAt(document: DocumentSnapshot) = Query(ios.queryEndingAtDocument(document.ios))
internal actual fun _endAt(vararg fieldValues: Any) = Query(ios.queryEndingAtValues(fieldValues.asList()))

}
@Suppress("UNCHECKED_CAST")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,21 @@ actual open class Query(open val js: firebase.firestore.Query) {
Query(js.orderBy(field.js, direction.jsString))
}

internal actual fun _startAfter(document: DocumentSnapshot) = rethrow {
Query(js.startAfter(document.js))
}
internal actual fun _startAfter(document: DocumentSnapshot) = rethrow { Query(js.startAfter(document.js)) }

internal actual fun _startAfter(vararg fieldValues: Any) = rethrow { Query(js.startAfter(*fieldValues)) }

internal actual fun _startAt(document: DocumentSnapshot) = rethrow { Query(js.startAt(document.js)) }

internal actual fun _startAt(vararg fieldValues: Any) = rethrow { Query(js.startAt(*fieldValues)) }

internal actual fun _endBefore(document: DocumentSnapshot) = rethrow { Query(js.endBefore(document.js)) }

internal actual fun _endBefore(vararg fieldValues: Any) = rethrow { Query(js.endBefore(*fieldValues)) }

internal actual fun _endAt(document: DocumentSnapshot) = rethrow { Query(js.endAt(document.js)) }

internal actual fun _endAt(vararg fieldValues: Any) = rethrow { Query(js.endAt(*fieldValues)) }

actual val snapshots get() = callbackFlow<QuerySnapshot> {
val unsubscribe = rethrow {
Expand Down