2018-09-12 16:37:30 +02:00
package photoprism
import (
"github.com/jinzhu/gorm"
"github.com/photoprism/photoprism/forms"
2018-09-13 07:05:13 +02:00
"strings"
2018-09-12 16:37:30 +02:00
"time"
)
type Search struct {
originalsPath string
db * gorm . DB
}
2018-09-13 20:54:34 +02:00
type SearchCount struct {
Total int
}
2018-09-12 16:37:30 +02:00
type PhotoSearchResult struct {
// Photo
ID uint
CreatedAt time . Time
UpdatedAt time . Time
DeletedAt time . Time
TakenAt time . Time
PhotoTitle string
PhotoDescription string
PhotoArtist string
PhotoKeywords string
PhotoColors string
PhotoVibrantColor string
PhotoMutedColor string
PhotoCanonicalName string
PhotoPerceptualHash string
PhotoLat float64
PhotoLong float64
PhotoFavorite bool
// Camera
CameraID uint
CameraModel string
// Location
LocationID uint
LocDisplayName string
LocName string
LocCity string
LocPostcode string
LocCounty string
LocState string
LocCountry string
LocCountryCode string
LocCategory string
LocType string
// File
FileID uint
FileName string
FileType string
FileMime string
FileWidth int
FileHeight int
FileOrientation int
FileAspectRatio float64
2018-09-13 07:05:13 +02:00
// Tags
Tags string
2018-09-12 16:37:30 +02:00
}
2018-09-13 07:05:13 +02:00
func NewSearch ( originalsPath string , db * gorm . DB ) * Search {
2018-09-12 16:37:30 +02:00
instance := & Search {
originalsPath : originalsPath ,
db : db ,
}
return instance
}
2018-09-13 20:54:34 +02:00
func ( s * Search ) Photos ( form forms . PhotoSearchForm ) ( [ ] PhotoSearchResult , int , error ) {
q := s . db . NewScope ( nil ) . DB ( )
2018-09-12 16:37:30 +02:00
q = q . Table ( "photos" ) .
2018-09-13 20:54:34 +02:00
Select ( ` SQL_CALC_FOUND_ROWS photos . * ,
2018-09-12 16:37:30 +02:00
files . id AS file_id , files . file_name , files . file_type , files . file_mime , files . file_width , files . file_height , files . file_aspect_ratio , files . file_orientation ,
cameras . camera_model ,
2018-09-13 07:05:13 +02:00
locations . loc_display_name , locations . loc_name , locations . loc_city , locations . loc_postcode , locations . loc_country , locations . loc_country_code , locations . loc_category , locations . loc_type ,
GROUP_CONCAT ( tags . tag_label ) AS tags ` ) .
2018-09-12 16:37:30 +02:00
Joins ( "JOIN files ON files.photo_id = photos.id AND files.file_primary AND files.deleted_at IS NULL" ) .
Joins ( "JOIN cameras ON cameras.id = photos.camera_id" ) .
Joins ( "LEFT JOIN locations ON locations.id = photos.location_id" ) .
2018-09-13 07:05:13 +02:00
Joins ( "LEFT JOIN photo_tags ON photo_tags.photo_id = photos.id" ) .
Joins ( "LEFT JOIN tags ON photo_tags.tag_id = tags.id" ) .
Where ( "photos.deleted_at IS NULL" ) .
Group ( "photos.id, files.id" )
2018-09-12 16:37:30 +02:00
if form . Query != "" {
2018-09-13 20:54:34 +02:00
q = q . Where ( "tags.tag_label LIKE ? OR MATCH (photo_title, photo_description, photo_artist, photo_colors) AGAINST (?)" , "%" + strings . ToLower ( form . Query ) + "%" , form . Query )
2018-09-12 16:37:30 +02:00
}
2018-09-13 10:23:06 +02:00
if form . CameraID > 0 {
q = q . Where ( "camera_id = ?" , form . CameraID )
}
2018-09-13 07:05:13 +02:00
q = q . Order ( form . Order ) . Limit ( form . Count ) . Offset ( form . Offset )
2018-09-12 16:37:30 +02:00
results := make ( [ ] PhotoSearchResult , 0 , form . Count )
rows , err := q . Rows ( )
if err != nil {
2018-09-13 20:54:34 +02:00
return results , 0 , err
2018-09-12 16:37:30 +02:00
}
defer rows . Close ( )
for rows . Next ( ) {
var result PhotoSearchResult
s . db . ScanRows ( rows , & result )
results = append ( results , result )
}
2018-09-13 20:54:34 +02:00
// TODO: Check if this works properly with concurrent requests and caching
count := & SearchCount { }
s . db . Raw ( "SELECT FOUND_ROWS() AS total" ) . Scan ( & count )
total := count . Total
return results , total , nil
2018-09-12 16:37:30 +02:00
}
func ( s * Search ) FindFiles ( count int , offset int ) ( files [ ] File ) {
s . db . Where ( & File { } ) . Limit ( count ) . Offset ( offset ) . Find ( & files )
return files
}
func ( s * Search ) FindFile ( id string ) ( file File ) {
s . db . Where ( "id = ?" , id ) . First ( & file )
return file
}