Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -3583,6 +3583,41 @@ public static Expression type(String fieldName) {
return type(field(fieldName));
}

/**
* Creates an expression that checks if the result of an expression is of the given type.
*
* <p>Supported values for {@code type} are: "null", "array", "boolean", "bytes", "timestamp",
* "geo_point", "number", "int32", "int64", "float64", "decimal128", "map", "reference", "string",
* "vector", "max_key", "min_key", "object_id", "regex", and "request_timestamp".
*
* @param expr The expression to check the type of.
* @param type The type to check for.
* @return A new {@link BooleanExpression} that evaluates to true if the expression's result is of
* the given type, false otherwise.
*/
@BetaApi
public static BooleanExpression isType(Expression expr, String type) {
return new BooleanFunctionExpression("is_type", ImmutableList.of(expr, constant(type)));
}

/**
* Creates an expression that checks if the value of a field is of the given type.
*
* <p>Supported values for {@code type} are: "null", "array", "boolean", "bytes", "timestamp",
* "geo_point", "number", "int32", "int64", "float64", "decimal128", "map", "reference", "string",
* "vector", "max_key", "min_key", "object_id", "regex", and "request_timestamp".
*
* @param fieldName The name of the field to check the type of.
* @param type The type to check for.
* @return A new {@link BooleanExpression} that evaluates to true if the expression's result is of
* the given type, false otherwise.
*/
@BetaApi
public static BooleanExpression isType(String fieldName, String type) {
return new BooleanFunctionExpression(
"is_type", ImmutableList.of(field(fieldName), constant(type)));
}

// Numeric Operations
/**
* Creates an expression that rounds {@code numericExpr} to nearest integer.
Expand Down Expand Up @@ -5629,4 +5664,20 @@ public final Expression collectionId() {
public final Expression type() {
return type(this);
}

/**
* Creates an expression that checks if the result of this expression is of the given type.
*
* <p>Supported values for {@code type} are: "null", "array", "boolean", "bytes", "timestamp",
* "geo_point", "number", "int32", "int64", "float64", "decimal128", "map", "reference", "string",
* "vector", "max_key", "min_key", "object_id", "regex", and "request_timestamp".
*
* @param type The type to check for.
* @return A new {@link BooleanExpression} that evaluates to true if the expression's result is of
* the given type, false otherwise.
*/
@BetaApi
public final BooleanExpression isType(String type) {
return isType(this, type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3500,6 +3500,89 @@ public void testType() throws Exception {
"vector"));
}

@Test
public void testIsType() throws Exception {
List<PipelineResult> results =
firestore
.pipeline()
.collection(collection.getPath())
.replaceWith(
Expression.map(
map(
"int",
1,
"float",
1.1,
"str",
"a string",
"bool",
true,
"null",
null,
"geoPoint",
new GeoPoint(0.1, 0.2),
"timestamp",
Timestamp.ofTimeSecondsAndNanos(123456, 0),
"bytes",
com.google.cloud.firestore.Blob.fromBytes(new byte[] {1, 2, 3}),
"docRef",
collection.document("bar"),
"vector",
vector(new double[] {1.0, 2.0, 3.0}),
"map",
Expression.map(map("numberK", 1, "stringK", "a string")),
"array",
array(1, 2, true))))
.select(
Expression.isType("int", "int64").as("isInt64"),
Expression.isType("int", "number").as("isInt64IsNumber"),
Expression.isType("int", "decimal128").as("isInt64IsDecimal128"),
Expression.isType("float", "float64").as("isFloat64"),
Expression.isType("float", "number").as("isFloat64IsNumber"),
Expression.isType("float", "decimal128").as("isFloat64IsDecimal128"),
Expression.isType("str", "string").as("isStr"),
Expression.isType("str", "int64").as("isStrNum"),
Expression.isType("int", "string").as("isNumStr"),
Expression.isType("bool", "boolean").as("isBool"),
Expression.isType("null", "null").as("isNull"),
Expression.isType("geoPoint", "geo_point").as("isGeoPoint"),
Expression.isType("timestamp", "timestamp").as("isTimestamp"),
Expression.isType("bytes", "bytes").as("isBytes"),
Expression.isType("docRef", "reference").as("isDocRef"),
Expression.isType("vector", "vector").as("isVector"),
Expression.isType("map", "map").as("isMap"),
Expression.isType("array", "array").as("isArray"),
Expression.isType(constant(1), "int64").as("exprIsInt64"),
field("int").isType("int64").as("staticIsInt64"))
.limit(1)
.execute()
.get()
.getResults();
assertThat(data(results))
.containsExactly(
map(
"isInt64", true,
"isInt64IsNumber", true,
"isInt64IsDecimal128", false,
"isFloat64", true,
"isFloat64IsNumber", true,
"isFloat64IsDecimal128", false,
"isStr", true,
"isStrNum", false,
"isNumStr", false,
"isBool", true,
"isNull", true,
"isGeoPoint", true,
"isTimestamp", true,
"isBytes", true,
"isDocRef", true,
"isVector", true,
"isMap", true,
"isArray", true,
"exprIsInt64", true,
"staticIsInt64", true));
}

@Test
public void testExplainWithError() {
assumeFalse(
Expand Down
Loading