Skip to content

Commit e376414

Browse files
committed
Android AggregateQuery support
1 parent b16f2f7 commit e376414

File tree

9 files changed

+173
-0
lines changed

9 files changed

+173
-0
lines changed

firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import dev.gitlive.firebase.FirebaseApp
1212
import dev.gitlive.firebase.android
1313
import dev.gitlive.firebase.firestore.internal.NativeDocumentSnapshotWrapper
1414
import java.util.concurrent.Executor
15+
import com.google.firebase.firestore.AggregateField as AndroidAggregateField
16+
import com.google.firebase.firestore.AggregateField.AverageAggregateField as AndroidAverageAggregateField
17+
import com.google.firebase.firestore.AggregateField.CountAggregateField as AndroidCountAggregateField
18+
import com.google.firebase.firestore.AggregateField.SumAggregateField as AndroidSumAggregateField
19+
import com.google.firebase.firestore.AggregateQuery as AndroidAggregateQuery
20+
import com.google.firebase.firestore.AggregateQuerySnapshot as AndroidAggregateQuerySnapshot
1521
import com.google.firebase.firestore.CollectionReference as AndroidCollectionReference
1622
import com.google.firebase.firestore.DocumentChange as AndroidDocumentChange
1723
import com.google.firebase.firestore.DocumentReference as AndroidDocumentReference
@@ -124,6 +130,15 @@ internal actual typealias NativeQuery = AndroidQuery
124130
public operator fun Query.Companion.invoke(android: AndroidQuery): Query = Query(android)
125131
public val Query.android: AndroidQuery get() = native
126132

133+
internal actual typealias NativeAggregateQuery = AndroidAggregateQuery
134+
internal actual typealias NativeAggregateQuerySnapshot = AndroidAggregateQuerySnapshot
135+
136+
public operator fun AggregateQuery.Companion.invoke(android: AndroidQuery): AggregateQuery = AggregateQuery(android)
137+
public val AggregateQuery.android: AndroidAggregateQuery get() = native
138+
139+
public operator fun AggregateQuerySnapshot.Companion.invoke(android: AndroidAggregateQuerySnapshot): AggregateQuerySnapshot = AggregateQuerySnapshot(android)
140+
public val AggregateQuerySnapshot.android: AndroidAggregateQuerySnapshot get() = native
141+
127142
public actual typealias Direction = AndroidQuery.Direction
128143
public actual typealias ChangeType = AndroidDocumentChange.Type
129144

@@ -198,3 +213,26 @@ public actual class FieldPath private constructor(internal val android: AndroidF
198213
public actual typealias EncodedFieldPath = AndroidFieldPath
199214

200215
internal typealias NativeSource = AndroidSource
216+
217+
public actual sealed class AggregateField {
218+
219+
public abstract val android: AndroidAggregateField
220+
221+
public actual companion object {
222+
public actual fun average(field: String): Average = Average(AndroidAggregateField.average(field))
223+
public actual fun average(fieldPath: FieldPath): Average = Average(AndroidAggregateField.average(fieldPath.android))
224+
public actual fun count(): Count = Count
225+
public actual fun sum(field: String): Sum = Sum(AndroidAggregateField.sum(field))
226+
public actual fun sum(fieldPath: FieldPath): Sum = Sum(AndroidAggregateField.sum(fieldPath.android))
227+
}
228+
229+
public actual data object Count : AggregateField() {
230+
override val android: AndroidCountAggregateField get() = AndroidAggregateField.count()
231+
}
232+
public actual data class Average(
233+
override val android: AndroidAverageAggregateField
234+
) : AggregateField()
235+
public actual data class Sum(
236+
override val android: AndroidSumAggregateField
237+
) : AggregateField()
238+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dev.gitlive.firebase.firestore.internal
2+
3+
import dev.gitlive.firebase.firestore.AggregateField
4+
import dev.gitlive.firebase.firestore.AggregateSource
5+
import dev.gitlive.firebase.firestore.NativeAggregateQuery
6+
import dev.gitlive.firebase.firestore.NativeAggregateQuerySnapshot
7+
import dev.gitlive.firebase.firestore.NativeQuery
8+
import kotlinx.coroutines.tasks.await
9+
10+
internal actual class NativeAggregateQueryWrapper actual constructor(actual val native: NativeAggregateQuery) {
11+
12+
actual val query: NativeQuery get() = native.query
13+
14+
actual suspend fun get(source: AggregateSource): NativeAggregateQuerySnapshot = native.get(when (source) {
15+
AggregateSource.SERVER -> com.google.firebase.firestore.AggregateSource.SERVER
16+
}).await()
17+
}
18+
19+
internal actual class NativeAggregateQuerySnapshotWrapper actual constructor(actual val native: NativeAggregateQuerySnapshot) {
20+
actual val query: NativeAggregateQuery get() = native.query
21+
actual val count: Long get() = native.count
22+
23+
actual operator fun get(aggregateField: AggregateField): Number? = native.get(aggregateField.android) as? Number
24+
actual operator fun get(averageAggregateField: AggregateField.Average): Double? = native.get(averageAggregateField.android)
25+
actual operator fun get(countAggregateField: AggregateField.Count): Long = native.get(countAggregateField.android)
26+
actual fun getDouble(aggregateField: AggregateField): Double? = native.getDouble(aggregateField.android)
27+
actual fun getLong(aggregateField: AggregateField): Long? = native.getLong(aggregateField.android)
28+
}

firebase-firestore/src/androidMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import com.google.android.gms.tasks.TaskExecutors
44
import com.google.firebase.firestore.FieldPath
55
import com.google.firebase.firestore.MetadataChanges
66
import com.google.firebase.firestore.Query
7+
import dev.gitlive.firebase.firestore.AggregateField
78
import dev.gitlive.firebase.firestore.Direction
89
import dev.gitlive.firebase.firestore.EncodedFieldPath
910
import dev.gitlive.firebase.firestore.Filter
11+
import dev.gitlive.firebase.firestore.NativeAggregateQuery
1012
import dev.gitlive.firebase.firestore.NativeDocumentSnapshot
1113
import dev.gitlive.firebase.firestore.QuerySnapshot
1214
import dev.gitlive.firebase.firestore.Source
@@ -19,6 +21,7 @@ import kotlinx.coroutines.tasks.await
1921
internal actual open class NativeQueryWrapper internal actual constructor(actual open val native: Query) {
2022

2123
actual fun limit(limit: Number) = native.limit(limit.toLong())
24+
actual fun limitToLast(limit: Number) = native.limitToLast(limit.toLong())
2225

2326
actual val snapshots get() = callbackFlow {
2427
val listener = native.addSnapshotListener { snapshot, exception ->
@@ -137,4 +140,7 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
137140
}
138141
awaitClose { registration.remove() }
139142
}
143+
144+
actual fun count(): NativeAggregateQuery = native.count()
145+
actual fun aggregate(aggregateField: AggregateField, vararg aggregateFields: AggregateField) = native.aggregate(aggregateField.android, *aggregateFields.map { it.android }.toTypedArray())
140146
}

firebase-firestore/src/appleMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import platform.Foundation.NSNull
1818
internal actual open class NativeQueryWrapper internal actual constructor(actual open val native: NativeQuery) {
1919

2020
actual fun limit(limit: Number) = native.queryLimitedTo(limit.toLong())
21+
actual fun limitToLast(limit: Number) = native.queryLimitedToLast(limit.toLong())
2122

2223
actual suspend fun get(source: Source) = QuerySnapshot(awaitResult { native.getDocumentsWithSource(source.toIosSource(), it) })
2324

firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import dev.gitlive.firebase.internal.EncodedObject
1010
import dev.gitlive.firebase.Firebase
1111
import dev.gitlive.firebase.FirebaseApp
1212
import dev.gitlive.firebase.FirebaseException
13+
import dev.gitlive.firebase.firestore.internal.NativeAggregateQuerySnapshotWrapper
14+
import dev.gitlive.firebase.firestore.internal.NativeAggregateQueryWrapper
1315
import dev.gitlive.firebase.firestore.internal.NativeCollectionReferenceWrapper
1416
import dev.gitlive.firebase.firestore.internal.NativeDocumentReference
1517
import dev.gitlive.firebase.firestore.internal.NativeDocumentSnapshotWrapper
@@ -247,6 +249,7 @@ public open class Query internal constructor(internal val nativeQuery: NativeQue
247249
internal open val native: NativeQuery = nativeQuery.native
248250

249251
public fun limit(limit: Number): Query = Query(nativeQuery.limit(limit))
252+
public fun limitToLast(limit: Number): Query = Query(nativeQuery.limitToLast(limit))
250253
public val snapshots: Flow<QuerySnapshot> = nativeQuery.snapshots
251254
public fun snapshots(includeMetadataChanges: Boolean = false): Flow<QuerySnapshot> = nativeQuery.snapshots(includeMetadataChanges)
252255
public suspend fun get(source: Source = Source.DEFAULT): QuerySnapshot = nativeQuery.get(source)
@@ -340,6 +343,10 @@ public open class Query internal constructor(internal val nativeQuery: NativeQue
340343
* @param builder closure for configuring the [FieldValuesDSL]
341344
*/
342345
public fun endAtFieldValues(builder: FieldValuesDSL.() -> Unit): Query = Query(nativeQuery.endAt(*FieldValuesDSL().apply(builder).fieldValues.toTypedArray()))
346+
347+
public fun aggregate(aggregateField: AggregateField, vararg aggregateFields: AggregateField): AggregateQuery = AggregateQuery(
348+
nativeQuery.aggregate(aggregateField, *aggregateFields)
349+
)
343350
}
344351

345352
@Deprecated("Deprecated in favor of using a [FilterBuilder]", replaceWith = ReplaceWith("where { field equalTo equalTo }", "dev.gitlive.firebase.firestore"))
@@ -394,6 +401,39 @@ public fun Query.where(path: FieldPath, inArray: List<Any>? = null, arrayContain
394401
)
395402
}
396403

404+
internal expect class NativeAggregateQuery
405+
internal expect class NativeAggregateQuerySnapshot
406+
407+
public class AggregateQuery internal constructor(internal val nativeQuery: NativeAggregateQueryWrapper) {
408+
409+
public companion object {}
410+
411+
public val query: Query get() = Query(nativeQuery.query)
412+
internal val native = nativeQuery.native
413+
414+
internal constructor(native: NativeAggregateQuery) : this(NativeAggregateQueryWrapper(native))
415+
416+
public suspend fun get(source: AggregateSource = AggregateSource.SERVER): AggregateQuerySnapshot = AggregateQuerySnapshot(nativeQuery.get(source))
417+
418+
}
419+
420+
public class AggregateQuerySnapshot internal constructor(internal val nativeSnapshot: NativeAggregateQuerySnapshotWrapper) {
421+
422+
public companion object {}
423+
424+
public val query: AggregateQuery get() = AggregateQuery(nativeSnapshot.query)
425+
internal val native = nativeSnapshot.native
426+
public val count: Long get() = nativeSnapshot.count
427+
428+
internal constructor(native: NativeAggregateQuerySnapshot) : this(NativeAggregateQuerySnapshotWrapper(native))
429+
430+
public operator fun get(aggregateField: AggregateField): Number? = nativeSnapshot[aggregateField]
431+
public operator fun get(averageAggregateField: AggregateField.Average): Double? = nativeSnapshot[averageAggregateField]
432+
public operator fun get(countAggregateField: AggregateField.Count): Long = nativeSnapshot[countAggregateField]
433+
public fun getDouble(aggregateField: AggregateField): Double? = nativeSnapshot.getDouble(aggregateField)
434+
public fun getLong(aggregateField: AggregateField): Long? = nativeSnapshot.getLong(aggregateField)
435+
}
436+
397437
internal expect class NativeWriteBatch
398438

399439
public data class WriteBatch internal constructor(internal val nativeWrapper: NativeWriteBatchWrapper) {
@@ -827,3 +867,23 @@ public enum class Source {
827867
SERVER,
828868
DEFAULT,
829869
}
870+
871+
public enum class AggregateSource {
872+
SERVER
873+
}
874+
875+
public expect sealed class AggregateField {
876+
877+
public companion object {
878+
public fun average(field: String): Average
879+
public fun average(fieldPath: FieldPath): Average
880+
public fun count(): Count
881+
public fun sum(field: String): Sum
882+
public fun sum(fieldPath: FieldPath): Sum
883+
}
884+
885+
public object Count : AggregateField
886+
public class Average : AggregateField
887+
public class Sum : AggregateField
888+
889+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package dev.gitlive.firebase.firestore.internal
2+
3+
import dev.gitlive.firebase.firestore.AggregateField
4+
import dev.gitlive.firebase.firestore.AggregateSource
5+
import dev.gitlive.firebase.firestore.NativeAggregateQuery
6+
import dev.gitlive.firebase.firestore.NativeAggregateQuerySnapshot
7+
import dev.gitlive.firebase.firestore.NativeQuery
8+
9+
internal expect class NativeAggregateQueryWrapper(native: NativeAggregateQuery) {
10+
11+
val native: NativeAggregateQuery
12+
val query: NativeQuery
13+
14+
suspend fun get(source: AggregateSource = AggregateSource.SERVER): NativeAggregateQuerySnapshot
15+
16+
}
17+
18+
internal expect class NativeAggregateQuerySnapshotWrapper(native: NativeAggregateQuerySnapshot) {
19+
val native: NativeAggregateQuerySnapshot
20+
val query: NativeAggregateQuery
21+
val count: Long
22+
23+
operator fun get(aggregateField: AggregateField): Number?
24+
operator fun get(averageAggregateField: AggregateField.Average): Double?
25+
operator fun get(countAggregateField: AggregateField.Count): Long
26+
fun getDouble(aggregateField: AggregateField): Double?
27+
fun getLong(aggregateField: AggregateField): Long?
28+
}

firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package dev.gitlive.firebase.firestore.internal
22

3+
import dev.gitlive.firebase.firestore.AggregateField
34
import dev.gitlive.firebase.firestore.Direction
45
import dev.gitlive.firebase.firestore.EncodedFieldPath
56
import dev.gitlive.firebase.firestore.Filter
7+
import dev.gitlive.firebase.firestore.NativeAggregateQuery
68
import dev.gitlive.firebase.firestore.NativeDocumentSnapshot
79
import dev.gitlive.firebase.firestore.NativeQuery
810
import dev.gitlive.firebase.firestore.QuerySnapshot
@@ -14,6 +16,7 @@ internal expect open class NativeQueryWrapper internal constructor(native: Nativ
1416
open val native: NativeQuery
1517

1618
fun limit(limit: Number): NativeQuery
19+
fun limitToLast(limit: Number): NativeQuery
1720
val snapshots: Flow<QuerySnapshot>
1821
fun snapshots(includeMetadataChanges: Boolean = false): Flow<QuerySnapshot>
1922
suspend fun get(source: Source = Source.DEFAULT): QuerySnapshot
@@ -32,4 +35,7 @@ internal expect open class NativeQueryWrapper internal constructor(native: Nativ
3235
fun endBefore(vararg fieldValues: Any): NativeQuery
3336
fun endAt(document: NativeDocumentSnapshot): NativeQuery
3437
fun endAt(vararg fieldValues: Any): NativeQuery
38+
39+
fun count(): NativeAggregateQuery
40+
fun aggregate(aggregateField: AggregateField, vararg aggregateFields: AggregateField): NativeAggregateQuery
3541
}

firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/externals/firestore.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ public external fun increment(n: Int): FieldValue
8888
public external fun initializeFirestore(app: FirebaseApp, settings: dynamic = definedExternally, databaseId: String? = definedExternally): Firestore
8989

9090
public external fun limit(limit: Number): QueryConstraint
91+
public external fun limitToLast(limit: Number): QueryConstraint
9192

9293
public external fun onSnapshot(
9394
reference: DocumentReference,

firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/internal/NativeQueryWrapper.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ internal actual open class NativeQueryWrapper internal actual constructor(actual
3838
dev.gitlive.firebase.firestore.externals.limit(limit),
3939
).wrapped
4040

41+
actual fun limitToLast(limit: Number) = query(
42+
js,
43+
dev.gitlive.firebase.firestore.externals.limitToLast(limit)
44+
).wrapped
45+
4146
actual fun where(filter: Filter) = query(js, filter.toQueryConstraint()).wrapped
4247

4348
private fun Filter.toQueryConstraint(): QueryConstraint = when (this) {

0 commit comments

Comments
 (0)