Skip to content
Draft
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
72 changes: 72 additions & 0 deletions firestore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>

# [Cloud Firestore: Node.js Samples](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/tree/main/firestore)

This collection of samples demonstrates how to perform various operations with Google Cloud Firestore using Node.js, including basic reads and writes, data pipelines, and solution counters.

## Table of Contents

* [Before you begin](#before-you-begin)
* [Samples](#samples)
* [Limit-to-last-query](#limit-to-last-query)
* [Pipelines-quickstart](#pipelines-quickstart)
* [Quickstart](#quickstart)
* [Solution-counters](#solution-counters)
* [Running the tests](#running-the-tests)

## Before you begin

Before running the samples, make sure you've followed the steps outlined in
[Using the client library](https://github.com/GoogleCloudPlatform/nodejs-docs-samples#using-the-client-library).

`npm install`

## Samples

### Limit-to-last-query

View the [source code](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/main/firestore/limit-to-last-query.js).

__Usage:__

`node limit-to-last-query.js`

-----

### Pipelines-quickstart

View the [source code](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/main/firestore/pipelines-quickstart.js).

__Usage:__

`node pipelines-quickstart.js`

-----

### Quickstart

View the [source code](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/main/firestore/quickstart.js).

__Usage:__

`node quickstart.js`

-----

### Solution-counters

View the [source code](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/main/firestore/solution-counters.js).

__Usage:__

`node solution-counters.js`

-----

## Running the tests

To run the automated tests for these samples, execute:

`npm test`

[product-docs]: https://cloud.google.com/firestore
39 changes: 39 additions & 0 deletions firestore/limit-to-last-query.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// [START firestore_limit_to_last_query]
const {Firestore} = require('@google-cloud/firestore');

// Create a new client
const firestore = new Firestore();

async function limitToLastQuery() {
try {
const collectionReference = firestore.collection('cities');
const cityDocuments = await collectionReference
.orderBy('name')
.limitToLast(2)
.get();
const cityDocumentData = cityDocuments.docs.map(d => d.data());
cityDocumentData.forEach(doc => {
console.log(doc.name);
});
} catch (error) {
console.error('Error executing limitToLastQuery:', error);
}
}
limitToLastQuery();
// [END firestore_limit_to_last_query]
20 changes: 20 additions & 0 deletions firestore/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "@google-cloud/firestore-samples",
"private": true,
"license": "Apache-2.0",
"author": "Google Inc.",
"repository": "googleapis/nodejs-firestore",
"engines": {
"node": ">=18"
},
"scripts": {
"test": "mocha --timeout 600000"
},
"dependencies": {
"@google-cloud/firestore": "^8.3.0"
},
"devDependencies": {
"chai": "^4.2.0",
"mocha": "^7.0.0"
}
}
63 changes: 63 additions & 0 deletions firestore/pipelines-quickstart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2026 Google LLC.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// [START firestore_pipelines_quickstart]
const {Firestore} = require('@google-cloud/firestore');
const {field} = require('@google-cloud/firestore/pipelines');

// Create a new client
const firestore = new Firestore();

async function quickstartPipelines() {
try {
// Obtain a collection reference.
const collection = firestore.collection('posts');

// Create a few new posts
for (let i = 0; i < 5; i++) {
await collection.add({
title: `Post ${i}`,
rating: Math.random() * 10, // random rating on a 10 point scale
});
}
console.log('Entered new data into the collection');

// Create a Pipeline that queries the 'posts' collection.
// Select the fields 'rating' and 'title', and convert the title to uppercase.
// Filter the results to only include posts with rating > 5.
const myPipeline = firestore
.pipeline()
.collection('posts')
.select('rating', field('title').toUpper().as('uppercaseTitle'))
.where(field('rating').greaterThan(5));

// Execute the Pipeline against the Firestore server.
const pipelineSnapshot = await myPipeline.execute();

// Iterate over each result in the PipelineSnapshot, printing the
// post to the console.
pipelineSnapshot.results.forEach(pipelineResult => {
console.log(pipelineResult.data());
});
} catch (error) {
console.error(
'Error executing pipelines quickstart:',
error.message || error
);
}
}
quickstartPipelines();
// [END firestore_pipelines_quickstart]
54 changes: 54 additions & 0 deletions firestore/quickstart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright 2017 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

// [START firestore_quickstart]
const {Firestore} = require('@google-cloud/firestore');

// Create a new client
const firestore = new Firestore();

async function quickstart() {
try {
// Obtain a document reference.
const document = firestore.doc('posts/intro-to-firestore');

// Enter new data into the document.
await document.set({
title: 'Welcome to Firestore',
body: 'Hello World',
});
console.log('Entered new data into the document');

// Update an existing document.
await document.update({
body: 'My first Firestore app',
});
console.log('Updated an existing document');

// Read the document.
const doc = await document.get();
console.log(`Read the document with ID: ${doc.id}`);
console.log('Document data:', doc.data());

// Delete the document.
await document.delete();
console.log('Deleted the document');
} catch (error) {
console.error('Error executing quickstart:', error.message || error);
}
}
quickstart();
// [END firestore_quickstart]
69 changes: 69 additions & 0 deletions firestore/solution-counters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';
const {Firestore, FieldValue} = require('@google-cloud/firestore');

async function main() {
// [START firestore_solution_sharded_counter_increment]
function incrementCounter(docRef, numShards) {
const shardId = Math.floor(Math.random() * numShards);
const shardRef = docRef.collection('shards').doc(shardId.toString());
return shardRef.set({count: FieldValue.increment(1)}, {merge: true});
}
// [END firestore_solution_sharded_counter_increment]

// [START firestore_solution_sharded_counter_get]
async function getCount(docRef) {
const querySnapshot = await docRef.collection('shards').get();
return querySnapshot.docs.reduce(
(total, doc) => total + (doc.get('count') || 0),
0
);
}
// [END firestore_solution_sharded_counter_get]

// [START firestore_data_delete_doc]
async function deleteDocs(docRef) {
const shardsCollectionRef = docRef.collection('shards');
const shardDocs = await shardsCollectionRef.get();
const promises = shardDocs.docs.map(doc => doc.ref.delete());
return Promise.all(promises);
}
// [END firestore_data_delete_doc]

try {
// Create a new client
const firestore = new Firestore();
const docRef = firestore.doc(
'distributed_counter_samples/distributed_counter'
);
// Clean up documents from potential prior test runs
await deleteDocs(docRef);
const numberOfShards = 10;
// Increase the document count
await incrementCounter(docRef, numberOfShards);
console.log('counter increased');
// Get document count
const count = await getCount(docRef);
console.log(`new count is : ${count}`);
// Delete the document
await deleteDocs(docRef);
console.log('Deleted the document');
} catch (error) {
console.error('Error in sharded counter:', error.message || error);
}
}

main();
48 changes: 48 additions & 0 deletions firestore/test/limit-to-last-query.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const {execSync} = require('child_process');
const {assert} = require('chai');
const {after, before, describe, it} = require('mocha');
const exec = cmd => execSync(cmd, {encoding: 'utf8'});
const {Firestore, FieldPath} = require('@google-cloud/firestore');

describe('limit to last query', () => {
const firestore = new Firestore();
const cities = ['San Francisco', 'Los Angeles', 'Tokyo', 'Beijing'];

before(async () => {
await Promise.all(
cities.map(city => firestore.doc(`cities/${city}`).set({name: city}))
);
});

after(async () => {
const cityCollectionRef = firestore.collection('cities');
const cityDocs = (
await cityCollectionRef.select(FieldPath.documentId()).get()
).docs;
await Promise.all(
cityDocs.map(doc => cityCollectionRef.doc(doc.id).delete())
);
});

it('should run limitToLast query', () => {
const output = exec('node limit-to-last-query.js');
assert.include(output, 'San Francisco');
assert.include(output, 'Tokyo');
});
});
Loading
Loading