Skip to content

Commit 508eb7a

Browse files
committed
Add exists to toPipeline()
1 parent 0c69e9f commit 508eb7a

File tree

6 files changed

+74
-27
lines changed

6 files changed

+74
-27
lines changed

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,32 +40,32 @@ public static Value encodeValue(Object value) {
4040
static FilterCondition toPipelineFilterCondition(FilterInternal f) {
4141
if (f instanceof ComparisonFilterInternal) {
4242
ComparisonFilterInternal comparisonFilter = (ComparisonFilterInternal) f;
43-
String fieldPath = comparisonFilter.fieldReference.getFieldPath();
43+
Field field = Field.of(comparisonFilter.fieldReference.getFieldPath());
4444
Value value = comparisonFilter.value;
4545
switch (comparisonFilter.operator) {
4646
case LESS_THAN:
47-
return Field.of(fieldPath).lt(value);
47+
return and(field.exists(), field.lt(value));
4848
case LESS_THAN_OR_EQUAL:
49-
return Field.of(fieldPath).lte(value);
49+
return and(field.exists(), field.lte(value));
5050
case GREATER_THAN:
51-
return Field.of(fieldPath).gt(value);
51+
return and(field.exists(), field.gt(value));
5252
case GREATER_THAN_OR_EQUAL:
53-
return Field.of(fieldPath).gte(value);
53+
return and(field.exists(), field.gte(value));
5454
case EQUAL:
55-
return Field.of(fieldPath).eq(value);
55+
return and(field.exists(), field.eq(value));
5656
case NOT_EQUAL:
57-
return not(Field.of(fieldPath).eq(value));
57+
return and(field.exists(), not(field.eq(value)));
5858
case ARRAY_CONTAINS:
59-
return Field.of(fieldPath).arrayContains(value);
59+
return and(field.exists(), field.arrayContains(value));
6060
case IN:
6161
List<Value> valuesList = value.getArrayValue().getValuesList();
62-
return inAny(Field.of(fieldPath), Lists.newArrayList(valuesList));
62+
return and(field.exists(), inAny(field, Lists.newArrayList(valuesList)));
6363
case ARRAY_CONTAINS_ANY:
6464
List<Value> valuesListAny = value.getArrayValue().getValuesList();
65-
return arrayContainsAny(Field.of(fieldPath), valuesListAny.toArray());
65+
return and(field.exists(), arrayContainsAny(field, valuesListAny.toArray()));
6666
case NOT_IN:
6767
List<Value> notInValues = value.getArrayValue().getValuesList();
68-
return not(inAny(Field.of(fieldPath), Lists.newArrayList(notInValues)));
68+
return and(field.exists(), not(inAny(field, Lists.newArrayList(notInValues))));
6969
default:
7070
// Handle OPERATOR_UNSPECIFIED and UNRECOGNIZED cases as needed
7171
throw new IllegalArgumentException("Unsupported operator: " + comparisonFilter.operator);
@@ -96,16 +96,16 @@ static FilterCondition toPipelineFilterCondition(FilterInternal f) {
9696
}
9797
} else if (f instanceof UnaryFilterInternal) {
9898
UnaryFilterInternal unaryFilter = (UnaryFilterInternal) f;
99-
String fieldPath = unaryFilter.fieldReference.getFieldPath();
99+
Field field = Field.of(unaryFilter.fieldReference.getFieldPath());
100100
switch (unaryFilter.getOperator()) {
101101
case IS_NAN:
102-
return Field.of(fieldPath).isNaN();
102+
return and(field.exists(), field.isNaN());
103103
case IS_NULL:
104-
return Field.of(fieldPath).isNull();
104+
return and(field.exists(), field.isNull());
105105
case IS_NOT_NAN:
106-
return not(Field.of(fieldPath).isNaN());
106+
return and(field.exists(), not(field.isNaN()));
107107
case IS_NOT_NULL:
108-
return not(Field.of(fieldPath).isNull());
108+
return and(field.exists(), not(field.isNull()));
109109
default:
110110
// Handle OPERATOR_UNSPECIFIED and UNRECOGNIZED cases as needed
111111
throw new IllegalArgumentException("Unsupported operator: " + unaryFilter.getOperator());

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

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import com.google.common.base.Preconditions;
5353
import com.google.common.collect.ImmutableList;
5454
import com.google.common.collect.ImmutableMap;
55+
import com.google.common.collect.Lists;
5556
import com.google.firestore.bundle.BundledQuery;
5657
import com.google.firestore.v1.Cursor;
5758
import com.google.firestore.v1.Document;
@@ -2139,6 +2140,9 @@ public Pipeline pipeline() {
21392140
ppl = ppl.where(toPipelineFilterCondition(f));
21402141
}
21412142

2143+
// Collecting implicit exists fields.
2144+
Set<Exists> exists = new HashSet<>();
2145+
21422146
// Projections
21432147
if (this.options.getFieldProjections() != null
21442148
&& !this.options.getFieldProjections().isEmpty()) {
@@ -2147,6 +2151,10 @@ public Pipeline pipeline() {
21472151
this.options.getFieldProjections().stream()
21482152
.map(fieldReference -> Field.of(fieldReference.getFieldPath()))
21492153
.toArray(Selectable[]::new));
2154+
exists.addAll(
2155+
this.options.getFieldProjections().stream()
2156+
.map(fieldReference -> Field.of(fieldReference.getFieldPath()).exists())
2157+
.collect(Collectors.toList()));
21502158
}
21512159

21522160
// Orders
@@ -2164,17 +2172,20 @@ public Pipeline pipeline() {
21642172
.collect(Collectors.toList());
21652173

21662174
// Add exists filters to match Query's implicit orderby semantics.
2167-
List<Exists> exists =
2175+
exists.addAll(
21682176
normalizedOrderbys.stream()
21692177
// .filter(order -> !order.fieldReference.getFieldPath().equals("__name__"))
21702178
.map(order -> Field.of(order.fieldReference.getFieldPath()).exists())
2171-
.collect(Collectors.toList());
2172-
if (exists.size() > 1) {
2179+
.collect(Collectors.toList()));
2180+
List<Exists> existsList = Lists.newArrayList(exists);
2181+
if (existsList.size() > 1) {
21732182
ppl =
21742183
ppl.where(
2175-
and(exists.get(0), exists.subList(1, exists.size()).toArray(new Exists[] {})));
2184+
and(
2185+
existsList.get(0),
2186+
existsList.subList(1, existsList.size()).toArray(new Exists[] {})));
21762187
} else if (exists.size() == 1) {
2177-
ppl = ppl.where(exists.get(0));
2188+
ppl = ppl.where(existsList.get(0));
21782189
}
21792190

21802191
ppl = ppl.sort(orders, Density.REQUIRED, Truncation.UNSPECIFIED);

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@BetaApi
88
public final class Exists extends Function implements FilterCondition {
99
@InternalApi
10-
Exists(Field field) {
11-
super("exists", Lists.newArrayList(field));
10+
Exists(Expr expr) {
11+
super("exists", Lists.newArrayList(expr));
1212
}
1313
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ default IsNaN isNaN() {
178178
return new IsNaN(this);
179179
}
180180

181+
@BetaApi
182+
default Exists exists() {
183+
return new Exists(this);
184+
}
185+
181186
@BetaApi
182187
default IsNull isNull() {
183188
return new IsNull(this);

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.google.api.core.InternalApi;
55
import com.google.cloud.firestore.FieldPath;
66
import com.google.cloud.firestore.Pipeline;
7+
import com.google.common.base.Objects;
78
import com.google.firestore.v1.Value;
89
import javax.annotation.Nullable;
910

@@ -30,9 +31,21 @@ public Value toProto() {
3031
return Value.newBuilder().setFieldReferenceValue(path.toString()).build();
3132
}
3233

33-
@BetaApi
34-
public Exists exists() {
35-
return new Exists(this);
34+
@Override
35+
public boolean equals(Object o) {
36+
if (this == o) {
37+
return true;
38+
}
39+
if (o == null || getClass() != o.getClass()) {
40+
return false;
41+
}
42+
Field field = (Field) o;
43+
return Objects.equal(path, field.path) && Objects.equal(pipeline, field.pipeline);
44+
}
45+
46+
@Override
47+
public int hashCode() {
48+
return Objects.hashCode(path, pipeline);
3649
}
3750

3851
@InternalApi

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.google.api.core.BetaApi;
66
import com.google.api.core.InternalApi;
77
import com.google.cloud.firestore.DocumentReference;
8+
import com.google.common.base.Objects;
89
import com.google.common.collect.Lists;
910
import com.google.firestore.v1.Value;
1011
import java.util.Arrays;
@@ -261,7 +262,7 @@ public static Exists exists(String field) {
261262
}
262263

263264
@BetaApi
264-
public static Exists exists(Field field) {
265+
public static Exists exists(Expr field) {
265266
return new Exists(field);
266267
}
267268

@@ -719,4 +720,21 @@ public static ArrayElement arrayElement() {
719720
public static Function function(String name, List<Expr> params) {
720721
return new Function(name, params);
721722
}
723+
724+
@Override
725+
public boolean equals(Object o) {
726+
if (this == o) {
727+
return true;
728+
}
729+
if (o == null || getClass() != o.getClass()) {
730+
return false;
731+
}
732+
Function function = (Function) o;
733+
return Objects.equal(name, function.name) && Objects.equal(params, function.params);
734+
}
735+
736+
@Override
737+
public int hashCode() {
738+
return Objects.hashCode(name, params);
739+
}
722740
}

0 commit comments

Comments
 (0)