Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@
import com.google.firebase.firestore.pipeline.FindNearestStage;
import com.google.firebase.firestore.pipeline.SampleStage;
import com.google.firebase.firestore.pipeline.SearchStage;
import com.google.firebase.firestore.pipeline.CollectionGroupOptions;
import com.google.firebase.firestore.pipeline.CollectionHints;
import com.google.firebase.firestore.pipeline.UnnestOptions;

import static com.google.firebase.firestore.pipeline.Expression.field;
Expand Down Expand Up @@ -4204,4 +4206,330 @@ void searchPhraseMatch() {
// [END search_phrase_match]
}

void pipelineJoinTestData() {
// [START pipeline_join_test_data]
// Load set of cities.
CollectionReference cities = db.collection("cities");

Map<String, Object> sfData = new HashMap<>();
sfData.put("name", "San Francisco");
sfData.put("state", "CA");
sfData.put("country", "USA");
cities.document("SF").set(sfData);

Map<String, Object> laData = new HashMap<>();
laData.put("name", "Los Angeles");
laData.put("state", "CA");
laData.put("country", "USA");
cities.document("LA").set(laData);

Map<String, Object> dcData = new HashMap<>();
dcData.put("name", "Washington, D.C.");
dcData.put("state", null);
dcData.put("country", "USA");
cities.document("DC").set(dcData);

Map<String, Object> tokData = new HashMap<>();
tokData.put("name", "Tokyo");
tokData.put("state", null);
tokData.put("country", "Japan");
cities.document("TOK").set(tokData);

// Load restaurants in various cities.
CollectionReference sfRestaurants = db.collection("cities").document("SF").collection("restaurants");
CollectionReference laRestaurants = db.collection("cities").document("LA").collection("restaurants");
CollectionReference dcRestaurants = db.collection("cities").document("DC").collection("restaurants");

DocumentReference rest1 = sfRestaurants.document("rest1");
Map<String, Object> rest1Data = new HashMap<>();
rest1Data.put("name", "Golden Gate Pizza");
rest1Data.put("type", "pizza");
rest1Data.put("owner_id", "Mario Rossi");
rest1.set(rest1Data);

DocumentReference rest2 = sfRestaurants.document("rest2");
Map<String, Object> rest2Data = new HashMap<>();
rest2Data.put("name", "Bay Area Burger");
rest2Data.put("type", "burger");
rest2Data.put("owner_id", "Sarah Jenkins");
rest2.set(rest2Data);

DocumentReference rest3 = sfRestaurants.document("rest3");
Map<String, Object> rest3Data = new HashMap<>();
rest3Data.put("name", "Sunset Taco");
rest3Data.put("type", "mexican");
rest3Data.put("owner_id", "Edward");
rest3.set(rest3Data);

DocumentReference rest4 = laRestaurants.document("rest4");
Map<String, Object> rest4Data = new HashMap<>();
rest4Data.put("name", "Hollywood Sushi");
rest4Data.put("type", "sushi");
rest4Data.put("owner_id", "Ken Kenji");
rest4.set(rest4Data);

DocumentReference rest5 = laRestaurants.document("rest5");
Map<String, Object> rest5Data = new HashMap<>();
rest5Data.put("name", "Venice Pizza");
rest5Data.put("type", "pizza");
rest5Data.put("owner_id", "Luigi Romano");
rest5.set(rest5Data);

DocumentReference rest6 = dcRestaurants.document("rest6");
Map<String, Object> rest6Data = new HashMap<>();
rest6Data.put("name", "Capitol Tacos");
rest6Data.put("type", "mexican");
rest6Data.put("owner_id", "Maria Garcia");
rest6.set(rest6Data);

DocumentReference rest7 = dcRestaurants.document("rest7");
Map<String, Object> rest7Data = new HashMap<>();
rest7Data.put("name", "Georgetown Coffee");
rest7Data.put("type", "cafe");
rest7Data.put("owner_id", "David Kim");
rest7.set(rest7Data);

// Load collection of reviews.
CollectionReference reviews = db.collection("reviews");

Map<String, Object> rev1 = new HashMap<>();
rev1.put("restaurant", rest1);
rev1.put("rating", 5);
rev1.put("reviewer_id", "Alice");
reviews.add(rev1);

Map<String, Object> rev2 = new HashMap<>();
rev2.put("restaurant", rest1);
rev2.put("rating", 4);
rev2.put("reviewer_id", "Bob");
reviews.add(rev2);

Map<String, Object> rev3 = new HashMap<>();
rev3.put("restaurant", rest2);
rev3.put("rating", 4);
rev3.put("reviewer_id", "Charlie");
reviews.add(rev3);

Map<String, Object> rev4 = new HashMap<>();
rev4.put("restaurant", rest3);
rev4.put("rating", 5);
rev4.put("reviewer_id", "Diana");
reviews.add(rev4);

Map<String, Object> rev5 = new HashMap<>();
rev5.put("restaurant", rest3);
rev5.put("rating", 4);
rev5.put("reviewer_id", "Edward");
reviews.add(rev5);

Map<String, Object> rev6 = new HashMap<>();
rev6.put("restaurant", rest3);
rev6.put("rating", 4);
rev6.put("reviewer_id", "Fiona");
reviews.add(rev6);

// rest4 has 0 reviews

Map<String, Object> rev7 = new HashMap<>();
rev7.put("restaurant", rest5);
rev7.put("rating", 3);
rev7.put("reviewer_id", "George");
reviews.add(rev7);

Map<String, Object> rev8 = new HashMap<>();
rev8.put("restaurant", rest6);
rev8.put("rating", 5);
rev8.put("reviewer_id", "Hannah");
reviews.add(rev8);

Map<String, Object> rev9 = new HashMap<>();
rev9.put("restaurant", rest6);
rev9.put("rating", 4);
rev9.put("reviewer_id", "Ian");
reviews.add(rev9);

Map<String, Object> rev10 = new HashMap<>();
rev10.put("restaurant", rest7);
rev10.put("rating", 5);
rev10.put("reviewer_id", "Julia");
reviews.add(rev10);
// [END pipeline_join_test_data]
}

void pipelineJoinLookup() {
// [START pipeline_join_lookup]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("reviews")
.define(field("restaurant").alias("restaurant_name"))
.addFields(
db.pipeline()
.collectionGroup("restaurants")
.where(field("__name__").equal(variable("restaurant_name")))
.select("name", "type")
.toScalarExpression()
.alias("restaurant")
)
.execute();
// [END pipeline_join_lookup]
}

void pipelineJoinArray() {
// [START pipeline_join_array]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.where(field("type").equal("pizza"))
.define(field("__name__").alias("restaurant_name"))
.select(
field("name"),
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("restaurant_name")))
.select("rating", "reviewer_id")
.toArrayExpression()
.alias("reviews")
)
.execute();
// [END pipeline_join_array]
}

void pipelineJoinAggregate() {
// [START pipeline_join_aggregate]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.where(field("type").equal("pizza"))
.define(field("__name__").alias("restaurant_name"))
.select(
field("name"),
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("restaurant_name")))
.aggregate(average("rating").alias("avg_rating"))
.toScalarExpression()
.alias("avg_rating")
)
.execute();
// [END pipeline_join_aggregate]
}

void pipelineJoinLimit() {
// [START pipeline_join_limit]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.define(field("__name__").alias("restaurant_name"))
.select(
field("name"),
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("restaurant_name")))
.sort(field("rating").descending())
.limit(2)
.select("rating", "reviewer_id")
.toArrayExpression()
.alias("top_reviews")
)
.execute();
// [END pipeline_join_limit]
}

void pipelineJoinSubcollection() {
// [START pipeline_join_subcollection]
Task<Pipeline.Snapshot> results = db.pipeline()
.collection("cities")
.addFields(
PipelineSource.subcollection("restaurants")
.toArrayExpression()
.length()
.alias("restaurant_count")
)
.execute();
// [END pipeline_join_subcollection]
}

void pipelineJoinMultiField() {
// [START pipeline_join_multi_field]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.define(
field("owner_id").alias("owner_id"),
field("__name__").alias("__name__")
)
.where(
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("__name__")))
.where(field("reviewer_id").equal(variable("owner_id")))
.aggregate(countAll().alias("c"))
.toScalarExpression()
.greaterThan(0)
)
.execute();
// [END pipeline_join_multi_field]
}

void pipelineJoinAnti() {
// [START pipeline_join_anti]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.define(field("__name__").alias("restaurant_name"))
.where(
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("restaurant_name")))
.aggregate(countAll().alias("review_count"))
.toScalarExpression()
.equal(0)
)
.execute();
// [END pipeline_join_anti]
}

void pipelineJoinUnnest() {
// [START pipeline_join_unnest]
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup("restaurants")
.where(field("type").equal("pizza"))
.define(field("__name__").alias("restaurant_name"))
.unnest(
db.pipeline()
.collectionGroup("reviews")
.where(field("restaurant").equal(variable("restaurant_name")))
.select("rating", "reviewer_id")
.toArrayExpression()
.alias("review")
)
.execute();
// [END pipeline_join_unnest]
}

void pipelineJoinUncorrelated() {
// [START pipeline_join_uncorrelated]
Task<Pipeline.Snapshot> results = db.pipeline()
.collection("reviews")
// Average review rating is 4.3
.where(
field("rating").greaterThan(
db.pipeline()
.collection("reviews")
.aggregate(average("rating").alias("avg"))
.toScalarExpression()
)
)
.select("rating", "reviewer_id")
.execute();
// [END pipeline_join_uncorrelated]
}

void pipelineForceTableScan() {
// [START pipeline_force_table_scan]
// Force Planner to only do a Full-Table Scan
Task<Pipeline.Snapshot> results = db.pipeline()
.collectionGroup(
"customers",
new CollectionGroupOptions().withHints(new CollectionHints().withForceIndex("primary"))
)
.limit(2)
.execute();
// [END pipeline_force_table_scan]
}

}
Loading
Loading