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

feat(firestore): add getCountFromServer(...) method #792

Merged
merged 8 commits into from
Jan 9, 2025
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
5 changes: 5 additions & 0 deletions .changeset/friendly-shoes-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@capacitor-firebase/firestore': minor
---

feat: add `getCountFromServer` method
34 changes: 34 additions & 0 deletions packages/firestore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ const removeAllListeners = async () => {
* [`writeBatch(...)`](#writebatch)
* [`getCollection(...)`](#getcollection)
* [`getCollectionGroup(...)`](#getcollectiongroup)
* [`getCountFromServer(...)`](#getcountfromserver)
* [`clearPersistence()`](#clearpersistence)
* [`enableNetwork()`](#enablenetwork)
* [`disableNetwork()`](#disablenetwork)
Expand Down Expand Up @@ -433,6 +434,25 @@ Reads the collection group referenced by the specified reference.
--------------------


### getCountFromServer(...)

```typescript
getCountFromServer(options: GetCountFromServerOptions) => Promise<GetCountFromServerResult>
```

Fetches the number of documents in a collection.

| Param | Type |
| ------------- | ------------------------------------------------------------------------------- |
| **`options`** | <code><a href="#getcountfromserveroptions">GetCountFromServerOptions</a></code> |

**Returns:** <code>Promise&lt;<a href="#getcountfromserverresult">GetCountFromServerResult</a>&gt;</code>

**Since:** 6.4.0

--------------------


### clearPersistence()

```typescript
Expand Down Expand Up @@ -765,6 +785,20 @@ Remove all listeners for this plugin.
| **`queryConstraints`** | <code>QueryNonFilterConstraint[]</code> | Narrow or order the set of documents to retrieve, but do not explicitly filter for document fields. | 5.2.0 |


#### GetCountFromServerResult

| Prop | Type | Description | Since |
| ----------- | ------------------- | ------------------------------------------ | ----- |
| **`count`** | <code>number</code> | The number of documents in the collection. | 6.4.0 |


#### GetCountFromServerOptions

| Prop | Type | Description | Since |
| --------------- | ------------------- | ----------------------------------------------------------------------------------- | ----- |
| **`reference`** | <code>string</code> | The reference as a string, with path components separated by a forward slash (`/`). | 6.4.0 |


#### UseEmulatorOptions

| Prop | Type | Description | Default | Since |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import androidx.annotation.NonNull;
import com.getcapacitor.PluginCall;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.AggregateQuery;
import com.google.firebase.firestore.AggregateQuerySnapshot;
import com.google.firebase.firestore.AggregateSource;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.Filter;
Expand All @@ -19,6 +22,7 @@
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.DeleteDocumentOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCollectionGroupOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCollectionOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCountFromServerOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetDocumentOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.RemoveSnapshotListenerOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.SetDocumentOptions;
Expand All @@ -27,6 +31,7 @@
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.WriteBatchOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.results.AddDocumentResult;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.results.GetCollectionResult;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.results.GetCountFromServerResult;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.results.GetDocumentResult;
import io.capawesome.capacitorjs.plugins.firebase.firestore.interfaces.EmptyResultCallback;
import io.capawesome.capacitorjs.plugins.firebase.firestore.interfaces.NonEmptyResultCallback;
Expand Down Expand Up @@ -238,6 +243,26 @@ public void useEmulator(@NonNull String host, int port) {
getFirebaseFirestoreInstance().useEmulator(host, port);
}

public void getCountFromServer(@NonNull GetCountFromServerOptions options, @NonNull NonEmptyResultCallback callback) {
String reference = options.getReference();
Query query = getFirebaseFirestoreInstance().collection(reference);
AggregateQuery countQuery = query.count();

countQuery
.get(AggregateSource.SERVER)
.addOnCompleteListener(
task -> {
if (task.isSuccessful()) {
AggregateQuerySnapshot snapshot = task.getResult();
GetCountFromServerResult result = new GetCountFromServerResult(snapshot.getCount());
callback.success(result);
} else {
callback.error(task.getException());
}
}
);
}

public void addDocumentSnapshotListener(@NonNull AddDocumentSnapshotListenerOptions options, @NonNull NonEmptyResultCallback callback) {
String reference = options.getReference();
String callbackId = options.getCallbackId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.DeleteDocumentOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCollectionGroupOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCollectionOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetCountFromServerOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.GetDocumentOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.RemoveSnapshotListenerOptions;
import io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options.SetDocumentOptions;
Expand Down Expand Up @@ -394,6 +395,36 @@ public void useEmulator(PluginCall call) {
}
}

@PluginMethod
public void getCountFromServer(PluginCall call) {
try {
String reference = call.getString("reference");
if (reference == null) {
call.reject(ERROR_REFERENCE_MISSING);
return;
}

GetCountFromServerOptions options = new GetCountFromServerOptions(reference);
NonEmptyResultCallback callback = new NonEmptyResultCallback() {
@Override
public void success(Result result) {
call.resolve(result.toJSObject());
}

@Override
public void error(Exception exception) {
Logger.error(TAG, exception.getMessage(), exception);
call.reject(exception.getMessage());
}
};

implementation.getCountFromServer(options, callback);
} catch (Exception exception) {
Logger.error(TAG, exception.getMessage(), exception);
call.reject(exception.getMessage());
}
}

@PluginMethod(returnType = PluginMethod.RETURN_CALLBACK)
public void addDocumentSnapshotListener(PluginCall call) {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.capawesome.capacitorjs.plugins.firebase.firestore.classes.options;

import androidx.annotation.NonNull;

public class GetCountFromServerOptions {

@NonNull
private final String reference;

public GetCountFromServerOptions(@NonNull String reference) {
this.reference = reference;
}

@NonNull
public String getReference() {
return reference;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.capawesome.capacitorjs.plugins.firebase.firestore.classes.results;

import com.getcapacitor.JSObject;
import io.capawesome.capacitorjs.plugins.firebase.firestore.interfaces.Result;

public class GetCountFromServerResult implements Result {

private final long count;

public GetCountFromServerResult(long count) {
this.count = count;
}

@Override
public JSObject toJSObject() {
JSObject result = new JSObject();
result.put("count", count);
return result;
}
}
8 changes: 8 additions & 0 deletions packages/firestore/ios/Plugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
7C0070402ABC2DF8000C0F28 /* FirebaseFirestoreHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C00703F2ABC2DF8000C0F28 /* FirebaseFirestoreHelper.swift */; };
7C0070422ABC97E5000C0F28 /* QueryNonFilterConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0070412ABC97E5000C0F28 /* QueryNonFilterConstraint.swift */; };
7C0070442ABC9AE9000C0F28 /* QueryFilterConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0070432ABC9AE9000C0F28 /* QueryFilterConstraint.swift */; };
7C2AE7C92D2DBF7000F40418 /* GetCountFromServerOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2AE7C82D2DBF6D00F40418 /* GetCountFromServerOptions.swift */; };
7C2AE7CB2D2DC2B400F40418 /* GetCountFromServerResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C2AE7CA2D2DC2B100F40418 /* GetCountFromServerResult.swift */; };
7C90A58E2C21519B00A71389 /* AddCollectionGroupSnapshotListenerOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C90A58D2C21519B00A71389 /* AddCollectionGroupSnapshotListenerOptions.swift */; };
7CF0EFE32C207844004D910D /* WriteBatchOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF0EFE22C207844004D910D /* WriteBatchOptions.swift */; };
7CF0EFE52C20784E004D910D /* WriteBatchOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CF0EFE42C20784E004D910D /* WriteBatchOperation.swift */; };
Expand Down Expand Up @@ -92,6 +94,8 @@
7C00703F2ABC2DF8000C0F28 /* FirebaseFirestoreHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseFirestoreHelper.swift; sourceTree = "<group>"; };
7C0070412ABC97E5000C0F28 /* QueryNonFilterConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryNonFilterConstraint.swift; sourceTree = "<group>"; };
7C0070432ABC9AE9000C0F28 /* QueryFilterConstraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryFilterConstraint.swift; sourceTree = "<group>"; };
7C2AE7C82D2DBF6D00F40418 /* GetCountFromServerOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetCountFromServerOptions.swift; sourceTree = "<group>"; };
7C2AE7CA2D2DC2B100F40418 /* GetCountFromServerResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetCountFromServerResult.swift; sourceTree = "<group>"; };
7C90A58D2C21519B00A71389 /* AddCollectionGroupSnapshotListenerOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddCollectionGroupSnapshotListenerOptions.swift; sourceTree = "<group>"; };
7CF0EFE22C207844004D910D /* WriteBatchOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteBatchOptions.swift; sourceTree = "<group>"; };
7CF0EFE42C20784E004D910D /* WriteBatchOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WriteBatchOperation.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -190,6 +194,7 @@
7C0070302ABC1FB6000C0F28 /* Options */ = {
isa = PBXGroup;
children = (
7C2AE7C82D2DBF6D00F40418 /* GetCountFromServerOptions.swift */,
7C00700D2ABC1ED4000C0F28 /* AddCollectionSnapshotListenerOptions.swift */,
7C00700F2ABC1EE0000C0F28 /* AddDocumentOptions.swift */,
7C0070132ABC1F0F000C0F28 /* AddDocumentSnapshotListenerOptions.swift */,
Expand Down Expand Up @@ -223,6 +228,7 @@
7C0070382ABC2007000C0F28 /* Results */ = {
isa = PBXGroup;
children = (
7C2AE7CA2D2DC2B100F40418 /* GetCountFromServerResult.swift */,
7C0070112ABC1F03000C0F28 /* AddDocumentResult.swift */,
7C0070192ABC1F29000C0F28 /* GetCollectionGroupResult.swift */,
7C00701D2ABC1F38000C0F28 /* GetCollectionResult.swift */,
Expand Down Expand Up @@ -467,10 +473,12 @@
50E1A94820377CB70090CE1A /* FirebaseFirestorePlugin.swift in Sources */,
7C00702B2ABC1F7B000C0F28 /* QueryLimitConstraint.swift in Sources */,
7C0070202ABC1F42000C0F28 /* GetDocumentOptions.swift in Sources */,
7C2AE7CB2D2DC2B400F40418 /* GetCountFromServerResult.swift in Sources */,
7CF0EFE52C20784E004D910D /* WriteBatchOperation.swift in Sources */,
7C00701E2ABC1F38000C0F28 /* GetCollectionResult.swift in Sources */,
7C00702F2ABC1FAF000C0F28 /* QueryStartAtConstraint.swift in Sources */,
7C0070182ABC1F20000C0F28 /* GetCollectionGroupOptions.swift in Sources */,
7C2AE7C92D2DBF7000F40418 /* GetCountFromServerOptions.swift in Sources */,
7CF0EFE32C207844004D910D /* WriteBatchOptions.swift in Sources */,
7C0070102ABC1EE0000C0F28 /* AddDocumentOptions.swift in Sources */,
7C0070162ABC1F18000C0F28 /* DeleteDocumentOptions.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

@objc public class GetCountFromServerOptions: NSObject {
private let reference: String

init(reference: String) {
self.reference = reference
}

func getReference() -> String {
return reference
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Capacitor

@objc public class GetCountFromServerResult: NSObject, Result {
let count: Int

init(_ count: Int) {
self.count = count
}

public func toJSObject() -> AnyObject {
var result = JSObject()
result["count"] = count
return result as AnyObject
}
}
24 changes: 20 additions & 4 deletions packages/firestore/ios/Plugin/FirebaseFirestore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import FirebaseFirestore

private actor ListenerRegistrationMap {
private var listenerRegistrationMap: [String: ListenerRegistration] = [:]

func addRegistration(_ listenerRegistration: ListenerRegistration, listenerId: String) async {
listenerRegistrationMap[listenerId] = listenerRegistration
}

func removeRegistration(listenerId: String) async {
if let listenerRegistration = listenerRegistrationMap[listenerId] {
listenerRegistration.remove()
}
listenerRegistrationMap.removeValue(forKey: listenerId)
}

func removeAll() async {
listenerRegistrationMap.forEach { _, value in
value.remove()
Expand All @@ -27,7 +27,7 @@ private actor ListenerRegistrationMap {
@objc public class FirebaseFirestore: NSObject {
private let plugin: FirebaseFirestorePlugin
private var listenerRegistrationMap = ListenerRegistrationMap()

init(plugin: FirebaseFirestorePlugin) {
self.plugin = plugin
super.init()
Expand Down Expand Up @@ -217,6 +217,22 @@ private actor ListenerRegistrationMap {
Firestore.firestore().settings = settings
}

@objc public func getCountFromServer(_ options: GetCountFromServerOptions, completion: @escaping (Result?, Error?) -> Void) {
let reference = options.getReference()
let collectionReference = Firestore.firestore().collection(reference)
let countQuery = collectionReference.count

Task {
do {
let snapshot = try await countQuery.getAggregation(source: .server)
let result = GetCountFromServerResult(snapshot.count.intValue)
completion(result, nil)
} catch {
completion(nil, error)
}
}
}

@objc public func addDocumentSnapshotListener(_ options: AddDocumentSnapshotListenerOptions, completion: @escaping (Result?, Error?) -> Void) {
let reference = options.getReference()
let includeMetadataChanges = options.getIncludeMetadataChanges()
Expand Down
1 change: 1 addition & 0 deletions packages/firestore/ios/Plugin/FirebaseFirestorePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
CAP_PLUGIN_METHOD(writeBatch, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(getCollection, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(getCollectionGroup, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(getCountFromServer, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(enableNetwork, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(disableNetwork, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(useEmulator, CAPPluginReturnPromise);
Expand Down
22 changes: 21 additions & 1 deletion packages/firestore/ios/Plugin/FirebaseFirestorePlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,26 @@ public class FirebaseFirestorePlugin: CAPPlugin {
call.resolve()
}

@objc func getCountFromServer(_ call: CAPPluginCall) {
guard let reference = call.getString("reference") else {
call.reject(errorReferenceMissing)
return
}

let options = GetCountFromServerOptions(reference: reference)

implementation?.getCountFromServer(options, completion: { result, error in
if let error = error {
CAPLog.print("[", self.tag, "] ", error)
call.reject(error.localizedDescription)
return
}
if let result = result?.toJSObject() as? JSObject {
call.resolve(result)
}
})
}

@objc func addDocumentSnapshotListener(_ call: CAPPluginCall) {
call.keepAlive = true

Expand Down Expand Up @@ -359,7 +379,7 @@ public class FirebaseFirestorePlugin: CAPPlugin {
}
self.pluginCallMap.removeAll()
self.eventListeners?.removeAllObjects()

implementation?.removeAllListeners {
call.resolve()
}
Expand Down
Loading
Loading