Search: Omit full text index if query is too short #1517
This commit is contained in:
parent
79961ec11b
commit
0f90258ef9
10 changed files with 52 additions and 10 deletions
|
@ -15,6 +15,8 @@ import (
|
||||||
geojson "github.com/paulmach/go.geojson"
|
geojson "github.com/paulmach/go.geojson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetGeo performs a geo search with reduced metadata details for improved performance.
|
||||||
|
//
|
||||||
// GET /api/v1/geo
|
// GET /api/v1/geo
|
||||||
func GetGeo(router *gin.RouterGroup) {
|
func GetGeo(router *gin.RouterGroup) {
|
||||||
router.GET("/geo", func(c *gin.Context) {
|
router.GET("/geo", func(c *gin.Context) {
|
||||||
|
@ -37,7 +39,8 @@ func GetGeo(router *gin.RouterGroup) {
|
||||||
photos, err := query.Geo(f)
|
photos, err := query.Geo(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithStatusJSON(400, gin.H{"error": txt.UcFirst(err.Error())})
|
log.Warnf("search: %s", err)
|
||||||
|
AbortBadRequest(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ func GetPhotos(router *gin.RouterGroup) {
|
||||||
result, count, err := query.PhotoSearch(f)
|
result, count, err := query.PhotoSearch(f)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
log.Warnf("search: %s", err)
|
||||||
AbortBadRequest(c)
|
AbortBadRequest(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,5 +59,5 @@ func Msg(id Message, params ...interface{}) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Error(id Message, params ...interface{}) error {
|
func Error(id Message, params ...interface{}) error {
|
||||||
return errors.New(Msg(id, params...))
|
return errors.New(strings.ToLower(Msg(id, params...)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,20 +58,20 @@ func TestMsg(t *testing.T) {
|
||||||
func TestError(t *testing.T) {
|
func TestError(t *testing.T) {
|
||||||
t.Run("already exists", func(t *testing.T) {
|
t.Run("already exists", func(t *testing.T) {
|
||||||
err := Error(ErrAlreadyExists, "A cat")
|
err := Error(ErrAlreadyExists, "A cat")
|
||||||
assert.EqualError(t, err, "A cat already exists")
|
assert.EqualError(t, err, "a cat already exists")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unexpected error", func(t *testing.T) {
|
t.Run("unexpected error", func(t *testing.T) {
|
||||||
err := Error(ErrUnexpected, "A cat")
|
err := Error(ErrUnexpected, "A cat")
|
||||||
assert.EqualError(t, err, "Unexpected error, please try again")
|
assert.EqualError(t, err, "unexpected error, please try again")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("already exists german", func(t *testing.T) {
|
t.Run("already exists german", func(t *testing.T) {
|
||||||
SetLocale("de")
|
SetLocale("de")
|
||||||
errGerman := Error(ErrAlreadyExists, "Eine Katze")
|
errGerman := Error(ErrAlreadyExists, "Eine Katze")
|
||||||
assert.EqualError(t, errGerman, "Eine Katze existiert bereits")
|
assert.EqualError(t, errGerman, "eine katze existiert bereits")
|
||||||
SetLocale("")
|
SetLocale("")
|
||||||
errDefault := Error(ErrAlreadyExists, "A cat")
|
errDefault := Error(ErrAlreadyExists, "A cat")
|
||||||
assert.EqualError(t, errDefault, "A cat already exists")
|
assert.EqualError(t, errDefault, "a cat already exists")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,10 @@ func Geo(f form.GeoSearch) (results GeoResults, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set search filters based on search terms.
|
// Set search filters based on search terms.
|
||||||
if terms := txt.SearchTerms(f.Query); len(terms) > 0 {
|
if terms := txt.SearchTerms(f.Query); f.Query != "" && len(terms) == 0 {
|
||||||
|
f.Name = fs.StripKnownExt(f.Query) + "*"
|
||||||
|
f.Query = ""
|
||||||
|
} else if len(terms) > 0 {
|
||||||
switch {
|
switch {
|
||||||
case terms["faces"]:
|
case terms["faces"]:
|
||||||
f.Query = strings.ReplaceAll(f.Query, "faces", "")
|
f.Query = strings.ReplaceAll(f.Query, "faces", "")
|
||||||
|
|
|
@ -23,6 +23,13 @@ func NormalizeSearchQuery(s string) string {
|
||||||
return strings.Trim(s, "+&|_-=!@$%^(){}\\<>,.;: ")
|
return strings.Trim(s, "+&|_-=!@$%^(){}\\<>,.;: ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsTooShort tests if a search query is too short.
|
||||||
|
func IsTooShort(q string) bool {
|
||||||
|
q = strings.Trim(q, "- '")
|
||||||
|
|
||||||
|
return q != "" && len(q) < 3 && txt.IsLatin(q)
|
||||||
|
}
|
||||||
|
|
||||||
// LikeAny returns a single where condition matching the search words.
|
// LikeAny returns a single where condition matching the search words.
|
||||||
func LikeAny(col, s string, keywords, exact bool) (wheres []string) {
|
func LikeAny(col, s string, keywords, exact bool) (wheres []string) {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
|
|
|
@ -13,6 +13,21 @@ func TestNormalizeSearchQuery(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIsTooShort(t *testing.T) {
|
||||||
|
t.Run("Empty", func(t *testing.T) {
|
||||||
|
assert.False(t, IsTooShort(""))
|
||||||
|
})
|
||||||
|
t.Run("IsTooShort", func(t *testing.T) {
|
||||||
|
assert.True(t, IsTooShort("aa"))
|
||||||
|
})
|
||||||
|
t.Run("Chinese", func(t *testing.T) {
|
||||||
|
assert.False(t, IsTooShort("李"))
|
||||||
|
})
|
||||||
|
t.Run("OK", func(t *testing.T) {
|
||||||
|
assert.False(t, IsTooShort("foo"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestLikeAny(t *testing.T) {
|
func TestLikeAny(t *testing.T) {
|
||||||
t.Run("and_or_search", func(t *testing.T) {
|
t.Run("and_or_search", func(t *testing.T) {
|
||||||
if w := LikeAny("k.keyword", "table spoon & usa | img json", true, false); len(w) != 2 {
|
if w := LikeAny("k.keyword", "table spoon & usa | img json", true, false); len(w) != 2 {
|
||||||
|
|
|
@ -145,7 +145,10 @@ func PhotoSearch(f form.PhotoSearch) (results PhotoResults, count int, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set search filters based on search terms.
|
// Set search filters based on search terms.
|
||||||
if terms := txt.SearchTerms(f.Query); len(terms) > 0 {
|
if terms := txt.SearchTerms(f.Query); f.Query != "" && len(terms) == 0 {
|
||||||
|
f.Name = fs.StripKnownExt(f.Query) + "*"
|
||||||
|
f.Query = ""
|
||||||
|
} else if len(terms) > 0 {
|
||||||
switch {
|
switch {
|
||||||
case terms["faces"]:
|
case terms["faces"]:
|
||||||
f.Query = strings.ReplaceAll(f.Query, "faces", "")
|
f.Query = strings.ReplaceAll(f.Query, "faces", "")
|
||||||
|
|
|
@ -11,6 +11,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPhotoSearch(t *testing.T) {
|
func TestPhotoSearch(t *testing.T) {
|
||||||
|
t.Run("Chinese", func(t *testing.T) {
|
||||||
|
var frm form.PhotoSearch
|
||||||
|
|
||||||
|
frm.Query = "张"
|
||||||
|
frm.Count = 10
|
||||||
|
frm.Offset = 0
|
||||||
|
|
||||||
|
_, _, err := PhotoSearch(frm)
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
t.Run("search all", func(t *testing.T) {
|
t.Run("search all", func(t *testing.T) {
|
||||||
var frm form.PhotoSearch
|
var frm form.PhotoSearch
|
||||||
|
|
||||||
|
|
|
@ -214,7 +214,7 @@ func SearchTerms(s string) map[string]bool {
|
||||||
for _, w := range KeywordsRegexp.FindAllString(s, -1) {
|
for _, w := range KeywordsRegexp.FindAllString(s, -1) {
|
||||||
w = strings.Trim(w, "- '")
|
w = strings.Trim(w, "- '")
|
||||||
|
|
||||||
if w == "" || len(w) < 2 && IsLatin(w) {
|
if w == "" || len(w) < 3 && IsLatin(w) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue