From 3301c5b6e2bdbf2663d951e8414fc16fc2fa50bb Mon Sep 17 00:00:00 2001 From: Jisha Abubaker Date: Mon, 2 Oct 2017 22:34:56 -0700 Subject: [PATCH] Adding firestore samples --- firestore/README.md | 47 ++ firestore/pom.xml | 58 +++ .../com/example/firestore/Quickstart.java | 196 +++++++++ .../snippets/ManageDataSnippets.java | 402 ++++++++++++++++++ .../firestore/snippets/QueryDataSnippets.java | 308 ++++++++++++++ .../firestore/snippets/References.java | 82 ++++ .../snippets/RetrieveDataSnippets.java | 138 ++++++ .../firestore/snippets/model/City.java | 144 +++++++ .../com/example/firestore/QuickstartIT.java | 120 ++++++ .../snippets/ManageDataSnippetsIT.java | 213 ++++++++++ .../snippets/QueryDataSnippetsIT.java | 225 ++++++++++ .../snippets/RetrieveDataSnippetsIT.java | 113 +++++ pom.xml | 2 + 13 files changed, 2048 insertions(+) create mode 100644 firestore/README.md create mode 100644 firestore/pom.xml create mode 100644 firestore/src/main/java/com/example/firestore/Quickstart.java create mode 100644 firestore/src/main/java/com/example/firestore/snippets/ManageDataSnippets.java create mode 100644 firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java create mode 100644 firestore/src/main/java/com/example/firestore/snippets/References.java create mode 100644 firestore/src/main/java/com/example/firestore/snippets/RetrieveDataSnippets.java create mode 100644 firestore/src/main/java/com/example/firestore/snippets/model/City.java create mode 100644 firestore/src/test/java/com/example/firestore/QuickstartIT.java create mode 100644 firestore/src/test/java/com/example/firestore/snippets/ManageDataSnippetsIT.java create mode 100644 firestore/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java create mode 100644 firestore/src/test/java/com/example/firestore/snippets/RetrieveDataSnippetsIT.java diff --git a/firestore/README.md b/firestore/README.md new file mode 100644 index 00000000000..db5d5612582 --- /dev/null +++ b/firestore/README.md @@ -0,0 +1,47 @@ +# Getting started with Google Cloud Firestore +[Google Cloud Firestore](https://cloud.google.com/firestore/docs/) is a hosted NoSQL database built +for automatic scaling, high performance, and ease of application development. + +These code samples demonstrate how to access the Google Cloud Firestore API +using the Beta version of the Firestore Client Libraries. + +Note: You cannot use both Cloud Firestore and Cloud Datastore in the +same project, which might affect apps using App Engine. Try using Cloud Firestore with a different +project. + +## Setup +- Install [Maven](http://maven.apache.org/). +- Open the [Firebase Console](https://console.firebase.com) and click **Add project**. +- Select the option to **Enable Cloud Firestore Beta** for this project. +- Click **Create Project**. + When you create a Cloud Firestore project, it also enables the API in the + [Cloud API Manager](https://console.cloud.google.com/projectselector/apis/api/firestore.googleapis.com/overview). +- [Create a service account](https://cloud.google.com/docs/authentication/) + and set the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to point to the + credentials JSON file. + +## Build +Build your project: + + mvn clean package + + +## Quickstart +[Quickstart.java](src/main/java/com/example/java/com/example/firestore/Quicstart.java) + demonstrates adding and querying documents in a collection in Firestore. +You can run the quickstart with: + + mvn exec:java -Dexec.mainClass=com.example.firestore.Quickstart -Dexec.args="your-firestore-project-id" + +Note: the default project-id will be used if no argument is provided. + +## Snippets +These [code samples](src/main/java/com/example/firestore/snippets) support +the Firestore [documentation](https://cloud.google.com/firestore/docs). + +## Tests +Run all tests: +``` + mvn clean verify +``` + diff --git a/firestore/pom.xml b/firestore/pom.xml new file mode 100644 index 00000000000..1c84ee450aa --- /dev/null +++ b/firestore/pom.xml @@ -0,0 +1,58 @@ + + + + 4.0.0 + com.example.firestore + firestore-samples + 1.0.0 + jar + Google Cloud Firestore Samples + + Quick start and code snippets supporting Firestore documentation + + + + doc-samples + com.google.cloud + 1.0.0 + .. + + + + 1.7 + 1.7 + + + + + + + com.google.cloud + google-cloud-firestore + 0.25.0-beta + + + + + + junit + junit + 4.12 + test + + + diff --git a/firestore/src/main/java/com/example/firestore/Quickstart.java b/firestore/src/main/java/com/example/firestore/Quickstart.java new file mode 100644 index 00000000000..9149dafd61d --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/Quickstart.java @@ -0,0 +1,196 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore; + +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.DocumentSnapshot; +// [START fs_include_dependencies] +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +// [END fs_include_dependencies] +import com.google.cloud.firestore.QuerySnapshot; +import com.google.cloud.firestore.WriteResult; +import com.google.common.collect.ImmutableMap; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A simple Quick start application demonstrating how to connect to Firestore + * and add and query documents. + */ +public class Quickstart { + + private Firestore db; + + /** + * Initialize Firestore using default project ID. + */ + public Quickstart() { + // [START fs_initialize] + Firestore db = FirestoreOptions.getDefaultInstance().getService(); + // [END fs_initialize] + this.db = db; + } + + public Quickstart(String projectId) { + // [START fs_initialize_project_id] + FirestoreOptions firestoreOptions = + FirestoreOptions.getDefaultInstance().toBuilder() + .setProjectId(projectId) + .build(); + Firestore db = firestoreOptions.getService(); + // [END fs_initialize_project_id] + this.db = db; + } + + Firestore getDb() { + return db; + } + + /** + * Add named test documents with fields first, last, middle (optional), born. + * + * @param docName document name + */ + void addDocument(String docName) throws Exception { + switch (docName) { + case "alovelace": { + // [START fs_add_data_1] + DocumentReference docRef = db.collection("users").document("alovelace"); + // Add document data with id "alovelace" using a hashmap + Map data = new HashMap<>(); + data.put("first", "Ada"); + data.put("last", "Lovelace"); + data.put("born", 1815); + //asynchronously write data + ApiFuture result = docRef.set(data); + // ... + // result.get() blocks on response + System.out.println("Update time : " + result.get().getUpdateTime()); + // [END fs_add_data_1] + break; + } + case "aturing": { + // [START fs_add_data_2] + DocumentReference docRef = db.collection("users").document("aturing"); + // Add document data with an additional field ("middle") + Map data = new HashMap<>(); + data.put("first", "Alan"); + data.put("middle", "Mathison"); + data.put("last", "Turing"); + data.put("born", 1912); + + ApiFuture result = docRef.set(data); + System.out.println("Update time : " + result.get().getUpdateTime()); + // [END fs_add_data_2] + break; + } + case "cbabbage": { + DocumentReference docRef = db.collection("users").document("cbabbage"); + Map data = + new ImmutableMap.Builder() + .put("first", "Charles") + .put("last", "Babbage") + .put("born", 1791) + .build(); + ApiFuture result = docRef.set(data); + System.out.println("Update time : " + result.get().getUpdateTime()); + break; + } + default: + } + } + + void runAQuery() throws Exception { + // [START fs_add_query] + // asynchronously query for all users born before 1900 + ApiFuture query = + db.collection("users").whereLessThan("born", 1900).get(); + // ... + // query.get() blocks on response + QuerySnapshot querySnapshot = query.get(); + List documents = querySnapshot.getDocuments(); + for (DocumentSnapshot document : documents) { + System.out.println("User: " + document.getId()); + System.out.println("First: " + document.getString("first")); + if (document.contains("middle")) { + System.out.println("Middle: " + document.getString("middle")); + } + System.out.println("Last: " + document.getString("last")); + System.out.println("Born: " + document.getLong("born")); + } + // [END fs_add_query] + } + + void retrieveAllDocuments() throws Exception { + // [START fs_get_all] + // asynchronously retrieve all users + ApiFuture query = db.collection("users").get(); + // ... + // query.get() blocks on response + QuerySnapshot querySnapshot = query.get(); + List documents = querySnapshot.getDocuments(); + for (DocumentSnapshot document : documents) { + System.out.println("User: " + document.getId()); + System.out.println("First: " + document.getString("first")); + if (document.contains("middle")) { + System.out.println("Middle: " + document.getString("middle")); + } + System.out.println("Last: " + document.getString("last")); + System.out.println("Born: " + document.getLong("born")); + } + // [END fs_get_all] + } + + void run() throws Exception { + String[] docNames = {"alovelace", "aturing", "cbabbage"}; + + // Adding document 1 + System.out.println("########## Adding document 1 ##########"); + addDocument(docNames[0]); + + // Adding document 2 + System.out.println("########## Adding document 2 ##########"); + addDocument(docNames[1]); + + // Adding document 3 + System.out.println("########## Adding document 3 ##########"); + addDocument(docNames[2]); + + // retrieve all users born before 1900 + System.out.println("########## users born before 1900 ##########"); + runAQuery(); + + // retrieve all users + System.out.println("########## All users ##########"); + retrieveAllDocuments(); + System.out.println("###################################"); + } + + /** + * A quick start application to get started with Firestore. + * + * @param args firestore-project-id (optional) + */ + public static void main(String[] args) throws Exception { + // default project is will be used if project-id argument is not available + String projectId = (args.length == 0) ? null : args[0]; + Quickstart quickStart = (projectId != null) ? new Quickstart(projectId) : new Quickstart(); + quickStart.run(); + } +} diff --git a/firestore/src/main/java/com/example/firestore/snippets/ManageDataSnippets.java b/firestore/src/main/java/com/example/firestore/snippets/ManageDataSnippets.java new file mode 100644 index 00000000000..30427e705c9 --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/snippets/ManageDataSnippets.java @@ -0,0 +1,402 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import com.example.firestore.snippets.model.City; +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.FieldValue; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.QuerySnapshot; +import com.google.cloud.firestore.SetOptions; +import com.google.cloud.firestore.Transaction; +import com.google.cloud.firestore.WriteBatch; +import com.google.cloud.firestore.WriteResult; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** Snippets to demonstrate Firestore add, update and delete operations. */ +class ManageDataSnippets { + + private final Firestore db; + + ManageDataSnippets(Firestore db) { + this.db = db; + } + + /** + * Add a document to a collection using a map. + * + * @return document data + */ + Map addSimpleDocumentAsMap() throws Exception { + // [START fs_add_doc_as_map] + // Create a Map to store the data we want to set + Map docData = new HashMap<>(); + docData.put("name", "Los Angeles"); + docData.put("state", "CA"); + docData.put("country", "USA"); + // Add a new document (asynchronously) in collection "cities" with id "LA" + ApiFuture future = db.collection("cities").document("LA").set(docData); + // ... + // future.get() blocks on response + System.out.println("Update time : " + future.get().getUpdateTime()); + // [END fs_add_doc_as_map] + return docData; + } + + /** + * Add a document to a collection using a map with different supported data types. + * + * @return document data + */ + Map addDocumentWithDifferentDataTypes() throws Exception { + // [START fs_add_doc_data_types] + Map docData = new HashMap<>(); + docData.put("stringExample", "Hello, World"); + docData.put("booleanExample", false); + docData.put("numberExample", 3.14159265); + docData.put("nullExample", null); + + ArrayList arrayExample = new ArrayList<>(); + Collections.addAll(arrayExample, 5L, true, "hello"); + docData.put("arrayExample", arrayExample); + + Map objectExample = new HashMap<>(); + objectExample.put("a", 5L); + objectExample.put("b", true); + + docData.put("objectExample", objectExample); + + ApiFuture future = db.collection("data").document("one").set(docData); + System.out.println("Update time : " + future.get().getUpdateTime()); + // [END fs_add_doc_data_types] + + return docData; + } + + /** + * Add a document to a collection as a custom object. + * + * @return entity added + */ + City addSimpleDocumentAsEntity() throws Exception { + // [START fs_add_simple_doc_as_entity] + City city = new City("Los Angeles", "CA", "USA", false, 3900000L); + ApiFuture future = db.collection("cities").document("LA").set(city); + // block on response if required + System.out.println("Update time : " + future.get().getUpdateTime()); + // [END fs_add_simple_doc_as_entity] + + return city; + } + + /** + * set() providing a document ID. + */ + void setRequiresId(Map data) { + // [START fs_set_requires_id] + db.collection("cities").document("new-city-id").set(data); + // [END fs_set_requires_id] + } + + /** + * Add a document without explicitly providing the document id. The document id gets automatically + * generated. + * + * @return auto generated id + */ + String addDocumentDataWithAutoGeneratedId() throws Exception { + // [START fs_add_doc_data_with_auto_id] + // Add document data with auto-generated id. + Map data = new HashMap<>(); + data.put("name", "Tokyo"); + data.put("country", "Japan"); + ApiFuture addedDocRef = db.collection("cities").add(data); + System.out.println("Added document with ID: " + addedDocRef.get().getId()); + // [END fs_add_doc_data_with_auto_id] + + return addedDocRef.get().getId(); + } + + /** + * Add data to a document after generating the document id. + * + * @return auto generated id + */ + String addDocumentDataAfterAutoGeneratingId() throws Exception { + City data = new City(); + + // [START fs_add_doc_data_after_auto_id] + // Add document data after generating an id. + DocumentReference addedDocRef = db.collection("cities").document(); + System.out.println("Added document with ID: " + addedDocRef.getId()); + + // later... + ApiFuture writeResult = addedDocRef.set(data); + // [END fs_add_doc_data_after_auto_id] + + // writeResult.get() blocks on operation + System.out.println("Update time : " + writeResult.get().getUpdateTime()); + return addedDocRef.getId(); + } + + /** Partially update a document using the .update(field1, value1..) method. */ + void updateSimpleDocument() throws Exception { + db.collection("cities").document("DC").set(new City("Washington D.C.")).get(); + // [START fs_update_doc] + // Update an existing document + DocumentReference docRef = db.collection("cities").document("DC"); + + // (async) Update one field + ApiFuture future = docRef.update("capital", true); + + // ... + WriteResult result = future.get(); + System.out.println("Write result: " + result); + // [END fs_update_doc] + } + + /** Partially update fields of a document using a map (field => value). */ + void updateUsingMap() throws Exception { + db.collection("cities").document("DC").set(new City("Washington D.C.")).get(); + // [START fs_update_doc_map] + // update multiple fields using a map + DocumentReference docRef = db.collection("cities").document("DC"); + + Map updates = new HashMap<>(); + updates.put("name", "Washington D.C."); + updates.put("country", "USA"); + updates.put("capital", true); + + //asynchronously update doc + ApiFuture writeResult = docRef.update(updates); + // ... + System.out.println("Update time : " + writeResult.get().getUpdateTime()); + // [END fs_update_doc_map] + } + + /** Partially update fields of a document using a map (field => value). */ + void updateAndCreateIfMissing() throws Exception { + // [START fs_update_create_if_missing] + //asynchronously update doc, create the document if missing + Map update = new HashMap<>(); + update.put("capital", true); + + ApiFuture writeResult = + db + .collection("cities") + .document("BJ") + .set(update, SetOptions.merge()); + // ... + System.out.println("Update time : " + writeResult.get().getUpdateTime()); + // [END fs_update_create_if_missing] + } + + /** Partial update nested fields of a document. */ + void updateNestedFields() throws Exception { + // [START fs_update_nested_fields] + // Create an initial document to update + DocumentReference frankDocRef = db.collection("users").document("frank"); + Map initialData = new HashMap<>(); + initialData.put("name", "Frank"); + initialData.put("age", 12); + + Map favorites = new HashMap<>(); + favorites.put("food", "Pizza"); + favorites.put("color", "Blue"); + favorites.put("subject", "Recess"); + initialData.put("favorites", favorites); + + ApiFuture initialResult = frankDocRef.set(initialData); + // Confirm that data has been successfully saved by blocking on the operation + initialResult.get(); + + // Update age and favorite color + Map updates = new HashMap<>(); + updates.put("age", 13); + updates.put("favorites.color", "Red"); + + // Async update document + ApiFuture writeResult = frankDocRef.update(updates); + // ... + System.out.println("Update time : " + writeResult.get().getUpdateTime()); + // [END fs_update_nested_fields] + } + + /** Update document with server timestamp. */ + void updateServerTimestamp() throws Exception { + db.collection("objects").document("some-id").set(new HashMap()).get(); + + // [START fs_update_server_timestamp] + DocumentReference docRef = db.collection("objects").document("some-id"); + // Update the timestamp field with the value from the server + ApiFuture writeResult = docRef.update("timestamp", FieldValue.serverTimestamp()); + System.out.println("Update time : " + writeResult.get()); + // [END fs_update_server_timestamp] + } + + /** Delete specific fields when updating a document. */ + void deleteFields() throws Exception { + City city = new City("Beijing"); + city.setCapital(true); + db.collection("cities").document("BJ").set(city).get(); + + // [START fs_delete_fields] + DocumentReference docRef = db.collection("cities").document("BJ"); + Map updates = new HashMap<>(); + updates.put("capital", FieldValue.delete()); + // Update and delete the "capital" field in the document + ApiFuture writeResult = docRef.update(updates); + System.out.println("Update time : " + writeResult.get()); + // [END fs_delete_fields] + } + + /** Delete a document in a collection. */ + void deleteDocument() throws Exception { + db.collection("cities").document("DC").set(new City("Washington, D.C.")).get(); + // [START fs_delete_doc] + // asynchronously delete a document + ApiFuture writeResult = db.collection("cities").document("DC").delete(); + // ... + System.out.println("Update time : " + writeResult.get().getUpdateTime()); + // [END fs_delete_doc] + } + + // [START fs_delete_collection] + /** Delete a collection in batches to avoid out-of-memory errors. + * Batch size may be tuned based on document size (atmost 1MB) and application requirements. + */ + void deleteCollection(CollectionReference collection, int batchSize) { + try { + // retrieve a small batch of documents to avoid out-of-memory errors + ApiFuture future = collection.limit(batchSize).get(); + int deleted = 0; + // future.get() blocks on document retrieval + List documents = future.get().getDocuments(); + for (DocumentSnapshot document : documents) { + document.getReference().delete(); + ++deleted; + } + if (deleted >= batchSize) { + // retrieve and delete another batch + deleteCollection(collection, batchSize); + } + } catch (Exception e) { + System.err.println("Error deleting collection : " + e.getMessage()); + } + } + // [END fs_delete_collection] + + /** Run a simple transaction to perform a field value increment. + * + * @return transaction future + */ + ApiFuture runSimpleTransaction() throws Exception { + // [START fs_run_simple_transaction] + // Initialize doc + final DocumentReference docRef = db.collection("cities").document("SF"); + City city = new City("SF"); + city.setCountry("USA"); + city.setPopulation(860000L); + docRef.set(city).get(); + + // run an asynchronous transaction + ApiFuture transaction = + db.runTransaction( + new Transaction.Function() { + @Override + public Void updateCallback(Transaction transaction) throws Exception { + // retrieve document and increment population field + DocumentSnapshot snapshot = transaction.get(docRef).get(); + long oldPopulation = snapshot.getLong("population"); + transaction.update(docRef, "population", oldPopulation + 1); + return null; + } + }); + // block on transaction operation using transaction.get() + // [END fs_run_simple_transaction] + return transaction; + } + + /** + * Return information from a conditional transaction. + * + * + * @param population : set initial population. + */ + String returnInfoFromTransaction(long population) throws Exception { + Map map = new HashMap<>(); + map.put("population", population); + db.collection("cities").document("SF").set(map); + // [START fs_return_info_transaction] + final DocumentReference docRef = db.collection("cities").document("SF"); + ApiFuture transaction = + db.runTransaction( + new Transaction.Function() { + @Override + public String updateCallback(Transaction transaction) throws Exception { + DocumentSnapshot snapshot = transaction.get(docRef).get(); + Long newPopulation = snapshot.getLong("population") + 1; + // conditionally update based on current population + if (newPopulation <= 1000000L) { + transaction.update(docRef, "population", newPopulation); + return "Population increased to " + newPopulation; + } else { + throw new Exception("Sorry! Population is too big."); + } + } + }); + // Print information retrieved from transaction + System.out.println(transaction.get()); + // [END fs_return_info_transaction] + return transaction.get(); + } + + /** Write documents in a batch. */ + void writeBatch() throws Exception { + db.collection("cities").document("SF").set(new City()).get(); + db.collection("cities").document("LA").set(new City()).get(); + + // [START fs_write_batch] + // Get a new write batch + WriteBatch batch = db.batch(); + // Set the value of 'NYC' + DocumentReference nycRef = db.collection("cities").document("NYC"); + batch.set(nycRef, new City()); + + // Update the population of 'SF' + DocumentReference sfRef = db.collection("cities").document("SF"); + batch.update(sfRef, "population", 1000000L); + + // Delete the city 'LA' + DocumentReference laRef = db.collection("cities").document("LA"); + batch.delete(laRef); + + // asynchronously commit the batch + ApiFuture> future = batch.commit(); + // ... + // future.get() blocks on batch commit operation + for (WriteResult result :future.get()) { + System.out.println("Update time : " + result.getUpdateTime()); + } + // [END fs_write_batch] + } +} diff --git a/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java b/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java new file mode 100644 index 00000000000..b3389216232 --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/snippets/QueryDataSnippets.java @@ -0,0 +1,308 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import com.example.firestore.snippets.model.City; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.Query; +import com.google.cloud.firestore.Query.Direction; +import com.google.cloud.firestore.QuerySnapshot; +import com.google.cloud.firestore.WriteResult; + +import java.util.ArrayList; +import java.util.List; + +/** Snippets to support firestore querying data documentation. */ +class QueryDataSnippets { + + private final Firestore db; + + QueryDataSnippets(Firestore db) { + this.db = db; + } + + /** + * Creates cities collection and add sample documents to test queries. + * + * @return collection reference + */ + void prepareExamples() throws Exception { + // [START fs_query_create_examples] + CollectionReference cities = db.collection("cities"); + List> futures = new ArrayList<>(); + futures.add(cities.document("SF").set(new City("San Francisco", "CA", "USA", false, 860000L))); + futures.add(cities.document("LA").set(new City("Los Angeles", "CA", "USA", false, 3900000L))); + futures.add(cities.document("DC").set(new City("Washington D.C.", null, "USA", true, 680000L))); + futures.add(cities.document("TOK").set(new City("Tokyo", null, "Japan", true, 9000000L))); + futures.add(cities.document("BJ").set(new City("Beijing", null, "China", true, 21500000L))); + // (optional) block on documents successfully added + ApiFutures.allAsList(futures).get(); + // [END fs_query_create_examples] + } + + /** + * Creates a sample query. + * + * @return query + */ + Query createAQuery() throws Exception { + // [START fs_create_query] + // Create a reference to the cities collection + CollectionReference cities = db.collection("cities"); + // Create a query against the collection. + Query query = cities.whereEqualTo("capital", true); + // retrieve query results asynchronously using query.get() + ApiFuture querySnapshot = query.get(); + + for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { + System.out.println(document.getId()); + } + // [END fs_create_query] + return query; + } + + /** + * Creates a sample query. + * + * @return query + */ + Query createAQueryAlternate() throws Exception { + // [START fs_create_query_country] + // Create a reference to the cities collection + CollectionReference cities = db.collection("cities"); + // Create a query against the collection. + Query query = cities.whereEqualTo("state", "CA"); + // retrieve query results asynchronously using query.get() + ApiFuture querySnapshot = query.get(); + + for (DocumentSnapshot document : querySnapshot.get().getDocuments()) { + System.out.println(document.getId()); + } + // [END fs_create_query_country] + return query; + } + + /** + * Creates queries with simple where clauses. + * + * @return queries + */ + List createSimpleQueries() { + List querys = new ArrayList<>(); + CollectionReference cities = db.collection("cities"); + + // [START fs_simple_queries] + Query countryQuery = cities.whereEqualTo("state", "CA"); + Query populationQuery = cities.whereLessThan("population", 1000000L); + Query cityQuery = cities.whereGreaterThanOrEqualTo("name", "San Francisco"); + // [END fs_simple_queries] + + querys.add(countryQuery); + querys.add(populationQuery); + querys.add(cityQuery); + return querys; + } + + /** + * Creates chained where clauses. + * + *

Note : equality and inequality clauses over multiple fields cannot be chained. + * + * @return query + */ + Query createChainedQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_chained_query] + Query chainedQuery1 = cities.whereEqualTo("state", "CO") + .whereEqualTo("name", "Denver"); + // [END fs_chained_query] + return chainedQuery1; + } + + /** + * An instance of a currently unsupported chained query: equality with inequality. + * NOTE : Requires support for creation of composite indices. + * + * @return query + */ + Query createCompositeIndexChainedQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_composite_index_chained_query] + Query chainedQuery2 = cities.whereEqualTo("state", "CA") + .whereLessThan("population", 1000000L); + // [END fs_composite_index_chained_query] + return chainedQuery2; + } + + /** + * An instance of a valid range/inequality query : range operators are limited to a single field. + * + * @return query + */ + Query createRangeQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_range_query] + Query validQuery1 = cities.whereGreaterThanOrEqualTo("state", "CA") + .whereLessThanOrEqualTo("state", "IN"); + Query validQuery2 = cities.whereEqualTo("state", "CA") + .whereGreaterThan("population", 1000000); + // [END fs_range_query] + return validQuery1; + } + + /** + * An instance of an invalid range query : range operators are limited to a single field. + * + * @return query + */ + Query createInvalidRangeQuery() { + CollectionReference cities = db.collection("cities"); + // Violates constraint : range operators are limited to a single field + // [START fs_invalid_range_query] + Query invalidRangeQuery = cities.whereGreaterThanOrEqualTo("state", "CA") + .whereGreaterThan("population", 100000); + // [END fs_invalid_range_query] + return invalidRangeQuery; + } + + /** + * Creates a query that combines order by with limit. + * + * @return query + */ + Query createOrderByNameWithLimitQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_order_by_name_limit_query] + Query query = cities.orderBy("name").limit(3); + // [END fs_order_by_name_limit_query] + return query; + } + + /** + * Creates a query that orders by country and population(descending). + * + * @return query + */ + Query createOrderByCountryAndPopulation() { + CollectionReference cities = db.collection("cities"); + // [START fs_order_by_country_population] + Query query = cities.orderBy("state").orderBy("population", Direction.DESCENDING); + // [END fs_order_by_country_population] + return query; + } + + /** + * Creates a query that combines order by in descending order with the limit operator. + * + * @return query + */ + Query createOrderByNameDescWithLimitQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_order_by_name_desc_limit_query] + Query query = cities.orderBy("name", Direction.DESCENDING).limit(3); + // [END fs_order_by_name_desc_limit_query] + return query; + } + + /** + * Creates a query that combines where clause with order by and limit operator. + * + * @return query + */ + Query createWhereWithOrderByAndLimitQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_where_order_by_limit_query] + Query query = cities.whereGreaterThan("population", 2500000L).orderBy("population").limit(2); + // [END fs_where_order_by_limit_query] + return query; + } + + /** + * Creates a query using a range where clause with order by. Order by must be based on the same + * field as the range clause. + * + * @return query + */ + Query createRangeWithOrderByQuery() { + CollectionReference cities = db.collection("cities"); + // [START fs_range_order_by_query] + Query query = cities.whereGreaterThan("population", 2500000L).orderBy("population"); + // [END fs_range_order_by_query] + return query; + } + + /** + * Creates an instance of an invalid range combined with order. Violates the constraint that range + * and order by are required to be on the same field. + * + * @return query + */ + Query createInvalidRangeWithOrderByQuery() { + CollectionReference cities = db.collection("cities"); + // Violates the constraint that range and order by are required to be on the same field + // [START fs_invalid_range_order_by_query] + Query query = cities.whereGreaterThan("population", 2500000L).orderBy("country"); + // [END fs_invalid_range_order_by_query] + return query; + } + + /** + * Create a query defining the start point of a query. + * + * @return query + */ + Query createStartAtFieldQueryCursor() { + CollectionReference cities = db.collection("cities"); + // [START fs_start_at_field_query_cursor] + Query query = cities.orderBy("population").startAt(4921000L); + // [END fs_start_at_field_query_cursor] + return query; + } + + /** + * Create a query defining the start point of a query. + * + * @return query + */ + Query createEndAtFieldQueryCursor() { + CollectionReference cities = db.collection("cities"); + // [START fs_end_at_field_query_cursor] + Query query = cities.orderBy("population").endAt(4921000L); + // [END fs_end_at_field_query_cursor] + return query; + } + + /* Create queries with multiple cursor conditions. */ + void createMultipleCursorConditionsQuery() { + // [START fs_multiple_cursor_conditions] + // Will return all Springfields + Query query1 = db.collection("cities") + .orderBy("name") + .orderBy("state") + .startAt("Springfield"); + + // Will return "Springfield, Missouri" and "Springfield, Wisconsin" + Query query2 = db.collection("cities") + .orderBy("name") + .orderBy("state") + .startAt("Springfield", "Missouri"); + // [END fs_multiple_cursor_conditions] + } +} diff --git a/firestore/src/main/java/com/example/firestore/snippets/References.java b/firestore/src/main/java/com/example/firestore/snippets/References.java new file mode 100644 index 00000000000..52c4df728a0 --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/snippets/References.java @@ -0,0 +1,82 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.Firestore; + +/** Examples of references to a collection, document in a collection and subcollection. */ +public class References { + + private final Firestore db; + + public References(Firestore db) { + this.db = db; + } + + /** + * Return a reference to collection. + * + * @return collection reference + */ + public CollectionReference getACollectionRef() { + // [START fs_collection_ref] + // Reference to the collection "users" + CollectionReference collection = db.collection("users"); + // [END fs_collection_ref] + return collection; + } + + /** + * Return a reference to a document. + * + * @return document reference + */ + public DocumentReference getADocumentRef() { + // [START fs_document_ref] + // Reference to a document with id "alovelace" in the collection "employees" + DocumentReference document = db.collection("users").document("alovelace"); + // [END fs_document_ref] + return document; + } + + /** + * Return a reference to a document using path. + * + * @return document reference + */ + public DocumentReference getADocumentRefUsingPath() { + // [START fs_document_path_ref] + // Reference to a document with id "alovelace" in the collection "employees" + DocumentReference document = db.document("users/alovelace"); + // [END fs_document_path_ref] + return document; + } + + /** + * Return a reference to a document in a sub-collection. + * + * @return document reference in a subcollection + */ + public DocumentReference getASubCollectionDocumentRef() { + // [START fs_subcollection_ref] + // Reference to a document in subcollection "messages" + DocumentReference document = + db.collection("rooms").document("roomA").collection("messages").document("message1"); + // [END fs_subcollection_ref] + return document; + } +} diff --git a/firestore/src/main/java/com/example/firestore/snippets/RetrieveDataSnippets.java b/firestore/src/main/java/com/example/firestore/snippets/RetrieveDataSnippets.java new file mode 100644 index 00000000000..e3c7515f841 --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/snippets/RetrieveDataSnippets.java @@ -0,0 +1,138 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import com.example.firestore.snippets.model.City; + +import com.google.api.core.ApiFuture; +import com.google.api.core.ApiFutures; +import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.QuerySnapshot; +import com.google.cloud.firestore.WriteResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** Snippets to demonstrate Firestore data retrieval operations. */ +public class RetrieveDataSnippets { + + private final Firestore db; + + RetrieveDataSnippets(Firestore db) { + this.db = db; + } + + /** Create cities collection and add sample documents. */ + void prepareExamples() throws Exception { + // [START fs_retrieve_create_examples] + CollectionReference cities = db.collection("cities"); + List> futures = new ArrayList<>(); + futures.add(cities.document("SF").set(new City("San Francisco", "CA", "USA", false, 860000L))); + futures.add(cities.document("LA").set(new City("Los Angeles", "CA", "USA", false, 3900000L))); + futures.add(cities.document("DC").set(new City("Washington D.C.", null, "USA", true, 680000L))); + futures.add(cities.document("TOK").set(new City("Tokyo", null, "Japan", true, 9000000L))); + futures.add(cities.document("BJ").set(new City("Beijing", null, "China", true, 21500000L))); + // (optional) block on operation + ApiFutures.allAsList(futures).get(); + // [END fs_retrieve_create_examples] + } + + /** + * Retrieves document in collection as map. + * + * @return map (string => object) + */ + public Map getDocumentAsMap() throws Exception { + // [START fs_get_doc_as_map] + DocumentReference docRef = db.collection("cities").document("SF"); + // asynchronously retrieve the document + ApiFuture future = docRef.get(); + // ... + // future.get() blocks on response + DocumentSnapshot document = future.get(); + if (document.exists()) { + System.out.println("Document data: " + document.getData()); + } else { + System.out.println("No such document!"); + } + // [END fs_get_doc_as_map] + return (document.exists()) ? document.getData() : null; + } + + /** + * Retrieves document in collection as a custom object. + * + * @return document data as City object + */ + public City getDocumentAsEntity() throws Exception { + // [START fs_get_doc_as_entity] + DocumentReference docRef = db.collection("cities").document("BJ"); + // asynchronously retrieve the document + ApiFuture future = docRef.get(); + // block on response + DocumentSnapshot document = future.get(); + City city = null; + if (document.exists()) { + // convert document to POJO + city = document.toObject(City.class); + System.out.println(city); + } else { + System.out.println("No such document!"); + } + // [END fs_get_doc_as_entity] + return city; + } + + /** + * Return multiple documents from a collection based on a query. + * + * @return list of documents of capital cities. + */ + public List getQueryResults() throws Exception { + // [START fs_get_multiple_docs] + //asynchronously retrieve multiple documents + ApiFuture future = + db.collection("cities").whereEqualTo("capital", true).get(); + // future.get() blocks on response + List documents = future.get().getDocuments(); + for (DocumentSnapshot document : documents) { + System.out.println(document.getId() + " => " + document.toObject(City.class)); + } + // [END fs_get_multiple_docs] + return documents; + } + + /** + * Return all documents in the cities collection. + * + * @return list of documents + */ + public List getAllDocuments() throws Exception { + // [START fs_get_all_docs] + //asynchronously retrieve all documents + ApiFuture future = db.collection("cities").get(); + // future.get() blocks on response + List documents = future.get().getDocuments(); + for (DocumentSnapshot document : documents) { + System.out.println(document.getId() + " => " + document.toObject(City.class)); + } + // [END fs_get_all_docs] + return documents; + } +} diff --git a/firestore/src/main/java/com/example/firestore/snippets/model/City.java b/firestore/src/main/java/com/example/firestore/snippets/model/City.java new file mode 100644 index 00000000000..c3cc3ebcd5e --- /dev/null +++ b/firestore/src/main/java/com/example/firestore/snippets/model/City.java @@ -0,0 +1,144 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets.model; + +import java.util.Objects; + +/** Represents a city : name, weather, population, country, capital, geo coordinates. */ +public class City { + + private String name; + private String state; + private String country; + private Boolean capital; + private Long population; + + // [START fs_class_definition] + public City() { + // Must have a public no-argument constructor + } + + // Initialize all fields of a city + public City(String name, String state, String country, Boolean capital, Long population) { + this.name = name; + this.state = state; + this.country = country; + this.capital = capital; + this.population = population; + } + // [END fs_class_definition] + + public City(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public Boolean getCapital() { + return capital; + } + + public void setCapital(Boolean capital) { + this.capital = capital; + } + + public Long getPopulation() { + return population; + } + + public void setPopulation(Long population) { + this.population = population; + } + + private String getDefinedValue(String s) { + if (s != null) { + return s; + } else { + return ""; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (name != null) { + sb.append(name); + } + if (state != null) { + sb.append(" state : "); + sb.append(state); + sb.append(","); + } + if (country != null) { + sb.append(", "); + sb.append(country); + } + sb.append(" : ["); + if (population != null) { + sb.append(" population : "); + sb.append(population); + sb.append(","); + } + if (capital != null) { + sb.append(" capital : "); + sb.append(capital); + sb.append(","); + } + //remove trailing comma + if (sb.lastIndexOf(",") >= sb.length() - 1) { + sb.deleteCharAt(sb.length() - 1); + } + sb.append(" ]"); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof City)) { + return false; + } + City city = (City) obj; + return Objects.equals(name, city.name) + && Objects.equals(state, city.state) + && Objects.equals(country, city.country) + && Objects.equals(population, city.population) + && Objects.equals(capital, city.capital); + + } +} diff --git a/firestore/src/test/java/com/example/firestore/QuickstartIT.java b/firestore/src/test/java/com/example/firestore/QuickstartIT.java new file mode 100644 index 00000000000..a84d45ce1ad --- /dev/null +++ b/firestore/src/test/java/com/example/firestore/QuickstartIT.java @@ -0,0 +1,120 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore; + +import static org.junit.Assert.assertTrue; + +import com.google.api.core.ApiFuture; + +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.QuerySnapshot; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class QuickstartIT { + + private Quickstart quickstart; + private Firestore db; + private ByteArrayOutputStream bout; + private PrintStream out; + private String projectId = "java-docs-samples-firestore"; + + @Before + public void setUp() throws Exception { + quickstart = new Quickstart(projectId); + db = quickstart.getDb(); + bout = new ByteArrayOutputStream(); + out = new PrintStream(bout); + System.setOut(out); + deleteAllDocuments(); + } + + @Test + public void testQuickstart() throws Exception { + addData(); + + bout.reset(); + quickstart.runAQuery(); + String output = bout.toString(); + // confirm that results do not contain aturing + assertTrue(output.contains("alovelace")); + assertTrue(output.contains("cbabbage")); + assertTrue(!output.contains("aturing")); + + bout.reset(); + quickstart.retrieveAllDocuments(); + output = bout.toString(); + // confirm that all documents are retrieved + assertTrue(output.contains("alovelace")); + assertTrue(output.contains("aturing")); + assertTrue(output.contains("cbabbage")); + } + + private void validate(DocumentReference docRef, Map data) throws Exception { + DocumentSnapshot documentSnapshot = docRef.get().get(); + assertTrue(Objects.equals(documentSnapshot.getData(), data)); + } + + private void addData() throws Exception { + Map expectedData = new HashMap<>(); + + quickstart.addDocument("alovelace"); + expectedData.put("first", "Ada"); + expectedData.put("last", "Lovelace"); + expectedData.put("born", 1815L); + validate(db.document("users/alovelace"), expectedData); + + expectedData.clear(); + expectedData.put("first", "Alan"); + expectedData.put("middle", "Mathison"); + expectedData.put("last", "Turing"); + expectedData.put("born", 1912L); + quickstart.addDocument("aturing"); + validate(db.document("users/aturing"), expectedData); + + expectedData.clear(); + expectedData.put("first", "Charles"); + expectedData.put("last", "Babbage"); + expectedData.put("born", 1791L); + quickstart.addDocument("cbabbage"); + validate(db.document("users/cbabbage"), expectedData); + } + + private void deleteAllDocuments() throws Exception { + ApiFuture future = db.collection("users").get(); + QuerySnapshot querySnapshot = future.get(); + for (DocumentSnapshot doc : querySnapshot.getDocuments()) { + // block on delete operation + db.document("users/" + doc.getId()).delete().get(); + } + } + + @After + public void tearDown() throws Exception { + deleteAllDocuments(); + } +} diff --git a/firestore/src/test/java/com/example/firestore/snippets/ManageDataSnippetsIT.java b/firestore/src/test/java/com/example/firestore/snippets/ManageDataSnippetsIT.java new file mode 100644 index 00000000000..c0a95fdd651 --- /dev/null +++ b/firestore/src/test/java/com/example/firestore/snippets/ManageDataSnippetsIT.java @@ -0,0 +1,213 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.example.firestore.snippets.model.City; +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.CollectionReference; +import com.google.cloud.firestore.DocumentReference; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +import com.google.cloud.firestore.QuerySnapshot; +import java.util.Date; +import java.util.Map; +import java.util.Objects; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class ManageDataSnippetsIT { + + private static Firestore db; + private static ManageDataSnippets manageDataSnippets; + private static String projectId = "java-docs-samples-firestore"; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance().toBuilder() + .setProjectId(projectId) + .build(); + db = firestoreOptions.getService(); + deleteAllDocuments(); + manageDataSnippets = new ManageDataSnippets(db); + } + + @Test + public void testAddDatasMap() throws Exception { + Map expectedData = manageDataSnippets.addSimpleDocumentAsMap(); + DocumentReference docRef = db.collection("cities").document("LA"); + assertTrue(Objects.equals(expectedData, getDocumentDataAsMap(docRef))); + } + + @Test + public void testAddDataWithDifferentDataTypes() throws Exception { + Map expectedData = manageDataSnippets.addDocumentWithDifferentDataTypes(); + DocumentReference docRef = db.collection("data").document("one"); + assertEquals(expectedData, getDocumentDataAsMap(docRef)); + } + + @Test + public void testAddDataAsEntity() throws Exception { + City city = manageDataSnippets.addSimpleDocumentAsEntity(); + DocumentReference docRef = db.collection("cities").document("LA"); + assertTrue(Objects.equals(city, getDocumentDataAsCity(docRef))); + } + + @Test + public void testAddDocWithAutoGenId() throws Exception { + String autoId = manageDataSnippets.addDocumentDataWithAutoGeneratedId(); + City city = new City("Tokyo"); + city.setCountry("Japan"); + DocumentReference docRef = db.collection("cities").document(autoId); + assertTrue(Objects.equals(city, getDocumentDataAsCity(docRef))); + } + + @Test + public void testAddDocAfterAutoGenId() throws Exception { + String autoId = manageDataSnippets.addDocumentDataAfterAutoGeneratingId(); + City city = new City(); + DocumentReference docRef = db.collection("cities").document(autoId); + assertTrue(Objects.equals(city, getDocumentDataAsCity(docRef))); + } + + @Test + public void testUpdateSimpleDocument() throws Exception { + manageDataSnippets.updateSimpleDocument(); + DocumentReference docRef = db.collection("cities").document("DC"); + City city = new City("Washington D.C."); + city.setCapital(true); + assertTrue(Objects.equals(city, getDocumentDataAsCity(docRef))); + } + + @Test + public void testUpdateUsingMap() throws Exception { + manageDataSnippets.updateUsingMap(); + DocumentReference docRef = db.collection("cities").document("DC"); + City city = new City("Washington D.C."); + city.setCapital(true); + city.setCountry("USA"); + assertTrue(Objects.equals(city, getDocumentDataAsCity(docRef))); + } + + @Test + public void testUpdateAndCreateIfMissing() throws Exception { + manageDataSnippets.updateAndCreateIfMissing(); + DocumentReference docRef = db.collection("cities").document("BJ"); + assertTrue(getDocumentDataAsCity(docRef).getCapital()); + } + + @Test + public void testUpdateNestedFields() throws Exception { + manageDataSnippets.updateNestedFields(); + DocumentReference docRef = db.collection("users").document("frank"); + + DocumentSnapshot snapshot = getDocumentData(docRef); + assertEquals((long) snapshot.getLong("age"), 13); + assertEquals(snapshot.getString("favorites.color"), "Red"); + assertEquals(snapshot.getString("favorites.food"), "Pizza"); + } + + @Test + public void testUpdateServerTimestamp() throws Exception { + manageDataSnippets.updateServerTimestamp(); + DocumentReference docRef = db.collection("objects").document("some-id"); + Map data = getDocumentDataAsMap(docRef); + assertTrue(data.get("timestamp") instanceof Date); + } + + @Test + public void testDeleteFields() throws Exception { + manageDataSnippets.deleteFields(); + DocumentReference docRef = db.collection("cities").document("BJ"); + Map data = getDocumentDataAsMap(docRef); + assertFalse(data.containsKey("capital")); + } + + @Test(expected = Exception.class) + public void testDeleteDocument() throws Exception { + manageDataSnippets.deleteDocument(); + getDocumentDataAsMap(db.collection("cities").document("DC")); + } + + @Test + public void testSimpleTransaction() throws Exception { + DocumentReference docRef = db.collection("cities").document("SF"); + ApiFuture future = manageDataSnippets.runSimpleTransaction(); + future.get(); + Map data = getDocumentDataAsMap(docRef); + assertEquals(data.get("population"), 860000L + 1L); + } + + @Test + public void testTransactionReturnsInfo() throws Exception { + String info = manageDataSnippets.returnInfoFromTransaction(50L); + assertEquals(info, "Population increased to 51"); + try { + info = manageDataSnippets.returnInfoFromTransaction(5000001L); + assertTrue("Should never get here", false); + } catch (Exception e) { + assertTrue(e.getMessage().contains("Sorry! Population is too big.")); + } + } + + @Test + public void testWriteBatchIsSuccessful() throws Exception { + manageDataSnippets.writeBatch(); + CollectionReference collection = db.collection("cities"); + ApiFuture document = collection.document("NYC").get(); + assertTrue(document.get().exists()); + DocumentReference documentReference = collection.document("SF"); + Map data = getDocumentDataAsMap(documentReference); + assertTrue(data.containsKey("population")); + document = collection.document("LA").get(); + assertFalse(document.get().exists()); + } + + private DocumentSnapshot getDocumentData(DocumentReference docRef) throws Exception { + return docRef.get().get(); + } + + private Map getDocumentDataAsMap(DocumentReference docRef) throws Exception { + return docRef.get().get().getData(); + } + + private City getDocumentDataAsCity(DocumentReference docRef) throws Exception { + return docRef.get().get().toObject(City.class); + } + + private static void deleteAllDocuments() throws Exception { + ApiFuture future = db.collection("cities").get(); + QuerySnapshot querySnapshot = future.get(); + for (DocumentSnapshot doc : querySnapshot.getDocuments()) { + // block on delete operation + db.collection("cities").document(doc.getId()).delete().get(); + } + } + + @AfterClass + public static void tearDown() throws Exception { + manageDataSnippets.deleteCollection(db.collection("cities"), 10); + manageDataSnippets.deleteCollection(db.collection("users"), 10); + } +} diff --git a/firestore/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java b/firestore/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java new file mode 100644 index 00000000000..3b93a38bac9 --- /dev/null +++ b/firestore/src/test/java/com/example/firestore/snippets/QueryDataSnippetsIT.java @@ -0,0 +1,225 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +import com.google.cloud.firestore.Query; +import com.google.cloud.firestore.QuerySnapshot; +import com.google.common.collect.ImmutableMap; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class QueryDataSnippetsIT { + + private static Firestore db; + private static QueryDataSnippets queryDataSnippets; + private static String projectId = "java-docs-samples-firestore"; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance().toBuilder() + .setProjectId(projectId) + .build(); + db = firestoreOptions.getService(); + deleteAllDocuments(); + queryDataSnippets = new QueryDataSnippets(db); + queryDataSnippets.prepareExamples(); + } + + @Test + public void testCreateAQuery() throws Exception { + Query q = queryDataSnippets.createAQuery(); + Set result = getResultsAsSet(q); + Set expectedResults = new HashSet<>(Arrays.asList("DC", "TOK", "BJ")); + assertTrue(Objects.equals(result, expectedResults)); + } + + @Test + public void testSimpleQueryReturnsExpectedResults() throws Exception { + List> expectedResults = new ArrayList<>(); + + expectedResults.add(new HashSet<>(Arrays.asList("SF", "LA"))); + expectedResults.add(new HashSet<>(Arrays.asList("SF", "DC"))); + expectedResults.add(new HashSet<>(Arrays.asList("SF", "DC", "TOK"))); + + List queries = queryDataSnippets.createSimpleQueries(); + for (int i = 0; i < queries.size(); i++) { + Set results = getResultsAsSet(queries.get(i)); + assertTrue(Objects.equals(results, expectedResults.get(i))); + } + } + + @Test + public void testChainedQuery() throws Exception { + Query q = queryDataSnippets.createChainedQuery(); + Set result = getResultsAsSet(q); + Set expectedResults = new HashSet<>(); + assertTrue(Objects.equals(result, expectedResults)); + } + + @Test + public void testRangeQuery() throws Exception { + Query q = queryDataSnippets.createRangeQuery(); + Set result = getResultsAsSet(q); + Set expectedResults = new HashSet<>(Arrays.asList("SF", "LA")); + assertTrue(Objects.equals(result, expectedResults)); + } + + @Test(expected = Exception.class) + public void testInvalidRangeQueryThrowsException() throws Exception { + Query q = queryDataSnippets.createInvalidRangeQuery(); + getResults(q); + } + + @Test + public void testOrderByNameWithLimitQuery() throws Exception { + Query q = queryDataSnippets.createOrderByNameWithLimitQuery(); + List result = getResults(q); + List expectedResults = Arrays.asList("BJ", "LA", "SF"); + assertEquals(result, expectedResults); + } + + @Test + public void testOrderByNameDescWithLimitQuery() throws Exception { + Query q = queryDataSnippets.createOrderByNameDescWithLimitQuery(); + List result = getResults(q); + List expectedResults = Arrays.asList("DC", "TOK", "SF"); + assertTrue(Objects.equals(result, expectedResults)); + } + + @Test + public void testWhereWithOrderByAndLimitQuery() throws Exception { + Query q = queryDataSnippets.createWhereWithOrderByAndLimitQuery(); + List result = getResults(q); + List expectedResults = Arrays.asList("LA", "TOK"); + assertEquals(result, expectedResults); + } + + @Test + public void testRangeWithOrderByQuery() throws Exception { + Query q = queryDataSnippets.createRangeWithOrderByQuery(); + List result = getResults(q); + List expectedResults = Arrays.asList("LA", "TOK", "BJ"); + assertEquals(result, expectedResults); + } + + @Test(expected = Exception.class) + public void testInvalidRangeWithOrderByQuery() throws Exception { + Query q = queryDataSnippets.createInvalidRangeWithOrderByQuery(); + getResults(q); + } + + @Test + public void testStartAtFieldQueryCursor() throws Exception { + Query q = queryDataSnippets.createStartAtFieldQueryCursor(); + List expectedResults = Arrays.asList("TOK", "BJ"); + List result = getResults(q); + assertTrue(Objects.equals(result, expectedResults)); + } + + @Test + public void testEndAtFieldQueryCursor() throws Exception { + Query q = queryDataSnippets.createEndAtFieldQueryCursor(); + List expectedResults = Arrays.asList("DC", "SF", "LA"); + List result = getResults(q); + assertEquals(result, expectedResults); + } + + @Test + public void testMultipleCursorConditions() throws Exception { + // populate us_cities collection + Map city1 = new ImmutableMap.Builder() + .put("name", "Springfield").put("state", "Massachusetts").build(); + Map city2 = new ImmutableMap.Builder() + .put("name", "Springfield").put("state", "Missouri").build(); + Map city3 = new ImmutableMap.Builder() + .put("name", "Springfield").put("state", "Wisconsin").build(); + + db.collection("us_cities").document("Massachusetts").set(city1).get(); + db.collection("us_cities").document("Missouri").set(city2).get(); + db.collection("us_cities").document("Wisconsin").set(city3).get(); + + Query query1 = db.collection("us_cities") + .orderBy("name") + .orderBy("state") + .startAt("Springfield"); + + // all documents are retrieved + QuerySnapshot querySnapshot = query1.get().get(); + List docs = querySnapshot.getDocuments(); + assertEquals(3, docs.size()); + + + // Will return "Springfield, Missouri" and "Springfield, Wisconsin" + Query query2 = db.collection("us_cities") + .orderBy("name") + .orderBy("state") + .startAt("Springfield", "Missouri"); + + // only Missouri and Wisconsin are retrieved + List expectedResults = Arrays.asList("Missouri", "Wisconsin"); + List result = getResults(query2); + assertTrue(Objects.equals(result, expectedResults)); + } + + private Set getResultsAsSet(Query query) throws Exception { + List docIds = getResults(query); + return new HashSet<>(docIds); + } + + private List getResults(Query query) throws Exception { + // asynchronously retrieve query results + ApiFuture future = query.get(); + // block on response + QuerySnapshot querySnapshot = future.get(); + List docIds = new ArrayList<>(); + for (DocumentSnapshot document : querySnapshot.getDocuments()) { + docIds.add(document.getId()); + } + return docIds; + } + + private static void deleteAllDocuments() throws Exception { + ApiFuture future = db.collection("cities").get(); + QuerySnapshot querySnapshot = future.get(); + for (DocumentSnapshot doc : querySnapshot.getDocuments()) { + // block on delete operation + db.collection("cities").document(doc.getId()).delete().get(); + } + } + + @AfterClass + public static void tearDown() throws Exception { + deleteAllDocuments(); + } +} diff --git a/firestore/src/test/java/com/example/firestore/snippets/RetrieveDataSnippetsIT.java b/firestore/src/test/java/com/example/firestore/snippets/RetrieveDataSnippetsIT.java new file mode 100644 index 00000000000..455733d29d3 --- /dev/null +++ b/firestore/src/test/java/com/example/firestore/snippets/RetrieveDataSnippetsIT.java @@ -0,0 +1,113 @@ +/* + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.firestore.snippets; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import com.example.firestore.snippets.model.City; + +import com.google.api.core.ApiFuture; +import com.google.cloud.firestore.DocumentSnapshot; +import com.google.cloud.firestore.Firestore; +import com.google.cloud.firestore.FirestoreOptions; +import com.google.cloud.firestore.QuerySnapshot; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +@SuppressWarnings("checkstyle:abbreviationaswordinname") +public class RetrieveDataSnippetsIT { + private static Firestore db; + private static RetrieveDataSnippets retrieveDataSnippets; + private static String projectId = "java-docs-samples-firestore"; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + FirestoreOptions firestoreOptions = FirestoreOptions.getDefaultInstance().toBuilder() + .setProjectId(projectId) + .build(); + db = firestoreOptions.getService(); + deleteAllDocuments(); + retrieveDataSnippets = new RetrieveDataSnippets(db); + retrieveDataSnippets.prepareExamples(); + } + + @Test + public void testRetrievalAsMap() throws Exception { + Map data = retrieveDataSnippets.getDocumentAsMap(); + assertEquals(data.get("name"), "San Francisco"); + assertEquals(data.get("country"), "USA"); + assertEquals(data.get("capital"), false); + assertEquals(data.get("population"), 860000L); + } + + @Test + public void testRetrieveAsEntity() throws Exception { + City city = retrieveDataSnippets.getDocumentAsEntity(); + assertEquals(city.getName(), "Beijing"); + assertEquals(city.getCountry(), "China"); + assertEquals(city.getCapital(), true); + assertEquals((long) city.getPopulation(), 21500000L); + } + + @Test + public void testRetrieveQueryResults() throws Exception { + List docs = retrieveDataSnippets.getQueryResults(); + assertEquals(docs.size(), 3); + Set docIds = new HashSet<>(); + for (DocumentSnapshot doc : docs) { + docIds.add(doc.getId()); + } + assertTrue(docIds.contains("BJ") && docIds.contains("TOK") && docIds.contains("DC")); + } + + @Test + public void testRetrieveAllDocuments() throws Exception { + List docs = retrieveDataSnippets.getAllDocuments(); + assertEquals(docs.size(), 5); + Set docIds = new HashSet<>(); + for (DocumentSnapshot doc : docs) { + docIds.add(doc.getId()); + } + assertTrue( + docIds.contains("SF") + && docIds.contains("LA") + && docIds.contains("DC") + && docIds.contains("TOK") + && docIds.contains("BJ")); + } + + private static void deleteAllDocuments() throws Exception { + ApiFuture future = db.collection("cities").get(); + QuerySnapshot querySnapshot = future.get(); + for (DocumentSnapshot doc : querySnapshot.getDocuments()) { + // block on delete operation + db.collection("cities").document(doc.getId()).delete().get(); + } + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + deleteAllDocuments(); + } +} diff --git a/pom.xml b/pom.xml index d14b425184c..07e7db7bc59 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,8 @@ errorreporting + firestore + iap kms