Skip to content
Merged
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
2 changes: 1 addition & 1 deletion firestore/pipeline_constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func ConstantOf(value any) Expr {

// Handle known scalar types
switch value.(type) {
case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, float32, float64, time.Time, *ts.Timestamp, []byte, Vector32, Vector64, *latlng.LatLng:
case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, float32, float64, time.Time, *ts.Timestamp, []byte, Vector32, Vector64, bool, *latlng.LatLng, *DocumentRef:
pbVal, _, err := toProtoValue(reflect.ValueOf(value))
if err != nil {
return &constant{baseExpr: &baseExpr{err: err}}
Expand Down
87 changes: 87 additions & 0 deletions firestore/pipeline_expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ type Expr interface {
Round() Expr
Sqrt() Expr

// Array operations
ArrayContains(value any) BooleanExpr
ArrayContainsAll(values any) BooleanExpr
ArrayContainsAny(values any) BooleanExpr
ArrayLength() Expr
EqualAny(values any) BooleanExpr
NotEqualAny(values any) BooleanExpr
ArrayGet(offset any) Expr
ArrayReverse() Expr
ArrayConcat(otherArrays ...any) Expr
ArraySum() Expr
ArrayMaximum() Expr
ArrayMinimum() Expr

// Timestamp operations
TimestampAdd(unit, amount any) Expr
TimestampSubtract(unit, amount any) Expr
Expand All @@ -85,6 +99,35 @@ type Expr interface {
Average() AggregateFunction
Count() AggregateFunction

// String functions
ByteLength() Expr
CharLength() Expr
EndsWith(suffix any) BooleanExpr
Like(suffix any) BooleanExpr
RegexContains(pattern any) BooleanExpr
RegexMatch(pattern any) BooleanExpr
StartsWith(prefix any) BooleanExpr
StringConcat(otherStrings ...any) Expr
StringContains(substring any) BooleanExpr
StringReverse() Expr
Join(separator any) Expr
Substring(index, offset any) Expr
ToLower() Expr
ToUpper() Expr
Trim() Expr

// Type functions
IsNaN() BooleanExpr
IsNotNaN() BooleanExpr
IsNull() BooleanExpr
IsNotNull() BooleanExpr

// Vector functions
CosineDistance(other any) Expr
DotProduct(other any) Expr
EuclideanDistance(other any) Expr
VectorLength() Expr

// Ordering
Ascending() Ordering
Descending() Ordering
Expand Down Expand Up @@ -121,6 +164,20 @@ func (b *baseExpr) Pow(other any) Expr { return Pow(b, other) }
func (b *baseExpr) Round() Expr { return Round(b) }
func (b *baseExpr) Sqrt() Expr { return Sqrt(b) }

// Array functions
func (b *baseExpr) ArrayContains(value any) BooleanExpr { return ArrayContains(b, value) }
func (b *baseExpr) ArrayContainsAll(values any) BooleanExpr { return ArrayContainsAll(b, values) }
func (b *baseExpr) ArrayContainsAny(values any) BooleanExpr { return ArrayContainsAny(b, values) }
func (b *baseExpr) ArrayLength() Expr { return ArrayLength(b) }
func (b *baseExpr) EqualAny(values any) BooleanExpr { return EqualAny(b, values) }
func (b *baseExpr) NotEqualAny(values any) BooleanExpr { return NotEqualAny(b, values) }
func (b *baseExpr) ArrayGet(offset any) Expr { return ArrayGet(b, offset) }
func (b *baseExpr) ArrayReverse() Expr { return ArrayReverse(b) }
func (b *baseExpr) ArrayConcat(otherArrays ...any) Expr { return ArrayConcat(b, otherArrays...) }
func (b *baseExpr) ArraySum() Expr { return ArraySum(b) }
func (b *baseExpr) ArrayMaximum() Expr { return ArrayMaximum(b) }
func (b *baseExpr) ArrayMinimum() Expr { return ArrayMinimum(b) }

// Timestamp functions
func (b *baseExpr) TimestampAdd(unit, amount any) Expr { return TimestampAdd(b, unit, amount) }
func (b *baseExpr) TimestampSubtract(unit, amount any) Expr {
Expand Down Expand Up @@ -151,9 +208,39 @@ func (b *baseExpr) CountIf() AggregateFunction { return CountIf(b) }
func (b *baseExpr) Maximum() AggregateFunction { return Maximum(b) }
func (b *baseExpr) Minimum() AggregateFunction { return Minimum(b) }

// String functions
func (b *baseExpr) ByteLength() Expr { return ByteLength(b) }
func (b *baseExpr) CharLength() Expr { return CharLength(b) }
func (b *baseExpr) EndsWith(suffix any) BooleanExpr { return EndsWith(b, suffix) }
func (b *baseExpr) Like(suffix any) BooleanExpr { return Like(b, suffix) }
func (b *baseExpr) RegexContains(pattern any) BooleanExpr { return RegexContains(b, pattern) }
func (b *baseExpr) RegexMatch(pattern any) BooleanExpr { return RegexMatch(b, pattern) }
func (b *baseExpr) StartsWith(prefix any) BooleanExpr { return StartsWith(b, prefix) }
func (b *baseExpr) StringConcat(otherStrings ...any) Expr { return StringConcat(b, otherStrings...) }
func (b *baseExpr) StringContains(substring any) BooleanExpr { return StringContains(b, substring) }
func (b *baseExpr) StringReverse() Expr { return StringReverse(b) }
func (b *baseExpr) Join(separator any) Expr { return Join(b, separator) }
func (b *baseExpr) Substring(index, offset any) Expr { return Substring(b, index, offset) }
func (b *baseExpr) ToLower() Expr { return ToLower(b) }
func (b *baseExpr) ToUpper() Expr { return ToUpper(b) }
func (b *baseExpr) Trim() Expr { return Trim(b) }

// Type functions
func (b *baseExpr) IsNaN() BooleanExpr { return IsNaN(b) }
func (b *baseExpr) IsNotNaN() BooleanExpr { return IsNotNaN(b) }
func (b *baseExpr) IsNull() BooleanExpr { return IsNull(b) }
func (b *baseExpr) IsNotNull() BooleanExpr { return IsNotNull(b) }

// Vector functions
func (b *baseExpr) CosineDistance(other any) Expr { return CosineDistance(b, other) }
func (b *baseExpr) DotProduct(other any) Expr { return DotProduct(b, other) }
func (b *baseExpr) EuclideanDistance(other any) Expr { return EuclideanDistance(b, other) }
func (b *baseExpr) VectorLength() Expr { return VectorLength(b) }

// Ordering
func (b *baseExpr) Ascending() Ordering { return Ascending(b) }
func (b *baseExpr) Descending() Ordering { return Descending(b) }

func (b *baseExpr) As(alias string) Selectable {
return newAliasedExpr(b, alias)
}
Expand Down
180 changes: 180 additions & 0 deletions firestore/pipeline_filter_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,66 @@ func (b *baseBooleanExpr) isBooleanExpr() {}
// Ensure that baseBooleanExpr implements the BooleanExpr interface.
var _ BooleanExpr = (*baseBooleanExpr)(nil)

// ArrayContains creates an expression that checks if an array contains a specified element.
// - exprOrFieldPath can be a field path string, [FieldPath] or an [Expr] that evaluates to an array.
// - value is the element to check for.
//
// Example:
//
// // Check if the 'tags' array contains "Go".
// ArrayContains("tags", "Go")
func ArrayContains(exprOrFieldPath any, value any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("array_contains", []Expr{toExprOrField(exprOrFieldPath), toExprOrConstant(value)})}
Comment thread
bhshkh marked this conversation as resolved.
}

// ArrayContainsAll creates an expression that checks if an array contains all of the provided values.
// - exprOrFieldPath can be a field path string, [FieldPath] or an [Expr] that evaluates to an array.
// - values can be an array of values or an expression that evaluates to an array.
//
// Example:
//
// // Check if the 'tags' array contains both "Go" and "Firestore".
Comment thread
bhshkh marked this conversation as resolved.
// ArrayContainsAll("tags", []string{"Go", "Firestore"})
func ArrayContainsAll(exprOrFieldPath any, values any) BooleanExpr {
return newFieldAndArrayBooleanExpr("array_contains_all", exprOrFieldPath, values)
}

// ArrayContainsAny creates an expression that checks if an array contains any of the provided values.
// - exprOrFieldPath can be a field path string, [FieldPath] or an [Expr] that evaluates to an array.
// - values can be an array of values or an expression that evaluates to an array.
//
// Example:
//
// // Check if the 'tags' array contains either "Go" or "Firestore".
// ArrayContainsAny("tags", []string{"Go", "Firestore"})
func ArrayContainsAny(exprOrFieldPath any, values any) BooleanExpr {
return newFieldAndArrayBooleanExpr("array_contains_any", exprOrFieldPath, values)
}

// EqualAny creates an expression that checks if a field or expression is equal to any of the provided values.
// - exprOrFieldPath can be a field path string, [FieldPath] or an [Expr].
// - values can be an array of values or an expression that evaluates to an array.
//
// Example:
//
// // Check if the 'status' field is either "active" or "pending".
// EqualAny("status", []string{"active", "pending"})
func EqualAny(exprOrFieldPath any, values any) BooleanExpr {
return newFieldAndArrayBooleanExpr("equal_any", exprOrFieldPath, values)
}

// NotEqualAny creates an expression that checks if a field or expression is not equal to any of the provided values.
// - exprOrFieldPath can be a field path string, [FieldPath] or an [Expr].
// - values can be an array of values or an expression that evaluates to an array.
//
// Example:
//
// // Check if the 'status' field is not "archived" or "deleted".
// NotEqualAny("status", []string{"archived", "deleted"})
func NotEqualAny(exprOrFieldPath any, values any) BooleanExpr {
return newFieldAndArrayBooleanExpr("not_equal_any", exprOrFieldPath, values)
}

// Equal creates an expression that checks if field's value or an expression is equal to an expression or a constant value,
// returning it as a BooleanExpr.
// - left: The field path string, [FieldPath] or [Expr] to compare.
Expand Down Expand Up @@ -171,3 +231,123 @@ func LessThanOrEqual(left, right any) BooleanExpr {
func Equivalent(left, right any) BooleanExpr {
return &baseBooleanExpr{baseFunction: leftRightToBaseFunction("equivalent", left, right)}
}

// EndsWith creates an expression that checks if a string field or expression ends with a given suffix.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - suffix string or [Expr] to check for.
//
// Example:
//
// // Check if the 'filename' field ends with ".go".
// EndsWith("filename", ".go")
func EndsWith(exprOrFieldPath any, suffix any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("ends_with", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(suffix)})}
}

// Like creates an expression that performs a case-sensitive wildcard string comparison.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - pattern string or [Expr] to search for. You can use "%" as a wildcard character.
//
// Example:
//
// // Check if the 'name' field starts with "G".
// Like("name", "G%")
func Like(exprOrFieldPath any, pattern any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("like", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(pattern)})}
}

// RegexContains creates an expression that checks if a string contains a match for a regular expression.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - pattern is the regular expression to search for.
//
// Example:
//
// // Check if the 'email' field contains a gmail address.
// RegexContains("email", "@gmail\\.com$")
func RegexContains(exprOrFieldPath any, pattern any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("regex_contains", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(pattern)})}
}

// RegexMatch creates an expression that checks if a string matches a regular expression.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - pattern is the regular expression to match against.
//
// Example:
//
// // Check if the 'zip_code' field is a 5-digit number.
// RegexMatch("zip_code", "^[0-9]{5}$")
func RegexMatch(exprOrFieldPath any, pattern any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("regex_match", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(pattern)})}
}

// StartsWith creates an expression that checks if a string field or expression starts with a given prefix.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - prefix string or [Expr] to check for.
//
// Example:
//
// // Check if the 'name' field starts with "Mr.".
// StartsWith("name", "Mr.")
func StartsWith(exprOrFieldPath any, prefix any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("starts_with", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(prefix)})}
}

// StringContains creates an expression that checks if a string contains a specified substring.
// - exprOrFieldPath can be a field path string, [FieldPath] or [Expr].
// - substring is the string to search for.
//
// Example:
//
// // Check if the 'description' field contains the word "Firestore".
// StringContains("description", "Firestore")
func StringContains(exprOrFieldPath any, substring any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("string_contains", []Expr{toExprOrField(exprOrFieldPath), asStringExpr(substring)})}
}

// IsNaN creates a boolean expression that checks if a field or expression evaluates to NaN.
//
// exprOrFieldPath is the field path string, [FieldPath] or [Expr] that will be evaluated.
//
// Example:
//
// // Check if the 'score' field is NaN.
// IsNaN("score")
func IsNaN(exprOrFieldPath any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("is_nan", []Expr{toExprOrField(exprOrFieldPath)})}
}

// IsNotNaN creates a boolean expression that checks if a field or expression does not evaluate to NaN.
//
// exprOrFieldPath is the field path string, [FieldPath] or [Expr] that will be evaluated.
//
// Example:
//
// // Check if the 'score' field is not NaN.
// IsNotNaN("score")
func IsNotNaN(exprOrFieldPath any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("is_not_nan", []Expr{toExprOrField(exprOrFieldPath)})}
}

// IsNull creates a boolean expression that checks if a field or expression evaluates to null.
//
// exprOrFieldPath is the field path string, [FieldPath] or [Expr] that will be evaluated.
//
// Example:
//
// // Check if the 'address' field is null.
// IsNull("address")
func IsNull(exprOrFieldPath any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("is_null", []Expr{toExprOrField(exprOrFieldPath)})}
}

// IsNotNull creates a boolean expression that checks if a field or expression does not evaluate to null.
//
// exprOrFieldPath is the field path string, [FieldPath] or [Expr] that will be evaluated.
//
// Example:
//
// // Check if the 'address' field is not null.
// IsNotNull("address")
func IsNotNull(exprOrFieldPath any) BooleanExpr {
return &baseBooleanExpr{baseFunction: newBaseFunction("is_not_null", []Expr{toExprOrField(exprOrFieldPath)})}
}
Loading
Loading