refactor(assistant): streamline JSON handling in query filters
- Introduced utility functions for applying LIKE conditions on JSON columns, enhancing compatibility with PostgreSQL. - Simplified the filtering logic for tags and keywords in the GetAssistants and DeleteAssistants methods. - Added unit tests for the new JSON handling functions to ensure correctness across different database drivers.
This commit is contained in:
parent
8786aa9a6a
commit
4b30e80924
3 changed files with 65 additions and 18 deletions
|
|
@ -319,25 +319,20 @@ func (store *Xun) GetAssistants(filter types.AssistantFilter, locale ...string)
|
|||
if len(filter.Tags) > 0 {
|
||||
qb.Where(func(qb query.Query) {
|
||||
for i, tag := range filter.Tags {
|
||||
// For each tag, we need to match it as part of a JSON array
|
||||
// This will match both single tag arrays ["tag1"] and multi-tag arrays ["tag1","tag2"]
|
||||
pattern := fmt.Sprintf("%%\"%s\"%%", tag)
|
||||
if i == 0 {
|
||||
qb.Where("tags", "like", pattern)
|
||||
} else {
|
||||
qb.OrWhere("tags", "like", pattern)
|
||||
}
|
||||
store.whereJsonLike(qb, "tags", pattern, i > 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Apply keyword filter if provided
|
||||
if filter.Keywords != "" {
|
||||
kw := fmt.Sprintf("%%%s%%", filter.Keywords)
|
||||
qb.Where(func(qb query.Query) {
|
||||
qb.Where("name", "like", fmt.Sprintf("%%%s%%", filter.Keywords)).
|
||||
OrWhere("description", "like", fmt.Sprintf("%%%s%%", filter.Keywords)).
|
||||
OrWhere("capabilities", "like", fmt.Sprintf("%%%s%%", filter.Keywords)).
|
||||
OrWhere("locales", "like", fmt.Sprintf("%%%s%%", filter.Keywords))
|
||||
qb.Where("name", "like", kw).
|
||||
OrWhere("description", "like", kw).
|
||||
OrWhere("capabilities", "like", kw)
|
||||
store.whereJsonLike(qb, "locales", kw, true)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -714,20 +709,17 @@ func (store *Xun) DeleteAssistants(filter types.AssistantFilter) (int64, error)
|
|||
qb.Where(func(qb query.Query) {
|
||||
for i, tag := range filter.Tags {
|
||||
pattern := fmt.Sprintf("%%\"%s\"%%", tag)
|
||||
if i == 0 {
|
||||
qb.Where("tags", "like", pattern)
|
||||
} else {
|
||||
qb.OrWhere("tags", "like", pattern)
|
||||
}
|
||||
store.whereJsonLike(qb, "tags", pattern, i > 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Apply keyword filter if provided
|
||||
if filter.Keywords != "" {
|
||||
kw := fmt.Sprintf("%%%s%%", filter.Keywords)
|
||||
qb.Where(func(qb query.Query) {
|
||||
qb.Where("name", "like", fmt.Sprintf("%%%s%%", filter.Keywords)).
|
||||
OrWhere("description", "like", fmt.Sprintf("%%%s%%", filter.Keywords))
|
||||
qb.Where("name", "like", kw).
|
||||
OrWhere("description", "like", kw)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -198,6 +198,35 @@ func (store *Xun) getDriver() string {
|
|||
return "mysql"
|
||||
}
|
||||
|
||||
// jsonLikeExpr returns a dialect-specific SQL expression for LIKE on a JSON column.
|
||||
// PostgreSQL requires casting json/jsonb to text before applying LIKE.
|
||||
func (store *Xun) jsonLikeExpr(column string) string {
|
||||
switch store.getDriver() {
|
||||
case "postgres":
|
||||
return fmt.Sprintf(`"%s"::text LIKE ?`, column)
|
||||
default:
|
||||
return column + " LIKE ?"
|
||||
}
|
||||
}
|
||||
|
||||
// whereJsonLike applies a LIKE condition on a JSON column with proper dialect handling.
|
||||
func (store *Xun) whereJsonLike(qb query.Query, column, pattern string, or bool) {
|
||||
if store.getDriver() == "postgres" {
|
||||
expr := fmt.Sprintf(`"%s"::text LIKE ?`, column)
|
||||
if or {
|
||||
qb.OrWhereRaw(expr, pattern)
|
||||
} else {
|
||||
qb.WhereRaw(expr, pattern)
|
||||
}
|
||||
} else {
|
||||
if or {
|
||||
qb.OrWhere(column, "like", pattern)
|
||||
} else {
|
||||
qb.Where(column, "like", pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GenerateAssistantID generates a random-looking 6-digit ID
|
||||
func (store *Xun) GenerateAssistantID() (string, error) {
|
||||
maxAttempts := 10 // Maximum number of attempts to generate a unique ID
|
||||
|
|
|
|||
|
|
@ -81,6 +81,32 @@ func TestSandboxRawSQLAllDialects(t *testing.T) {
|
|||
assert.Contains(t, isNull, "=")
|
||||
}
|
||||
|
||||
func TestJsonLikeExpr(t *testing.T) {
|
||||
test.Prepare(t, config.Conf)
|
||||
defer test.Clean()
|
||||
|
||||
store, err := NewXun(typeSetting("default"))
|
||||
assert.NoError(t, err)
|
||||
xunStore := store.(*Xun)
|
||||
|
||||
expr := xunStore.jsonLikeExpr("tags")
|
||||
assert.Contains(t, expr, "LIKE ?")
|
||||
|
||||
driver := xunStore.getDriver()
|
||||
switch driver {
|
||||
case "postgres":
|
||||
assert.Contains(t, expr, `"tags"::text`)
|
||||
default:
|
||||
assert.Equal(t, "tags LIKE ?", expr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonLikeExprFallback(t *testing.T) {
|
||||
store := &Xun{}
|
||||
expr := store.jsonLikeExpr("tags")
|
||||
assert.Equal(t, "tags LIKE ?", expr)
|
||||
}
|
||||
|
||||
func TestToDBTime(t *testing.T) {
|
||||
assert.Equal(t, int64(0), toDBTime(0))
|
||||
assert.Equal(t, int64(1234567890), toDBTime(1234567890))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue