Skip to content

Commit 874ede4

Browse files
author
FalkWolsky
committed
Improving Firestore Firebase Datasource
1 parent b21c044 commit 874ede4

File tree

2 files changed

+77
-24
lines changed

2 files changed

+77
-24
lines changed

server/node-service/src/plugins/firebase/queryConfig.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ const queryConfig = {
8686
...(
8787
[
8888
{
89-
label: "Query Firestore",
90-
actionName: "FS.QueryFireStore",
89+
label: "List Documents from Collection",
90+
actionName: "FS.ListFireStore",
9191
params: [
9292
firestoreCollectionParamConfig,
9393
{
@@ -103,19 +103,31 @@ const queryConfig = {
103103
placeholder: "asc",
104104
},
105105
{
106-
key: "limit",
107-
label: "Limit",
106+
key: "pageSize",
107+
label: "Page Size",
108108
type: "numberInput",
109109
defaultValue: 10,
110110
},
111111
{
112-
key: "startAt",
113-
label: "Start at",
114-
type: "textInput",
115-
tooltip: "Start the query at a specific document.",
112+
key: "pageNumber",
113+
label: "Page Number",
114+
type: "numberInput",
115+
defaultValue: 1,
116116
}
117117
],
118118
},
119+
{
120+
label: "Query Collection",
121+
actionName: "FS.QueryFireStore",
122+
params: [
123+
firestoreCollectionParamConfig,
124+
{
125+
key: "query",
126+
label: "Query JSON",
127+
type: "jsonInput",
128+
},
129+
],
130+
},
119131
{
120132
label: "Insert Document",
121133
actionName: "FS.InsertDocument",

server/node-service/src/plugins/firebase/run.ts

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
CollectionReference,
66
DocumentReference,
77
getFirestore,
8+
WhereFilterOp,
89
OrderByDirection,
910
} from "firebase-admin/firestore";
1011
import { DataSourceDataType } from "./dataSourceConfig";
@@ -83,37 +84,77 @@ export async function runFirebasePlugin(
8384
return collections.map((i) => i.id);
8485
}
8586

86-
if (actionName === "FS.QueryFireStore") {
87+
if (actionName === "FS.ListFireStore") {
8788
const data = await withFirestoreCollection(async (ref) => {
88-
let query;
89+
90+
// Initialize query as a Query type, not CollectionReference
91+
let query: FirebaseFirestore.Query<FirebaseFirestore.DocumentData> = ref;
92+
93+
// Sorting
8994
if (actionData.orderBy) {
90-
console.log("orderBy", actionData.orderBy);
91-
query = ref.orderBy(
95+
query = query.orderBy(
9296
actionData.orderBy,
9397
(actionData.orderDirection || "asc") as OrderByDirection
9498
);
9599
}
96-
// Apply startAt if specified (for pagination)
97-
if (actionData.startAt) {
98-
if (Array.isArray(actionData.startAt)) {
99-
// If startAt is an array, pass it as is
100-
query = (query || ref).startAt(...actionData.startAt);
101-
} else {
102-
// If startAt is a single value, use it directly
103-
query = (query || ref).startAt(actionData.startAt);
100+
101+
// Get the total count using aggregate query
102+
const totalCount = await query.count().get().then((snapshot) => snapshot.data().count);
103+
104+
// Pagination
105+
const pageSize = actionData.pageSize || 10;
106+
const pageNumber = actionData.pageNumber || 1;
107+
const offset = (pageNumber - 1) * pageSize;
108+
109+
// Move to the starting point based on offset
110+
if (offset > 0) {
111+
const offsetSnapshot = await query.limit(offset).get();
112+
const lastVisible = offsetSnapshot.docs[offsetSnapshot.docs.length - 1];
113+
114+
// If we have a valid last document, use it to start the next page
115+
if (lastVisible) {
116+
query = query.startAfter(lastVisible);
104117
}
105118
}
106-
if (actionData.limit > 0) {
107-
query = (query || ref).limit(actionData.limit);
119+
120+
// Apply page size limit
121+
query = query.limit(pageSize);
122+
123+
// Execute the final query to get the page data
124+
const snapshot = await query.get();
125+
const documents = snapshot.empty ? [] : snapshot.docs.map((i) => i.data());
126+
127+
// Return data object with totalCount and documents
128+
return { totalCount, documents };
129+
});
130+
return data;
131+
}
132+
133+
if (actionName === "FS.QueryFireStore") {
134+
const data = await withFirestoreCollection(async (ref) => {
135+
let query: FirebaseFirestore.Query<FirebaseFirestore.DocumentData> = ref;
136+
137+
// Parse Query JSON from actionData.query
138+
if (actionData.query) {
139+
for (const condition of actionData.query) {
140+
const { field, op, value } = condition;
141+
if (!field || !op || value === undefined) {
142+
throw badRequest("Invalid query condition: " + JSON.stringify(condition));
143+
}
144+
query = query.where(field, op as WhereFilterOp, value);
145+
}
108146
}
109-
const snapshot = await (query || ref).get();
147+
148+
// Execute the query and retrieve results
149+
const snapshot = await query.get();
110150
if (snapshot.empty) {
111151
return [];
112152
}
113-
return snapshot.docs.map((i) => i.data());
153+
return snapshot.docs.map((doc) => doc.data());
114154
});
115155
return data;
116156
}
157+
117158

118159
if (actionName === "FS.GetDocument") {
119160
return await withFirestoreDoc(async (ref) => (await ref.get()).data());

0 commit comments

Comments
 (0)