Database: Improve config and SQL queries
This commit is contained in:
parent
40966c2add
commit
28880e682d
|
@ -73,7 +73,7 @@ func backupAction(ctx *cli.Context) error {
|
|||
var cmd *exec.Cmd
|
||||
|
||||
switch conf.DatabaseDriver() {
|
||||
case config.MySQL:
|
||||
case config.MySQL, config.MariaDB:
|
||||
cmd = exec.Command(
|
||||
conf.MysqldumpBin(),
|
||||
"-h", conf.DatabaseHost(),
|
||||
|
|
|
@ -101,7 +101,7 @@ func restoreAction(ctx *cli.Context) error {
|
|||
var cmd *exec.Cmd
|
||||
|
||||
switch conf.DatabaseDriver() {
|
||||
case config.MySQL:
|
||||
case config.MySQL, config.MariaDB:
|
||||
cmd = exec.Command(
|
||||
conf.MysqlBin(),
|
||||
"-h", conf.DatabaseHost(),
|
||||
|
|
|
@ -232,77 +232,93 @@ func (c *Config) UserConfig() ClientConfig {
|
|||
Server: NewRuntimeInfo(),
|
||||
}
|
||||
|
||||
c.Db().Table("photos").
|
||||
c.Db().
|
||||
Table("photos").
|
||||
Select("photo_uid, cell_id, photo_lat, photo_lng, taken_at").
|
||||
Where("deleted_at IS NULL AND photo_lat != 0 AND photo_lng != 0").
|
||||
Order("taken_at DESC").
|
||||
Limit(1).Offset(0).
|
||||
Take(&result.Pos)
|
||||
|
||||
c.Db().Table("cameras").
|
||||
c.Db().
|
||||
Table("cameras").
|
||||
Where("camera_slug <> 'zz' AND camera_slug <> ''").
|
||||
Select("COUNT(*) AS cameras").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("lenses").
|
||||
c.Db().
|
||||
Table("lenses").
|
||||
Where("lens_slug <> 'zz' AND lens_slug <> ''").
|
||||
Select("COUNT(*) AS lenses").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("photos").
|
||||
c.Db().
|
||||
Table("photos").
|
||||
Select("SUM(photo_type = 'video' AND photo_quality >= 0 AND photo_private = 0) AS videos, SUM(photo_type IN ('image','raw','live') AND photo_quality < 3 AND photo_quality >= 0 AND photo_private = 0) AS review, SUM(photo_quality = -1) AS hidden, SUM(photo_type IN ('image','raw','live') AND photo_private = 0 AND photo_quality >= 0) AS photos, SUM(photo_favorite = 1 AND photo_private = 0 AND photo_quality >= 0) AS favorites, SUM(photo_private = 1 AND photo_quality >= 0) AS private").
|
||||
Where("photos.id NOT IN (SELECT photo_id FROM files WHERE file_primary = 1 AND (file_missing = 1 OR file_error <> ''))").
|
||||
Where("deleted_at IS NULL").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("labels").
|
||||
c.Db().
|
||||
Table("labels").
|
||||
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
||||
Where("photo_count > 0").
|
||||
Where("deleted_at IS NULL").
|
||||
Where("(label_priority >= 0 OR label_favorite = 1)").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("albums").
|
||||
c.Db().
|
||||
Table("albums").
|
||||
Select("SUM(album_type = ?) AS albums, SUM(album_type = ?) AS moments, SUM(album_type = ?) AS months, SUM(album_type = ?) AS states, SUM(album_type = ?) AS folders", entity.AlbumDefault, entity.AlbumMoment, entity.AlbumMonth, entity.AlbumState, entity.AlbumFolder).
|
||||
Where("deleted_at IS NULL AND (albums.album_type <> 'folder' OR albums.album_path IN (SELECT photos.photo_path FROM photos WHERE photos.deleted_at IS NULL))").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("files").
|
||||
c.Db().
|
||||
Table("files").
|
||||
Select("COUNT(*) AS files").
|
||||
Where("file_missing = 0").
|
||||
Where("deleted_at IS NULL").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("countries").
|
||||
c.Db().
|
||||
Table("countries").
|
||||
Select("(COUNT(*) - 1) AS countries").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Table("places").
|
||||
c.Db().
|
||||
Table("places").
|
||||
Select("SUM(photo_count > 0) AS places").
|
||||
Where("id != 'zz'").
|
||||
Take(&result.Count)
|
||||
|
||||
c.Db().Order("country_slug").
|
||||
c.Db().
|
||||
Order("country_slug").
|
||||
Find(&result.Countries)
|
||||
|
||||
c.Db().Where("deleted_at IS NULL").
|
||||
c.Db().
|
||||
Where("id IN (SELECT photos.camera_id FROM photos WHERE photos.photo_quality >= 0 OR photos.deleted_at IS NULL)").
|
||||
Where("deleted_at IS NULL").
|
||||
Limit(10000).Order("camera_slug").
|
||||
Find(&result.Cameras)
|
||||
|
||||
c.Db().Where("deleted_at IS NULL").
|
||||
c.Db().
|
||||
Where("deleted_at IS NULL").
|
||||
Limit(10000).Order("lens_slug").
|
||||
Find(&result.Lenses)
|
||||
|
||||
c.Db().Where("deleted_at IS NULL AND album_favorite = 1").
|
||||
c.Db().
|
||||
Where("deleted_at IS NULL AND album_favorite = 1").
|
||||
Limit(20).Order("album_title").
|
||||
Find(&result.Albums)
|
||||
|
||||
c.Db().Table("photos").
|
||||
Where("photo_year > 0").
|
||||
c.Db().
|
||||
Table("photos").
|
||||
Where("photo_year > 0 AND (photos.photo_quality >= 0 OR photos.deleted_at IS NULL)").
|
||||
Order("photo_year DESC").
|
||||
Pluck("DISTINCT photo_year", &result.Years)
|
||||
|
||||
c.Db().Table("categories").
|
||||
c.Db().
|
||||
Table("categories").
|
||||
Select("l.label_uid, l.custom_slug, l.label_name").
|
||||
Joins("JOIN labels l ON categories.category_id = l.id").
|
||||
Where("l.deleted_at IS NULL").
|
||||
|
@ -311,7 +327,8 @@ func (c *Config) UserConfig() ClientConfig {
|
|||
Limit(1000).Offset(0).
|
||||
Scan(&result.Categories)
|
||||
|
||||
c.Db().Table("albums").
|
||||
c.Db().
|
||||
Table("albums").
|
||||
Select("album_category").
|
||||
Where("deleted_at IS NULL AND album_category <> ''").
|
||||
Group("album_category").
|
||||
|
|
|
@ -27,7 +27,7 @@ var dsnPattern = regexp.MustCompile(
|
|||
// DatabaseDriver returns the database driver name.
|
||||
func (c *Config) DatabaseDriver() string {
|
||||
switch strings.ToLower(c.params.DatabaseDriver) {
|
||||
case MySQL, "mariadb":
|
||||
case MySQL, MariaDB:
|
||||
c.params.DatabaseDriver = MySQL
|
||||
case SQLite, "sqlite", "sqllite", "test", "file", "":
|
||||
c.params.DatabaseDriver = SQLite
|
||||
|
@ -48,14 +48,23 @@ func (c *Config) DatabaseDriver() string {
|
|||
func (c *Config) DatabaseDsn() string {
|
||||
if c.params.DatabaseDsn == "" {
|
||||
switch c.DatabaseDriver() {
|
||||
case MySQL:
|
||||
case MySQL, MariaDB:
|
||||
return fmt.Sprintf(
|
||||
"%s:%s@tcp(%s)/%s?charset=utf8mb4,utf8&parseTime=true",
|
||||
"%s:%s@tcp(%s)/%s?charset=utf8mb4,utf8&collation=utf8mb4_unicode_ci&parseTime=true",
|
||||
c.DatabaseUser(),
|
||||
c.DatabasePassword(),
|
||||
c.DatabaseServer(),
|
||||
c.DatabaseName(),
|
||||
)
|
||||
case Postgres:
|
||||
return fmt.Sprintf(
|
||||
"user=%s password=%s dbname=%s host=%s port=%d sslmode=disable TimeZone=UTC",
|
||||
c.DatabaseUser(),
|
||||
c.DatabasePassword(),
|
||||
c.DatabaseName(),
|
||||
c.DatabaseHost(),
|
||||
c.DatabasePort(),
|
||||
)
|
||||
case SQLite:
|
||||
return filepath.Join(c.StoragePath(), "index.db")
|
||||
default:
|
||||
|
|
|
@ -15,9 +15,10 @@ import (
|
|||
|
||||
// Database drivers (sql dialects).
|
||||
const (
|
||||
MySQL = "mysql"
|
||||
SQLite = "sqlite3"
|
||||
// Postgres = "postgres" // TODO: Requires GORM 2.0 for generic column data types
|
||||
MySQL = "mysql"
|
||||
MariaDB = "mariadb"
|
||||
SQLite = "sqlite3"
|
||||
Postgres = "postgres" // TODO: Requires GORM 2.0 for generic column data types
|
||||
)
|
||||
|
||||
// Params provides a struct in which application configuration is stored.
|
||||
|
@ -32,6 +33,7 @@ type Params struct {
|
|||
Name string
|
||||
Version string
|
||||
Copyright string
|
||||
ConfigFile string
|
||||
SiteUrl string `yaml:"site-url" flag:"site-url"`
|
||||
SitePreview string `yaml:"site-preview" flag:"site-preview"`
|
||||
SiteTitle string `yaml:"site-title" flag:"site-title"`
|
||||
|
@ -53,7 +55,6 @@ type Params struct {
|
|||
ImportPath string `yaml:"import-path" flag:"import-path"`
|
||||
OriginalsPath string `yaml:"originals-path" flag:"originals-path"`
|
||||
OriginalsLimit int64 `yaml:"originals-limit" flag:"originals-limit"`
|
||||
ConfigFile string
|
||||
SettingsPath string `yaml:"settings-path" flag:"settings-path"`
|
||||
SettingsHidden bool `yaml:"settings-hidden" flag:"settings-hidden"`
|
||||
TempPath string `yaml:"temp-path" flag:"temp-path"`
|
||||
|
|
|
@ -36,10 +36,10 @@ type Account struct {
|
|||
AccShare bool
|
||||
AccSync bool
|
||||
RetryLimit int
|
||||
SharePath string `gorm:"type:VARBINARY(255);"`
|
||||
SharePath string `gorm:"type:VARBINARY(500);"`
|
||||
ShareSize string `gorm:"type:VARBINARY(16);"`
|
||||
ShareExpires int
|
||||
SyncPath string `gorm:"type:VARBINARY(255);"`
|
||||
SyncPath string `gorm:"type:VARBINARY(500);"`
|
||||
SyncStatus string `gorm:"type:VARBINARY(16);"`
|
||||
SyncInterval int
|
||||
SyncDate sql.NullTime `deepcopier:"skip"`
|
||||
|
|
|
@ -32,7 +32,7 @@ type Album struct {
|
|||
CoverUID string `gorm:"type:VARBINARY(42);" json:"CoverUID" yaml:"CoverUID,omitempty"`
|
||||
FolderUID string `gorm:"type:VARBINARY(42);index;" json:"FolderUID" yaml:"FolderUID,omitempty"`
|
||||
AlbumSlug string `gorm:"type:VARBINARY(255);index;" json:"Slug" yaml:"Slug"`
|
||||
AlbumPath string `gorm:"type:VARBINARY(768);index;" json:"Path" yaml:"-"`
|
||||
AlbumPath string `gorm:"type:VARBINARY(500);index;" json:"Path" yaml:"-"`
|
||||
AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"`
|
||||
AlbumTitle string `gorm:"type:VARCHAR(255);" json:"Title" yaml:"Title"`
|
||||
AlbumLocation string `gorm:"type:VARCHAR(255);" json:"Location" yaml:"Location,omitempty"`
|
||||
|
|
|
@ -11,7 +11,7 @@ type DuplicatesMap map[string]Duplicate
|
|||
|
||||
// Duplicate represents an exact file duplicate.
|
||||
type Duplicate struct {
|
||||
FileName string `gorm:"type:VARBINARY(768);primary_key;" json:"Name" yaml:"Name"`
|
||||
FileName string `gorm:"type:VARBINARY(755);primary_key;" json:"Name" yaml:"Name"`
|
||||
FileRoot string `gorm:"type:VARBINARY(16);primary_key;default:'/';" json:"Root" yaml:"Root,omitempty"`
|
||||
FileHash string `gorm:"type:VARBINARY(128);default:'';index" json:"Hash" yaml:"Hash,omitempty"`
|
||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||
|
|
|
@ -24,9 +24,9 @@ type File struct {
|
|||
PhotoUID string `gorm:"type:VARBINARY(42);index;" json:"PhotoUID" yaml:"PhotoUID"`
|
||||
InstanceID string `gorm:"type:VARBINARY(42);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
|
||||
FileUID string `gorm:"type:VARBINARY(42);unique_index;" json:"UID" yaml:"UID"`
|
||||
FileName string `gorm:"type:VARBINARY(768);unique_index:idx_files_name_root;" json:"Name" yaml:"Name"`
|
||||
FileName string `gorm:"type:VARBINARY(755);unique_index:idx_files_name_root;" json:"Name" yaml:"Name"`
|
||||
FileRoot string `gorm:"type:VARBINARY(16);default:'/';unique_index:idx_files_name_root;" json:"Root" yaml:"Root,omitempty"`
|
||||
OriginalName string `gorm:"type:VARBINARY(768);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||
FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"`
|
||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||
FileCodec string `gorm:"type:VARBINARY(32)" json:"Codec" yaml:"Codec,omitempty"`
|
||||
|
@ -48,7 +48,7 @@ type File struct {
|
|||
FileLuminance string `gorm:"type:VARBINARY(9);" json:"Luminance" yaml:"Luminance,omitempty"`
|
||||
FileDiff uint32 `json:"Diff" yaml:"Diff,omitempty"`
|
||||
FileChroma uint8 `json:"Chroma" yaml:"Chroma,omitempty"`
|
||||
FileError string `gorm:"type:varbinary(512)" json:"Error" yaml:"Error,omitempty"`
|
||||
FileError string `gorm:"type:VARBINARY(512)" json:"Error" yaml:"Error,omitempty"`
|
||||
ModTime int64 `json:"ModTime" yaml:"-"`
|
||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||
CreatedIn int64 `json:"CreatedIn" yaml:"-"`
|
||||
|
|
|
@ -21,7 +21,7 @@ type Folders []Folder
|
|||
|
||||
// Folder represents a file system directory.
|
||||
type Folder struct {
|
||||
Path string `gorm:"type:VARBINARY(255);unique_index:idx_folders_path_root;" json:"Path" yaml:"Path"`
|
||||
Path string `gorm:"type:VARBINARY(500);unique_index:idx_folders_path_root;" json:"Path" yaml:"Path"`
|
||||
Root string `gorm:"type:VARBINARY(16);default:'';unique_index:idx_folders_path_root;" json:"Root" yaml:"Root,omitempty"`
|
||||
FolderUID string `gorm:"type:VARBINARY(42);primary_key;" json:"UID,omitempty" yaml:"UID,omitempty"`
|
||||
FolderType string `gorm:"type:VARBINARY(16);" json:"Type" yaml:"Type,omitempty"`
|
||||
|
|
|
@ -19,12 +19,12 @@ type Labels []Label
|
|||
// Label is used for photo, album and location categorization
|
||||
type Label struct {
|
||||
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
|
||||
LabelUID string `gorm:"type:varbinary(42);unique_index;" json:"UID" yaml:"UID"`
|
||||
LabelSlug string `gorm:"type:varbinary(255);unique_index;" json:"Slug" yaml:"-"`
|
||||
CustomSlug string `gorm:"type:varbinary(255);index;" json:"CustomSlug" yaml:"-"`
|
||||
LabelUID string `gorm:"type:VARBINARY(42);unique_index;" json:"UID" yaml:"UID"`
|
||||
LabelSlug string `gorm:"type:VARBINARY(255);unique_index;" json:"Slug" yaml:"-"`
|
||||
CustomSlug string `gorm:"type:VARBINARY(255);index;" json:"CustomSlug" yaml:"-"`
|
||||
LabelName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
||||
LabelPriority int `gorm:"type:VARCHAR(255);" json:"Priority" yaml:"Priority,omitempty"`
|
||||
LabelFavorite bool `gorm:"type:VARCHAR(255);" json:"Favorite" yaml:"Favorite,omitempty"`
|
||||
LabelPriority int `json:"Priority" yaml:"Priority,omitempty"`
|
||||
LabelFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||
LabelDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
||||
LabelNotes string `gorm:"type:TEXT;" json:"Notes" yaml:"Notes,omitempty"`
|
||||
LabelCategories []*Label `gorm:"many2many:categories;association_jointable_foreignkey:category_id" json:"-" yaml:"-"`
|
||||
|
|
|
@ -17,9 +17,9 @@ type Lens struct {
|
|||
ID uint `gorm:"primary_key" json:"ID" yaml:"ID"`
|
||||
LensSlug string `gorm:"type:VARBINARY(255);unique_index;" json:"Slug" yaml:"Slug,omitempty"`
|
||||
LensName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
||||
LensMake string `json:"Make" yaml:"Make,omitempty"`
|
||||
LensModel string `json:"Model" yaml:"Model,omitempty"`
|
||||
LensType string `json:"Type" yaml:"Type,omitempty"`
|
||||
LensMake string `gorm:"type:VARCHAR(255);" json:"Make" yaml:"Make,omitempty"`
|
||||
LensModel string `gorm:"type:VARCHAR(255);" json:"Model" yaml:"Model,omitempty"`
|
||||
LensType string `gorm:"type:VARCHAR(255);" json:"Type" yaml:"Type,omitempty"`
|
||||
LensDescription string `gorm:"type:TEXT;" json:"Description,omitempty" yaml:"Description,omitempty"`
|
||||
LensNotes string `gorm:"type:TEXT;" json:"Notes,omitempty" yaml:"Notes,omitempty"`
|
||||
CreatedAt time.Time `json:"-" yaml:"-"`
|
||||
|
|
|
@ -54,9 +54,9 @@ type Photo struct {
|
|||
TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
|
||||
PhotoDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
||||
DescriptionSrc string `gorm:"type:VARBINARY(8);" json:"DescriptionSrc" yaml:"DescriptionSrc,omitempty"`
|
||||
PhotoPath string `gorm:"type:VARBINARY(768);index:idx_photos_path_name;" json:"Path" yaml:"-"`
|
||||
PhotoPath string `gorm:"type:VARBINARY(500);index:idx_photos_path_name;" json:"Path" yaml:"-"`
|
||||
PhotoName string `gorm:"type:VARBINARY(255);index:idx_photos_path_name;" json:"Name" yaml:"-"`
|
||||
OriginalName string `gorm:"type:VARBINARY(768);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||
OriginalName string `gorm:"type:VARBINARY(755);" json:"OriginalName" yaml:"OriginalName,omitempty"`
|
||||
PhotoFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||
PhotoSingle bool `json:"Single" yaml:"Single,omitempty"`
|
||||
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
||||
|
|
|
@ -13,7 +13,7 @@ var placeMutex = sync.Mutex{}
|
|||
// Place used to associate photos to places
|
||||
type Place struct {
|
||||
ID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"PlaceID" yaml:"PlaceID"`
|
||||
PlaceLabel string `gorm:"type:VARBINARY(768);unique_index;" json:"Label" yaml:"Label"`
|
||||
PlaceLabel string `gorm:"type:VARBINARY(755);unique_index;" json:"Label" yaml:"Label"`
|
||||
PlaceCity string `gorm:"type:VARCHAR(255);" json:"City" yaml:"City,omitempty"`
|
||||
PlaceState string `gorm:"type:VARCHAR(255);" json:"State" yaml:"State,omitempty"`
|
||||
PlaceCountry string `gorm:"type:VARBINARY(2);" json:"Country" yaml:"Country,omitempty"`
|
||||
|
|
|
@ -57,7 +57,7 @@ type User struct {
|
|||
RoleFamily bool `json:"RoleFamily" yaml:"RoleFamily,omitempty"`
|
||||
RoleFriend bool `json:"RoleFriend" yaml:"RoleFriend,omitempty"`
|
||||
WebDAV bool `gorm:"column:webdav" json:"WebDAV" yaml:"WebDAV,omitempty"`
|
||||
StoragePath string `gorm:"column:storage_path;type:VARBINARY(255);" json:"StoragePath" yaml:"StoragePath,omitempty"`
|
||||
StoragePath string `gorm:"column:storage_path;type:VARBINARY(500);" json:"StoragePath" yaml:"StoragePath,omitempty"`
|
||||
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
||||
InviteToken string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
||||
InvitedBy string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
||||
|
|
|
@ -199,7 +199,7 @@ func (m *Moments) Start() (err error) {
|
|||
continue
|
||||
}
|
||||
|
||||
if err := form.ParseQueryString(&f); err != nil {
|
||||
if err := form.Unserialize(&f, a.AlbumFilter); err != nil {
|
||||
log.Errorf("moments: %s", err.Error())
|
||||
} else {
|
||||
w := txt.Words(f.Label)
|
||||
|
|
|
@ -127,8 +127,8 @@ func AlbumSearch(f form.AlbumSearch) (results AlbumResults, err error) {
|
|||
}
|
||||
|
||||
if f.Query != "" {
|
||||
likeString := "%" + strings.ToLower(f.Query) + "%"
|
||||
s = s.Where("LOWER(albums.album_title) LIKE ? OR LOWER(albums.album_location) LIKE ?", likeString, likeString)
|
||||
likeString := "%" + f.Query + "%"
|
||||
s = s.Where("albums.album_title LIKE ? OR albums.album_location LIKE ?", likeString, likeString)
|
||||
}
|
||||
|
||||
if f.Type != "" {
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
|
@ -136,12 +138,15 @@ func Geo(f form.GeoSearch) (results GeoResults, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if f.Name != "" {
|
||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(f.Name, "*", "%"))
|
||||
if strings.Contains(f.Name, OrSep) {
|
||||
s = s.Where("photos.photo_name IN (?)", strings.Split(f.Name, OrSep))
|
||||
} else if f.Name != "" {
|
||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(fs.StripKnownExt(f.Name), "*", "%"))
|
||||
}
|
||||
|
||||
// Filter by status.
|
||||
if f.Archived {
|
||||
s = s.Where("photos.photo_quality > -1")
|
||||
s = s.Where("photos.deleted_at IS NOT NULL")
|
||||
} else {
|
||||
s = s.Where("photos.deleted_at IS NULL")
|
||||
|
|
|
@ -2,7 +2,6 @@ package query
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gosimple/slug"
|
||||
|
@ -46,12 +45,12 @@ func Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
|||
var label entity.Label
|
||||
|
||||
slugString := slug.Make(f.Query)
|
||||
likeString := "%" + strings.ToLower(f.Query) + "%"
|
||||
likeString := "%" + f.Query + "%"
|
||||
|
||||
if result := Db().First(&label, "label_slug = ? OR custom_slug = ?", slugString, slugString); result.Error != nil {
|
||||
log.Infof("search: label %s not found", txt.Quote(f.Query))
|
||||
|
||||
s = s.Where("LOWER(labels.label_name) LIKE ?", likeString)
|
||||
s = s.Where("labels.label_name LIKE ?", likeString)
|
||||
} else {
|
||||
labelIds = append(labelIds, label.ID)
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/photoprism/photoprism/pkg/fs"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/photoprism/photoprism/internal/entity"
|
||||
"github.com/photoprism/photoprism/internal/form"
|
||||
|
@ -144,6 +146,7 @@ func PhotoSearch(f form.PhotoSearch) (results PhotoResults, count int, err error
|
|||
s = s.Where("photos.photo_quality = -1")
|
||||
s = s.Where("photos.deleted_at IS NULL")
|
||||
} else if f.Archived {
|
||||
s = s.Where("photos.photo_quality > -1")
|
||||
s = s.Where("photos.deleted_at IS NOT NULL")
|
||||
} else {
|
||||
s = s.Where("photos.deleted_at IS NULL")
|
||||
|
@ -235,28 +238,40 @@ func PhotoSearch(f form.PhotoSearch) (results PhotoResults, count int, err error
|
|||
|
||||
if strings.HasSuffix(p, "/") {
|
||||
s = s.Where("photos.photo_path = ?", p[:len(p)-1])
|
||||
} else if strings.Contains(p, OrSep) {
|
||||
s = s.Where("photos.photo_path IN (?)", strings.Split(p, OrSep))
|
||||
} else {
|
||||
s = s.Where("photos.photo_path LIKE ?", strings.ReplaceAll(p, "*", "%"))
|
||||
}
|
||||
}
|
||||
|
||||
if f.Name != "" {
|
||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(f.Name, "*", "%"))
|
||||
if strings.Contains(f.Name, OrSep) {
|
||||
s = s.Where("photos.photo_name IN (?)", strings.Split(f.Name, OrSep))
|
||||
} else if f.Name != "" {
|
||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(fs.StripKnownExt(f.Name), "*", "%"))
|
||||
}
|
||||
|
||||
if f.Filename != "" {
|
||||
if strings.Contains(f.Filename, OrSep) {
|
||||
s = s.Where("files.file_name IN (?)", strings.Split(f.Filename, OrSep))
|
||||
} else if f.Filename != "" {
|
||||
s = s.Where("files.file_name LIKE ?", strings.ReplaceAll(f.Filename, "*", "%"))
|
||||
}
|
||||
|
||||
if f.Original != "" {
|
||||
if strings.Contains(f.Original, OrSep) {
|
||||
s = s.Where("photos.original_name IN (?)", strings.Split(f.Original, OrSep))
|
||||
} else if f.Original != "" {
|
||||
s = s.Where("photos.original_name LIKE ?", strings.ReplaceAll(f.Original, "*", "%"))
|
||||
}
|
||||
|
||||
if f.Title != "" {
|
||||
s = s.Where("LOWER(photos.photo_title) LIKE ?", strings.ReplaceAll(strings.ToLower(f.Title), "*", "%"))
|
||||
if strings.Contains(f.Title, OrSep) {
|
||||
s = s.Where("photos.photo_title IN (?)", strings.Split(strings.ToLower(f.Title), OrSep))
|
||||
} else if f.Title != "" {
|
||||
s = s.Where("photos.photo_title LIKE ?", strings.ReplaceAll(strings.ToLower(f.Title), "*", "%"))
|
||||
}
|
||||
|
||||
if f.Hash != "" {
|
||||
if strings.Contains(f.Hash, OrSep) {
|
||||
s = s.Where("files.file_hash IN (?)", strings.Split(strings.ToLower(f.Hash), OrSep))
|
||||
} else if f.Hash != "" {
|
||||
s = s.Where("files.file_hash IN (?)", strings.Split(strings.ToLower(f.Hash), OrSep))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue