Skip to content

Commit

Permalink
v.1.1.1: Enable filtering by documentIds in getDocumentsInCollection
Browse files Browse the repository at this point in the history
  • Loading branch information
olegkorol committed Dec 17, 2024
1 parent 6511646 commit eed57b7
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 9 deletions.
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ const firestore = new FirestoreAdminClient();
`firestore-admin` will take care of parsing the data to/from JSON when
fetching/updating documents.

If you work with Firestore Timestamp fields, read the
[Using timestamps](#using-timestamps) section.<br /> If you need to query
documents by their ID, read the [Using document IDs in a filter](#using-document-ids-in-a-filter)
section.

### Create a document

```typescript
Expand Down Expand Up @@ -204,7 +209,8 @@ await firestore.createDocument("my-collection", {
});
```

The above will be converted to a Firestore timestamp automatically.
The above `Date` object will be converted to a Firestore timestamp
automatically.

When filtering results by timestamp, make sure to use `Date` objects as well,
e.g.:
Expand All @@ -220,3 +226,33 @@ const documents = await firestore.getDocumentsInCollection("my-collection", {
},
});
```

In the query results, timestamp fields will be returned as an ISO Date string,
e.g. `2025-01-01T00:00:00.000Z`.

## Using document IDs in a filter

If you need to filter query results by document IDs in the
`getDocumentsInCollection` method, you can do so with the `documentId` field.

For example:

```typescript
// Will return all documents in the collection with the document IDs `docId1` and `docId2`.
const documents = await firestore.getDocumentsInCollection("my-collection", {
where: {
filters: [["documentId", FirestoreOperator.IN, ["docId1", "docId2"]]],
},
});

// You can still combine it with other filters, e.g.:

const documents = await firestore.getDocumentsInCollection("my-collection", {
where: {
filters: [
["documentId", FirestoreOperator.IN, ["docId1", "docId2"]],
["isActive", FirestoreOperator.EQUAL, true],
],
},
});
```
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@koiztech/firestore-admin",
"version": "1.1.0",
"version": "1.1.1",
"exports": "./mod.ts",
"tasks": {
"dev": "deno run --watch --env mod.ts",
Expand Down
41 changes: 34 additions & 7 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,40 @@ export class FirestoreAdminClient {
structuredQuery.where = {
compositeFilter: {
op: "AND",
filters: options.where.filters.map(([field, op, value]) => ({
fieldFilter: {
field: { fieldPath: field },
op,
value: this.encodeValue(value),
},
})),
filters: options.where.filters.map(([field, op, value]) => {
if (field === "documentId") {
if (!Array.isArray(value)) {
value = [value];
}
// For documentId filters, we need to construct the full document path
const fullPaths = value.map((id: string) => {
// If ID is already a full path, use it directly
if (id.includes("projects/")) return id;
// Otherwise construct the full path
return `projects/${this.GCP_PROJECT_NAME}/databases/(default)/documents/${path}/${id}`;
});
return {
fieldFilter: {
field: { fieldPath: "__name__" },
op: FirestoreOperator.IN, // Filtering by document ID(s) requires IN operator
value: {
arrayValue: {
values: fullPaths.map((p: any) => ({
referenceValue: p,
})),
},
},
},
};
}
return {
fieldFilter: {
field: { fieldPath: field },
op,
value: this.encodeValue(value),
},
};
}),
},
};
}
Expand Down

0 comments on commit eed57b7

Please sign in to comment.