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
|
var cmd *exec.Cmd
|
||||||
|
|
||||||
switch conf.DatabaseDriver() {
|
switch conf.DatabaseDriver() {
|
||||||
case config.MySQL:
|
case config.MySQL, config.MariaDB:
|
||||||
cmd = exec.Command(
|
cmd = exec.Command(
|
||||||
conf.MysqldumpBin(),
|
conf.MysqldumpBin(),
|
||||||
"-h", conf.DatabaseHost(),
|
"-h", conf.DatabaseHost(),
|
||||||
|
|
|
@ -101,7 +101,7 @@ func restoreAction(ctx *cli.Context) error {
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
|
|
||||||
switch conf.DatabaseDriver() {
|
switch conf.DatabaseDriver() {
|
||||||
case config.MySQL:
|
case config.MySQL, config.MariaDB:
|
||||||
cmd = exec.Command(
|
cmd = exec.Command(
|
||||||
conf.MysqlBin(),
|
conf.MysqlBin(),
|
||||||
"-h", conf.DatabaseHost(),
|
"-h", conf.DatabaseHost(),
|
||||||
|
|
|
@ -232,77 +232,93 @@ func (c *Config) UserConfig() ClientConfig {
|
||||||
Server: NewRuntimeInfo(),
|
Server: NewRuntimeInfo(),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Db().Table("photos").
|
c.Db().
|
||||||
|
Table("photos").
|
||||||
Select("photo_uid, cell_id, photo_lat, photo_lng, taken_at").
|
Select("photo_uid, cell_id, photo_lat, photo_lng, taken_at").
|
||||||
Where("deleted_at IS NULL AND photo_lat != 0 AND photo_lng != 0").
|
Where("deleted_at IS NULL AND photo_lat != 0 AND photo_lng != 0").
|
||||||
Order("taken_at DESC").
|
Order("taken_at DESC").
|
||||||
Limit(1).Offset(0).
|
Limit(1).Offset(0).
|
||||||
Take(&result.Pos)
|
Take(&result.Pos)
|
||||||
|
|
||||||
c.Db().Table("cameras").
|
c.Db().
|
||||||
|
Table("cameras").
|
||||||
Where("camera_slug <> 'zz' AND camera_slug <> ''").
|
Where("camera_slug <> 'zz' AND camera_slug <> ''").
|
||||||
Select("COUNT(*) AS cameras").
|
Select("COUNT(*) AS cameras").
|
||||||
Take(&result.Count)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Table("lenses").
|
c.Db().
|
||||||
|
Table("lenses").
|
||||||
Where("lens_slug <> 'zz' AND lens_slug <> ''").
|
Where("lens_slug <> 'zz' AND lens_slug <> ''").
|
||||||
Select("COUNT(*) AS lenses").
|
Select("COUNT(*) AS lenses").
|
||||||
Take(&result.Count)
|
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").
|
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("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").
|
Where("deleted_at IS NULL").
|
||||||
Take(&result.Count)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Table("labels").
|
c.Db().
|
||||||
|
Table("labels").
|
||||||
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
Select("MAX(photo_count) as label_max_photos, COUNT(*) AS labels").
|
||||||
Where("photo_count > 0").
|
Where("photo_count > 0").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Where("(label_priority >= 0 OR label_favorite = 1)").
|
Where("(label_priority >= 0 OR label_favorite = 1)").
|
||||||
Take(&result.Count)
|
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).
|
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))").
|
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)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Table("files").
|
c.Db().
|
||||||
|
Table("files").
|
||||||
Select("COUNT(*) AS files").
|
Select("COUNT(*) AS files").
|
||||||
Where("file_missing = 0").
|
Where("file_missing = 0").
|
||||||
Where("deleted_at IS NULL").
|
Where("deleted_at IS NULL").
|
||||||
Take(&result.Count)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Table("countries").
|
c.Db().
|
||||||
|
Table("countries").
|
||||||
Select("(COUNT(*) - 1) AS countries").
|
Select("(COUNT(*) - 1) AS countries").
|
||||||
Take(&result.Count)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Table("places").
|
c.Db().
|
||||||
|
Table("places").
|
||||||
Select("SUM(photo_count > 0) AS places").
|
Select("SUM(photo_count > 0) AS places").
|
||||||
Where("id != 'zz'").
|
Where("id != 'zz'").
|
||||||
Take(&result.Count)
|
Take(&result.Count)
|
||||||
|
|
||||||
c.Db().Order("country_slug").
|
c.Db().
|
||||||
|
Order("country_slug").
|
||||||
Find(&result.Countries)
|
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").
|
Limit(10000).Order("camera_slug").
|
||||||
Find(&result.Cameras)
|
Find(&result.Cameras)
|
||||||
|
|
||||||
c.Db().Where("deleted_at IS NULL").
|
c.Db().
|
||||||
|
Where("deleted_at IS NULL").
|
||||||
Limit(10000).Order("lens_slug").
|
Limit(10000).Order("lens_slug").
|
||||||
Find(&result.Lenses)
|
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").
|
Limit(20).Order("album_title").
|
||||||
Find(&result.Albums)
|
Find(&result.Albums)
|
||||||
|
|
||||||
c.Db().Table("photos").
|
c.Db().
|
||||||
Where("photo_year > 0").
|
Table("photos").
|
||||||
|
Where("photo_year > 0 AND (photos.photo_quality >= 0 OR photos.deleted_at IS NULL)").
|
||||||
Order("photo_year DESC").
|
Order("photo_year DESC").
|
||||||
Pluck("DISTINCT photo_year", &result.Years)
|
Pluck("DISTINCT photo_year", &result.Years)
|
||||||
|
|
||||||
c.Db().Table("categories").
|
c.Db().
|
||||||
|
Table("categories").
|
||||||
Select("l.label_uid, l.custom_slug, l.label_name").
|
Select("l.label_uid, l.custom_slug, l.label_name").
|
||||||
Joins("JOIN labels l ON categories.category_id = l.id").
|
Joins("JOIN labels l ON categories.category_id = l.id").
|
||||||
Where("l.deleted_at IS NULL").
|
Where("l.deleted_at IS NULL").
|
||||||
|
@ -311,7 +327,8 @@ func (c *Config) UserConfig() ClientConfig {
|
||||||
Limit(1000).Offset(0).
|
Limit(1000).Offset(0).
|
||||||
Scan(&result.Categories)
|
Scan(&result.Categories)
|
||||||
|
|
||||||
c.Db().Table("albums").
|
c.Db().
|
||||||
|
Table("albums").
|
||||||
Select("album_category").
|
Select("album_category").
|
||||||
Where("deleted_at IS NULL AND album_category <> ''").
|
Where("deleted_at IS NULL AND album_category <> ''").
|
||||||
Group("album_category").
|
Group("album_category").
|
||||||
|
|
|
@ -27,7 +27,7 @@ var dsnPattern = regexp.MustCompile(
|
||||||
// DatabaseDriver returns the database driver name.
|
// DatabaseDriver returns the database driver name.
|
||||||
func (c *Config) DatabaseDriver() string {
|
func (c *Config) DatabaseDriver() string {
|
||||||
switch strings.ToLower(c.params.DatabaseDriver) {
|
switch strings.ToLower(c.params.DatabaseDriver) {
|
||||||
case MySQL, "mariadb":
|
case MySQL, MariaDB:
|
||||||
c.params.DatabaseDriver = MySQL
|
c.params.DatabaseDriver = MySQL
|
||||||
case SQLite, "sqlite", "sqllite", "test", "file", "":
|
case SQLite, "sqlite", "sqllite", "test", "file", "":
|
||||||
c.params.DatabaseDriver = SQLite
|
c.params.DatabaseDriver = SQLite
|
||||||
|
@ -48,14 +48,23 @@ func (c *Config) DatabaseDriver() string {
|
||||||
func (c *Config) DatabaseDsn() string {
|
func (c *Config) DatabaseDsn() string {
|
||||||
if c.params.DatabaseDsn == "" {
|
if c.params.DatabaseDsn == "" {
|
||||||
switch c.DatabaseDriver() {
|
switch c.DatabaseDriver() {
|
||||||
case MySQL:
|
case MySQL, MariaDB:
|
||||||
return fmt.Sprintf(
|
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.DatabaseUser(),
|
||||||
c.DatabasePassword(),
|
c.DatabasePassword(),
|
||||||
c.DatabaseServer(),
|
c.DatabaseServer(),
|
||||||
c.DatabaseName(),
|
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:
|
case SQLite:
|
||||||
return filepath.Join(c.StoragePath(), "index.db")
|
return filepath.Join(c.StoragePath(), "index.db")
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -15,9 +15,10 @@ import (
|
||||||
|
|
||||||
// Database drivers (sql dialects).
|
// Database drivers (sql dialects).
|
||||||
const (
|
const (
|
||||||
MySQL = "mysql"
|
MySQL = "mysql"
|
||||||
SQLite = "sqlite3"
|
MariaDB = "mariadb"
|
||||||
// Postgres = "postgres" // TODO: Requires GORM 2.0 for generic column data types
|
SQLite = "sqlite3"
|
||||||
|
Postgres = "postgres" // TODO: Requires GORM 2.0 for generic column data types
|
||||||
)
|
)
|
||||||
|
|
||||||
// Params provides a struct in which application configuration is stored.
|
// Params provides a struct in which application configuration is stored.
|
||||||
|
@ -32,6 +33,7 @@ type Params struct {
|
||||||
Name string
|
Name string
|
||||||
Version string
|
Version string
|
||||||
Copyright string
|
Copyright string
|
||||||
|
ConfigFile string
|
||||||
SiteUrl string `yaml:"site-url" flag:"site-url"`
|
SiteUrl string `yaml:"site-url" flag:"site-url"`
|
||||||
SitePreview string `yaml:"site-preview" flag:"site-preview"`
|
SitePreview string `yaml:"site-preview" flag:"site-preview"`
|
||||||
SiteTitle string `yaml:"site-title" flag:"site-title"`
|
SiteTitle string `yaml:"site-title" flag:"site-title"`
|
||||||
|
@ -53,7 +55,6 @@ type Params struct {
|
||||||
ImportPath string `yaml:"import-path" flag:"import-path"`
|
ImportPath string `yaml:"import-path" flag:"import-path"`
|
||||||
OriginalsPath string `yaml:"originals-path" flag:"originals-path"`
|
OriginalsPath string `yaml:"originals-path" flag:"originals-path"`
|
||||||
OriginalsLimit int64 `yaml:"originals-limit" flag:"originals-limit"`
|
OriginalsLimit int64 `yaml:"originals-limit" flag:"originals-limit"`
|
||||||
ConfigFile string
|
|
||||||
SettingsPath string `yaml:"settings-path" flag:"settings-path"`
|
SettingsPath string `yaml:"settings-path" flag:"settings-path"`
|
||||||
SettingsHidden bool `yaml:"settings-hidden" flag:"settings-hidden"`
|
SettingsHidden bool `yaml:"settings-hidden" flag:"settings-hidden"`
|
||||||
TempPath string `yaml:"temp-path" flag:"temp-path"`
|
TempPath string `yaml:"temp-path" flag:"temp-path"`
|
||||||
|
|
|
@ -36,10 +36,10 @@ type Account struct {
|
||||||
AccShare bool
|
AccShare bool
|
||||||
AccSync bool
|
AccSync bool
|
||||||
RetryLimit int
|
RetryLimit int
|
||||||
SharePath string `gorm:"type:VARBINARY(255);"`
|
SharePath string `gorm:"type:VARBINARY(500);"`
|
||||||
ShareSize string `gorm:"type:VARBINARY(16);"`
|
ShareSize string `gorm:"type:VARBINARY(16);"`
|
||||||
ShareExpires int
|
ShareExpires int
|
||||||
SyncPath string `gorm:"type:VARBINARY(255);"`
|
SyncPath string `gorm:"type:VARBINARY(500);"`
|
||||||
SyncStatus string `gorm:"type:VARBINARY(16);"`
|
SyncStatus string `gorm:"type:VARBINARY(16);"`
|
||||||
SyncInterval int
|
SyncInterval int
|
||||||
SyncDate sql.NullTime `deepcopier:"skip"`
|
SyncDate sql.NullTime `deepcopier:"skip"`
|
||||||
|
|
|
@ -32,7 +32,7 @@ type Album struct {
|
||||||
CoverUID string `gorm:"type:VARBINARY(42);" json:"CoverUID" yaml:"CoverUID,omitempty"`
|
CoverUID string `gorm:"type:VARBINARY(42);" json:"CoverUID" yaml:"CoverUID,omitempty"`
|
||||||
FolderUID string `gorm:"type:VARBINARY(42);index;" json:"FolderUID" yaml:"FolderUID,omitempty"`
|
FolderUID string `gorm:"type:VARBINARY(42);index;" json:"FolderUID" yaml:"FolderUID,omitempty"`
|
||||||
AlbumSlug string `gorm:"type:VARBINARY(255);index;" json:"Slug" yaml:"Slug"`
|
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"`
|
AlbumType string `gorm:"type:VARBINARY(8);default:'album';" json:"Type" yaml:"Type,omitempty"`
|
||||||
AlbumTitle string `gorm:"type:VARCHAR(255);" json:"Title" yaml:"Title"`
|
AlbumTitle string `gorm:"type:VARCHAR(255);" json:"Title" yaml:"Title"`
|
||||||
AlbumLocation string `gorm:"type:VARCHAR(255);" json:"Location" yaml:"Location,omitempty"`
|
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.
|
// Duplicate represents an exact file duplicate.
|
||||||
type Duplicate struct {
|
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"`
|
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"`
|
FileHash string `gorm:"type:VARBINARY(128);default:'';index" json:"Hash" yaml:"Hash,omitempty"`
|
||||||
FileSize int64 `json:"Size" yaml:"Size,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"`
|
PhotoUID string `gorm:"type:VARBINARY(42);index;" json:"PhotoUID" yaml:"PhotoUID"`
|
||||||
InstanceID string `gorm:"type:VARBINARY(42);index;" json:"InstanceID,omitempty" yaml:"InstanceID,omitempty"`
|
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"`
|
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"`
|
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"`
|
FileHash string `gorm:"type:VARBINARY(128);index" json:"Hash" yaml:"Hash,omitempty"`
|
||||||
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
FileSize int64 `json:"Size" yaml:"Size,omitempty"`
|
||||||
FileCodec string `gorm:"type:VARBINARY(32)" json:"Codec" yaml:"Codec,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"`
|
FileLuminance string `gorm:"type:VARBINARY(9);" json:"Luminance" yaml:"Luminance,omitempty"`
|
||||||
FileDiff uint32 `json:"Diff" yaml:"Diff,omitempty"`
|
FileDiff uint32 `json:"Diff" yaml:"Diff,omitempty"`
|
||||||
FileChroma uint8 `json:"Chroma" yaml:"Chroma,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:"-"`
|
ModTime int64 `json:"ModTime" yaml:"-"`
|
||||||
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
CreatedAt time.Time `json:"CreatedAt" yaml:"-"`
|
||||||
CreatedIn int64 `json:"CreatedIn" yaml:"-"`
|
CreatedIn int64 `json:"CreatedIn" yaml:"-"`
|
||||||
|
|
|
@ -21,7 +21,7 @@ type Folders []Folder
|
||||||
|
|
||||||
// Folder represents a file system directory.
|
// Folder represents a file system directory.
|
||||||
type Folder struct {
|
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"`
|
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"`
|
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"`
|
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
|
// Label is used for photo, album and location categorization
|
||||||
type Label struct {
|
type Label struct {
|
||||||
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
|
ID uint `gorm:"primary_key" json:"ID" yaml:"-"`
|
||||||
LabelUID string `gorm:"type:varbinary(42);unique_index;" json:"UID" yaml:"UID"`
|
LabelUID string `gorm:"type:VARBINARY(42);unique_index;" json:"UID" yaml:"UID"`
|
||||||
LabelSlug string `gorm:"type:varbinary(255);unique_index;" json:"Slug" yaml:"-"`
|
LabelSlug string `gorm:"type:VARBINARY(255);unique_index;" json:"Slug" yaml:"-"`
|
||||||
CustomSlug string `gorm:"type:varbinary(255);index;" json:"CustomSlug" yaml:"-"`
|
CustomSlug string `gorm:"type:VARBINARY(255);index;" json:"CustomSlug" yaml:"-"`
|
||||||
LabelName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
LabelName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
||||||
LabelPriority int `gorm:"type:VARCHAR(255);" json:"Priority" yaml:"Priority,omitempty"`
|
LabelPriority int `json:"Priority" yaml:"Priority,omitempty"`
|
||||||
LabelFavorite bool `gorm:"type:VARCHAR(255);" json:"Favorite" yaml:"Favorite,omitempty"`
|
LabelFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
LabelDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
LabelDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
||||||
LabelNotes string `gorm:"type:TEXT;" json:"Notes" yaml:"Notes,omitempty"`
|
LabelNotes string `gorm:"type:TEXT;" json:"Notes" yaml:"Notes,omitempty"`
|
||||||
LabelCategories []*Label `gorm:"many2many:categories;association_jointable_foreignkey:category_id" json:"-" yaml:"-"`
|
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"`
|
ID uint `gorm:"primary_key" json:"ID" yaml:"ID"`
|
||||||
LensSlug string `gorm:"type:VARBINARY(255);unique_index;" json:"Slug" yaml:"Slug,omitempty"`
|
LensSlug string `gorm:"type:VARBINARY(255);unique_index;" json:"Slug" yaml:"Slug,omitempty"`
|
||||||
LensName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
LensName string `gorm:"type:VARCHAR(255);" json:"Name" yaml:"Name"`
|
||||||
LensMake string `json:"Make" yaml:"Make,omitempty"`
|
LensMake string `gorm:"type:VARCHAR(255);" json:"Make" yaml:"Make,omitempty"`
|
||||||
LensModel string `json:"Model" yaml:"Model,omitempty"`
|
LensModel string `gorm:"type:VARCHAR(255);" json:"Model" yaml:"Model,omitempty"`
|
||||||
LensType string `json:"Type" yaml:"Type,omitempty"`
|
LensType string `gorm:"type:VARCHAR(255);" json:"Type" yaml:"Type,omitempty"`
|
||||||
LensDescription string `gorm:"type:TEXT;" json:"Description,omitempty" yaml:"Description,omitempty"`
|
LensDescription string `gorm:"type:TEXT;" json:"Description,omitempty" yaml:"Description,omitempty"`
|
||||||
LensNotes string `gorm:"type:TEXT;" json:"Notes,omitempty" yaml:"Notes,omitempty"`
|
LensNotes string `gorm:"type:TEXT;" json:"Notes,omitempty" yaml:"Notes,omitempty"`
|
||||||
CreatedAt time.Time `json:"-" yaml:"-"`
|
CreatedAt time.Time `json:"-" yaml:"-"`
|
||||||
|
|
|
@ -54,9 +54,9 @@ type Photo struct {
|
||||||
TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
|
TitleSrc string `gorm:"type:VARBINARY(8);" json:"TitleSrc" yaml:"TitleSrc,omitempty"`
|
||||||
PhotoDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
PhotoDescription string `gorm:"type:TEXT;" json:"Description" yaml:"Description,omitempty"`
|
||||||
DescriptionSrc string `gorm:"type:VARBINARY(8);" json:"DescriptionSrc" yaml:"DescriptionSrc,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:"-"`
|
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"`
|
PhotoFavorite bool `json:"Favorite" yaml:"Favorite,omitempty"`
|
||||||
PhotoSingle bool `json:"Single" yaml:"Single,omitempty"`
|
PhotoSingle bool `json:"Single" yaml:"Single,omitempty"`
|
||||||
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
PhotoPrivate bool `json:"Private" yaml:"Private,omitempty"`
|
||||||
|
|
|
@ -13,7 +13,7 @@ var placeMutex = sync.Mutex{}
|
||||||
// Place used to associate photos to places
|
// Place used to associate photos to places
|
||||||
type Place struct {
|
type Place struct {
|
||||||
ID string `gorm:"type:VARBINARY(42);primary_key;auto_increment:false;" json:"PlaceID" yaml:"PlaceID"`
|
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"`
|
PlaceCity string `gorm:"type:VARCHAR(255);" json:"City" yaml:"City,omitempty"`
|
||||||
PlaceState string `gorm:"type:VARCHAR(255);" json:"State" yaml:"State,omitempty"`
|
PlaceState string `gorm:"type:VARCHAR(255);" json:"State" yaml:"State,omitempty"`
|
||||||
PlaceCountry string `gorm:"type:VARBINARY(2);" json:"Country" yaml:"Country,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"`
|
RoleFamily bool `json:"RoleFamily" yaml:"RoleFamily,omitempty"`
|
||||||
RoleFriend bool `json:"RoleFriend" yaml:"RoleFriend,omitempty"`
|
RoleFriend bool `json:"RoleFriend" yaml:"RoleFriend,omitempty"`
|
||||||
WebDAV bool `gorm:"column:webdav" json:"WebDAV" yaml:"WebDAV,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"`
|
CanInvite bool `json:"CanInvite" yaml:"CanInvite,omitempty"`
|
||||||
InviteToken string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
InviteToken string `gorm:"type:VARBINARY(32);" json:"-" yaml:"-"`
|
||||||
InvitedBy 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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := form.ParseQueryString(&f); err != nil {
|
if err := form.Unserialize(&f, a.AlbumFilter); err != nil {
|
||||||
log.Errorf("moments: %s", err.Error())
|
log.Errorf("moments: %s", err.Error())
|
||||||
} else {
|
} else {
|
||||||
w := txt.Words(f.Label)
|
w := txt.Words(f.Label)
|
||||||
|
|
|
@ -127,8 +127,8 @@ func AlbumSearch(f form.AlbumSearch) (results AlbumResults, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Query != "" {
|
if f.Query != "" {
|
||||||
likeString := "%" + strings.ToLower(f.Query) + "%"
|
likeString := "%" + f.Query + "%"
|
||||||
s = s.Where("LOWER(albums.album_title) LIKE ? OR LOWER(albums.album_location) LIKE ?", likeString, likeString)
|
s = s.Where("albums.album_title LIKE ? OR albums.album_location LIKE ?", likeString, likeString)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Type != "" {
|
if f.Type != "" {
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/photoprism/photoprism/pkg/fs"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
"github.com/photoprism/photoprism/internal/form"
|
"github.com/photoprism/photoprism/internal/form"
|
||||||
|
@ -136,12 +138,15 @@ func Geo(f form.GeoSearch) (results GeoResults, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Name != "" {
|
if strings.Contains(f.Name, OrSep) {
|
||||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(f.Name, "*", "%"))
|
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.
|
// Filter by status.
|
||||||
if f.Archived {
|
if f.Archived {
|
||||||
|
s = s.Where("photos.photo_quality > -1")
|
||||||
s = s.Where("photos.deleted_at IS NOT NULL")
|
s = s.Where("photos.deleted_at IS NOT NULL")
|
||||||
} else {
|
} else {
|
||||||
s = s.Where("photos.deleted_at IS NULL")
|
s = s.Where("photos.deleted_at IS NULL")
|
||||||
|
|
|
@ -2,7 +2,6 @@ package query
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gosimple/slug"
|
"github.com/gosimple/slug"
|
||||||
|
@ -46,12 +45,12 @@ func Labels(f form.LabelSearch) (results []LabelResult, err error) {
|
||||||
var label entity.Label
|
var label entity.Label
|
||||||
|
|
||||||
slugString := slug.Make(f.Query)
|
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 {
|
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))
|
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 {
|
} else {
|
||||||
labelIds = append(labelIds, label.ID)
|
labelIds = append(labelIds, label.ID)
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/photoprism/photoprism/pkg/fs"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/photoprism/photoprism/internal/entity"
|
"github.com/photoprism/photoprism/internal/entity"
|
||||||
"github.com/photoprism/photoprism/internal/form"
|
"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.photo_quality = -1")
|
||||||
s = s.Where("photos.deleted_at IS NULL")
|
s = s.Where("photos.deleted_at IS NULL")
|
||||||
} else if f.Archived {
|
} else if f.Archived {
|
||||||
|
s = s.Where("photos.photo_quality > -1")
|
||||||
s = s.Where("photos.deleted_at IS NOT NULL")
|
s = s.Where("photos.deleted_at IS NOT NULL")
|
||||||
} else {
|
} else {
|
||||||
s = s.Where("photos.deleted_at IS NULL")
|
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, "/") {
|
if strings.HasSuffix(p, "/") {
|
||||||
s = s.Where("photos.photo_path = ?", p[:len(p)-1])
|
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 {
|
} else {
|
||||||
s = s.Where("photos.photo_path LIKE ?", strings.ReplaceAll(p, "*", "%"))
|
s = s.Where("photos.photo_path LIKE ?", strings.ReplaceAll(p, "*", "%"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Name != "" {
|
if strings.Contains(f.Name, OrSep) {
|
||||||
s = s.Where("photos.photo_name LIKE ?", strings.ReplaceAll(f.Name, "*", "%"))
|
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, "*", "%"))
|
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, "*", "%"))
|
s = s.Where("photos.original_name LIKE ?", strings.ReplaceAll(f.Original, "*", "%"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Title != "" {
|
if strings.Contains(f.Title, OrSep) {
|
||||||
s = s.Where("LOWER(photos.photo_title) LIKE ?", strings.ReplaceAll(strings.ToLower(f.Title), "*", "%"))
|
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))
|
s = s.Where("files.file_hash IN (?)", strings.Split(strings.ToLower(f.Hash), OrSep))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue