Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.

Commit c49a906

Browse files
authored
Merge branch 'main' into mila/ifnull-coalesce
2 parents 8c1e209 + 0e30ec4 commit c49a906

3 files changed

Lines changed: 89 additions & 9 deletions

File tree

google-cloud-firestore/src/main/java/com/google/cloud/firestore/PipelineUtils.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,15 +174,19 @@ static BooleanExpression toPipelineBooleanExpr(FilterInternal f) {
174174
static AliasedAggregate toPipelineAggregatorTarget(AggregateField f) {
175175
String operator = f.getOperator();
176176
String fieldPath = f.getFieldPath();
177+
String alias = f.getAlias();
178+
if (alias.contains(".")) {
179+
alias = "`" + alias + "`";
180+
}
177181

178182
switch (operator) {
179183
case "sum":
180-
return Field.ofServerPath(fieldPath).sum().as(f.getAlias());
184+
return Field.ofServerPath(fieldPath).sum().as(alias);
181185

182186
case "count":
183-
return countAll().as(f.getAlias());
187+
return countAll().as(alias);
184188
case "average":
185-
return Field.ofServerPath(fieldPath).average().as(f.getAlias());
189+
return Field.ofServerPath(fieldPath).average().as(alias);
186190
default:
187191
// Handle the 'else' case appropriately in your Java code
188192
throw new IllegalArgumentException("Unsupported operator: " + operator);

google-cloud-firestore/src/main/java/com/google/cloud/firestore/pipeline/expressions/Expression.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4458,6 +4458,39 @@ public static Expression collectionId(String pathFieldName) {
44584458
return collectionId(field(pathFieldName));
44594459
}
44604460

4461+
/**
4462+
* Creates an expression that returns the parent document of a document reference.
4463+
*
4464+
* @param documentPath An expression that evaluates to a document path.
4465+
* @return A new {@link Expression} representing the parent operation.
4466+
*/
4467+
@BetaApi
4468+
public static Expression parent(Expression documentPath) {
4469+
return new FunctionExpression("parent", ImmutableList.of(documentPath));
4470+
}
4471+
4472+
/**
4473+
* Creates an expression that returns the parent document of a document reference.
4474+
*
4475+
* @param documentPath The string representation of the document path.
4476+
* @return A new {@link Expression} representing the parent operation.
4477+
*/
4478+
@BetaApi
4479+
public static Expression parent(String documentPath) {
4480+
return parent(constant(documentPath));
4481+
}
4482+
4483+
/**
4484+
* Creates an expression that returns the parent document of a document reference.
4485+
*
4486+
* @param docRef The {@link DocumentReference}.
4487+
* @return A new {@link Expression} representing the parent operation.
4488+
*/
4489+
@BetaApi
4490+
public static Expression parent(DocumentReference docRef) {
4491+
return parent(constant(docRef));
4492+
}
4493+
44614494
// Type Checking Functions
44624495
/**
44634496
* Creates an expression that checks if a field exists.
@@ -7137,6 +7170,16 @@ public final Expression collectionId() {
71377170
return collectionId(this);
71387171
}
71397172

7173+
/**
7174+
* Creates an expression that returns the parent document of a document reference.
7175+
*
7176+
* @return A new {@link Expression} representing the parent operation.
7177+
*/
7178+
@BetaApi
7179+
public final Expression parent() {
7180+
return parent(this);
7181+
}
7182+
71407183
/**
71417184
* Creates an expression that returns a string indicating the type of the value this expression
71427185
* evaluates to.

google-cloud-firestore/src/test/java/com/google/cloud/firestore/it/ITPipelineTest.java

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import static com.google.cloud.firestore.pipeline.expressions.Expression.notEqual;
7373
import static com.google.cloud.firestore.pipeline.expressions.Expression.nullValue;
7474
import static com.google.cloud.firestore.pipeline.expressions.Expression.or;
75+
import static com.google.cloud.firestore.pipeline.expressions.Expression.parent;
7576
import static com.google.cloud.firestore.pipeline.expressions.Expression.pow;
7677
import static com.google.cloud.firestore.pipeline.expressions.Expression.rand;
7778
import static com.google.cloud.firestore.pipeline.expressions.Expression.regexMatch;
@@ -109,6 +110,7 @@
109110
import com.google.cloud.Timestamp;
110111
import com.google.cloud.firestore.Blob;
111112
import com.google.cloud.firestore.CollectionReference;
113+
import com.google.cloud.firestore.DocumentReference;
112114
import com.google.cloud.firestore.Firestore;
113115
import com.google.cloud.firestore.FirestoreOptions;
114116
import com.google.cloud.firestore.GeoPoint;
@@ -2295,7 +2297,7 @@ public void testChecks() throws Exception {
22952297
.select(
22962298
field("rating").equal(nullValue()).as("ratingIsNull"),
22972299
field("rating").equal(Double.NaN).as("ratingIsNaN"),
2298-
// arrayGet("title", 0) evaluates to UNSET so it is not an error
2300+
// arrayGet("title", 0) evaluates to ERROR
22992301
arrayGet("title", 0).isError().as("isError"),
23002302
arrayGet("title", 0).ifError(constant("was error")).as("ifError"),
23012303
field("foo").isAbsent().as("isAbsent"),
@@ -2316,7 +2318,9 @@ public void testChecks() throws Exception {
23162318
"ratingIsNaN",
23172319
false,
23182320
"isError",
2319-
false,
2321+
true,
2322+
"ifError",
2323+
"was error",
23202324
"isAbsent",
23212325
true,
23222326
"titleIsNotNull",
@@ -3621,8 +3625,8 @@ public void testNestedFields() throws Exception {
36213625
assertThat(data(results))
36223626
.isEqualTo(
36233627
Lists.newArrayList(
3624-
map("title", "The Hitchhiker's Guide to the Galaxy", "awards.hugo", true),
3625-
map("title", "Dune", "awards.hugo", true)));
3628+
map("title", "The Hitchhiker's Guide to the Galaxy", "awards", map("hugo", true)),
3629+
map("title", "Dune", "awards", map("hugo", true))));
36263630
}
36273631

36283632
@Test
@@ -3645,8 +3649,12 @@ public void testPipelineInTransactions() throws Exception {
36453649
assertThat(data(results))
36463650
.isEqualTo(
36473651
Lists.newArrayList(
3648-
map("title", "The Hitchhiker's Guide to the Galaxy", "awards.hugo", true),
3649-
map("title", "Dune", "awards.hugo", true)));
3652+
map(
3653+
"title",
3654+
"The Hitchhiker's Guide to the Galaxy",
3655+
"awards",
3656+
map("hugo", true)),
3657+
map("title", "Dune", "awards", map("hugo", true))));
36503658

36513659
transaction.update(collection.document("book1"), map("foo", "bar"));
36523660

@@ -4378,4 +4386,29 @@ public void disallowDuplicateAliasesAcrossStages() {
43784386
});
43794387
assertThat(exception).hasMessageThat().contains("Duplicate alias or field name");
43804388
}
4389+
4390+
@Test
4391+
public void testSupportsParent() throws Exception {
4392+
DocumentReference docRef =
4393+
collection.document("book4").collection("reviews").document("review1");
4394+
4395+
Pipeline pipeline =
4396+
firestore
4397+
.pipeline()
4398+
.collection(collection.getPath())
4399+
.limit(1)
4400+
.select(
4401+
parent(docRef).as("parentRefStatic"),
4402+
constant(docRef).parent().as("parentRefInstance"))
4403+
.select(
4404+
field("parentRefStatic").documentId().as("parentIdStatic"),
4405+
field("parentRefInstance").documentId().as("parentIdInstance"));
4406+
4407+
List<PipelineResult> results = pipeline.execute().get().getResults();
4408+
assertThat(results).hasSize(1);
4409+
Map<String, Object> data = results.get(0).getData();
4410+
4411+
assertThat(data.get("parentIdStatic")).isEqualTo("book4");
4412+
assertThat(data.get("parentIdInstance")).isEqualTo("book4");
4413+
}
43814414
}

0 commit comments

Comments
 (0)