diff --git a/go.mod b/go.mod index 698bcb841..98e9e0eb3 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/gosimple/slug v1.9.0 github.com/jinzhu/gorm v1.9.12 + github.com/jinzhu/inflection v1.0.0 github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect github.com/karrick/godirwalk v1.15.6 github.com/kr/pretty v0.1.0 // indirect diff --git a/internal/query/query.go b/internal/query/query.go index b0d432a17..55774819c 100644 --- a/internal/query/query.go +++ b/internal/query/query.go @@ -16,6 +16,7 @@ import ( "github.com/photoprism/photoprism/internal/event" "github.com/photoprism/photoprism/pkg/txt" + "github.com/jinzhu/inflection" "github.com/jinzhu/gorm" ) @@ -58,11 +59,6 @@ func UnscopedDb() *gorm.DB { return entity.Db().Unscoped() } -// IsDialect returns true if the given sql dialect is used. -func IsDialect(name string) bool { - return name == Db().Dialect().GetName() -} - // DbDialect returns the sql dialect name. func DbDialect() string { return Db().Dialect().GetName() @@ -84,6 +80,12 @@ func LikeAny(col, search string) (where string) { } else { wheres = append(wheres, fmt.Sprintf("%s = '%s'", col, w)) } + + singular := inflection.Singular(w) + + if singular != w { + wheres = append(wheres, fmt.Sprintf("%s = '%s'", col, singular)) + } } return strings.Join(wheres, " OR ") @@ -103,7 +105,15 @@ func AnySlug(col, search, sep string) (where string) { var words []string for _, w := range strings.Split(search, sep) { - words = append(words, slug.Make(strings.TrimSpace(w))) + w = strings.TrimSpace(w) + + words = append(words, slug.Make(w)) + + singular := inflection.Singular(w) + + if singular != w { + words = append(words, slug.Make(singular)) + } } if len(words) == 0 { diff --git a/internal/query/query_test.go b/internal/query/query_test.go index 1d23061ed..633742582 100644 --- a/internal/query/query_test.go +++ b/internal/query/query_test.go @@ -32,6 +32,11 @@ func TestLikeAny(t *testing.T) { assert.Equal(t, "k.keyword = 'cat' OR k.keyword = 'dog'", where) }) + t.Run("cats dogs", func(t *testing.T) { + where := LikeAny("k.keyword", "cats dogs") + assert.Equal(t, "k.keyword LIKE 'cats%' OR k.keyword = 'cat' OR k.keyword LIKE 'dogs%' OR k.keyword = 'dog'", where) + }) + t.Run("spoon", func(t *testing.T) { where := LikeAny("k.keyword", "spoon") assert.Equal(t, "k.keyword LIKE 'spoon%'", where) @@ -59,6 +64,11 @@ func TestAnySlug(t *testing.T) { assert.Equal(t, "custom_slug = 'cat' OR custom_slug = 'dog'", where) }) + t.Run("cats dogs", func(t *testing.T) { + where := AnySlug("custom_slug", "cats dogs", " ") + assert.Equal(t, "custom_slug = 'cats' OR custom_slug = 'cat' OR custom_slug = 'dogs' OR custom_slug = 'dog'", where) + }) + t.Run("spoon", func(t *testing.T) { where := AnySlug("custom_slug", "spoon", " ") assert.Equal(t, "custom_slug = 'spoon'", where)