Compare commits

...

1 Commits

Author SHA1 Message Date
Piyush Singariya
62fa98c546 feat: forced full text on body 2026-02-20 15:20:16 +05:30
4 changed files with 29 additions and 8 deletions

View File

@@ -45,8 +45,8 @@ func (c *conditionBuilder) conditionFor(
}
return cond, nil
} else if key.FieldDataType == telemetrytypes.FieldDataTypeJSON && !operator.IsOpValidForJSON() {
// Skip building condition for invalid operators on JSON columns
return "", nil
// throw error for invalid operators on JSON columns
return "", errors.NewInvalidInputf(errors.CodeInvalidInput, "invalid operator")
}
}

View File

@@ -40,7 +40,9 @@ const (
BodyV2ColumnPrefix = constants.BodyV2ColumnPrefix
BodyPromotedColumnPrefix = constants.BodyPromotedColumnPrefix
MessageSubColumn = "message"
ftsBodyFieldKey = "object(body)"
bodySearchDefaultWarning = "When you search on `body` (full text or by field), Query Builder uses body.message:string by default. Check that this matches what you want to search."
ftsBodyFieldWarning = "Avoid using `object(body)` in queries. It performs a full scan and can severely slow queries. Use explicit fields instead (for example, `body.response.status_code` or `response.status_code`). Only use `object(body)` for temporary schema exploration. We do not recommend its usage elsewhere."
)
var (
@@ -142,7 +144,7 @@ func bodyAliasExpression() string {
return fmt.Sprintf("%s as body", LogsV2BodyV2Column)
}
func init() {
func enrichIntrinsicFields() error {
// body logical field is mapped to message field in the body context that too only with String data type
err := BodyLogicalFieldJSONMapping.SetJSONAccessPlan(telemetrytypes.JSONColumnMetadata{
BaseColumn: LogsV2BodyV2Column,
@@ -151,11 +153,26 @@ func init() {
MessageSubColumn: {telemetrytypes.String},
})
if err != nil {
panic(err)
return err
}
if querybuilder.BodyJSONQueryEnabled {
DefaultFullTextColumn = BodyLogicalFieldJSONMapping
IntrinsicFields["body"] = *BodyLogicalFieldJSONMapping
IntrinsicFields[ftsBodyFieldKey] = telemetrytypes.TelemetryFieldKey{
Name: "body_v2",
Signal: telemetrytypes.SignalLogs,
FieldContext: telemetrytypes.FieldContextLog,
FieldDataType: telemetrytypes.FieldDataTypeJSON,
Warnings: []string{ftsBodyFieldWarning},
}
}
return nil
}
func init() {
err := enrichIntrinsicFields()
if err != nil {
panic(err)
}
}

View File

@@ -881,7 +881,7 @@ func testAddIndexedPaths(t *testing.T, statementBuilder *logQueryStatementBuilde
}
}
func jsonQueryTestUtil(_ *testing.T) (func(), func()) {
func jsonQueryTestUtil(t *testing.T) (func(), func()) {
querybuilder.BodyJSONQueryEnabled = true
base := telemetrytypes.TelemetryFieldKey{
Name: "body",
@@ -892,14 +892,16 @@ func jsonQueryTestUtil(_ *testing.T) (func(), func()) {
enable := func() {
querybuilder.BodyJSONQueryEnabled = true
DefaultFullTextColumn = BodyLogicalFieldJSONMapping
IntrinsicFields["body"] = *BodyLogicalFieldJSONMapping
err := enrichIntrinsicFields()
require.NoError(t, err)
}
disable := func() {
querybuilder.BodyJSONQueryEnabled = false
DefaultFullTextColumn = &base
IntrinsicFields["body"] = base
err := enrichIntrinsicFields()
require.NoError(t, err)
}
return enable, disable

View File

@@ -199,7 +199,9 @@ func (f FilterOperator) IsArrayOperator() bool {
func (f FilterOperator) IsOpValidForJSON() bool {
switch f {
case FilterOperatorExists, FilterOperatorNotExists, FilterOperatorContains, FilterOperatorNotContains:
case FilterOperatorExists, FilterOperatorNotExists,
FilterOperatorContains, FilterOperatorNotContains,
FilterOperatorRegexp, FilterOperatorNotRegexp:
return true
default:
return false