Merge pull request #3 from gtsteffaniak/search2

make more efficient
This commit is contained in:
Graham Steffaniak 2023-07-04 19:56:00 -04:00 committed by GitHub
commit 665a1c68cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 96 additions and 76 deletions

View File

@ -4,5 +4,5 @@
"address": "",
"log": "stdout",
"database": "./database.db",
"root": "./srv"
"root": "/srv"
}

View File

@ -52,7 +52,6 @@ override the options.`,
Port: mustGetString(flags, "port"),
Log: mustGetString(flags, "log"),
}
err := d.store.Settings.Save(s)
checkErr(err)
err = d.store.Settings.SaveServer(ser)

View File

@ -49,9 +49,6 @@ func init() {
rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n")
flags := rootCmd.Flags()
// initialize indexing and schedule indexing ever n minutes (default 5)
indexingInterval := getEnvVariableAsUint32("INDEXING_INTERVAL")
go search.InitializeIndex(indexingInterval)
persistent := rootCmd.PersistentFlags()
@ -153,6 +150,9 @@ user created with the credentials from options "username" and "password".`,
}
fileCache = diskcache.New(afero.NewOsFs(), cacheDir)
}
// initialize indexing and schedule indexing ever n minutes (default 5)
indexingInterval := getEnvVariableAsUint32("INDEXING_INTERVAL")
go search.InitializeIndex(indexingInterval)
server := getRunParams(cmd.Flags(), d.store)
setupLog(server.Log)
@ -376,7 +376,6 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) {
Address: getParam(flags, "address"),
Root: getParam(flags, "root"),
}
err = d.store.Settings.SaveServer(ser)
checkErr(err)

BIN
src/backend/filebrowser Executable file

Binary file not shown.

4
src/backend/frontend/dist/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -1,78 +1,62 @@
package search
import (
"mime"
"path/filepath"
"regexp"
"strings"
)
var (
typeRegexp = regexp.MustCompile(`type:(\w+)`)
)
var typeRegexp = regexp.MustCompile(`type:(\w+)`)
var documentTypes = []string{
".word",
".pdf",
".txt",
}
var compressedFile = []string{
".7z",
".rar",
".zip",
".tar",
".tar.gz",
".tar.xz",
}
type searchOptions struct {
CaseSensitive bool
Conditions []condition
Conditions map[string]bool
Terms []string
}
type condition func(path string) bool
func extensionCondition(extension string) condition {
return func(path string) bool {
return filepath.Ext(path) == "."+extension
}
}
func imageCondition(path string) bool {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
return strings.HasPrefix(mimetype, "image")
}
func audioCondition(path string) bool {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
return strings.HasPrefix(mimetype, "audio")
}
func videoCondition(path string) bool {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
return strings.HasPrefix(mimetype, "video")
}
func ParseSearch(value string) *searchOptions {
opts := &searchOptions{
CaseSensitive: strings.Contains(value, "case:sensitive"),
Conditions: []condition{},
Conditions: map[string]bool{
"exact": strings.Contains(value, "case:exact"),
},
Terms: []string{},
}
// removes the options from the value
value = strings.Replace(value, "case:insensitive", "", -1)
value = strings.Replace(value, "case:sensitive", "", -1)
value = strings.Replace(value, "case:exact", "", -1)
value = strings.Replace(value, "case:exact", "", -1)
value = strings.TrimSpace(value)
types := typeRegexp.FindAllStringSubmatch(value, -1)
for _, t := range types {
if len(t) == 1 {
for _, filterType := range types {
if len(filterType) == 1 {
continue
}
switch t[1] {
switch filterType[1] {
case "image":
opts.Conditions = append(opts.Conditions, imageCondition)
opts.Conditions["image"] = true
case "audio", "music":
opts.Conditions = append(opts.Conditions, audioCondition)
opts.Conditions["audio"] = true
case "video":
opts.Conditions = append(opts.Conditions, videoCondition)
default:
opts.Conditions = append(opts.Conditions, extensionCondition(t[1]))
opts.Conditions["video"] = true
case "doc":
opts.Conditions["doc"] = true
case "zip":
opts.Conditions["zip"] = true
}
}
@ -81,14 +65,6 @@ func ParseSearch(value string) *searchOptions {
value = typeRegexp.ReplaceAllString(value, "")
}
// If it's case insensitive, put everything in lowercase.
if !opts.CaseSensitive {
value = strings.ToLower(value)
}
// Remove the spaces from the search value.
value = strings.TrimSpace(value)
if value == "" {
return opts
}

View File

@ -8,10 +8,11 @@ import (
"strings"
"sync"
"time"
"mime"
)
var (
rootPath = "/srv" // DO NOT include trailing slash
rootPath string = "/srv"
indexes map[string][]string
mutex sync.RWMutex
lastIndexed time.Time
@ -111,6 +112,9 @@ func SearchAllIndexes(search string, scope string) ([]string, []string) {
maximum := 100
count := 0
for _, searchTerm := range searchOptions.Terms {
if searchTerm == "" {
continue
}
// Iterate over the indexes
for dirName, v := range indexes {
if count > maximum {
@ -126,7 +130,7 @@ func SearchAllIndexes(search string, scope string) ([]string, []string) {
pathName = dirName + "/" + pathName
}
// Check if the path name contains the search term
if !containsSearchTerm(pathName, searchTerm, searchOptions.conditions) {
if !containsSearchTerm(pathName, searchTerm, searchOptions.Conditions) {
continue
}
pathName = scopedPathNameFilter(pathName, scope)
@ -137,7 +141,7 @@ func SearchAllIndexes(search string, scope string) ([]string, []string) {
matchingFiles = append(matchingFiles, pathName)
}
// Check if the path name contains the search term
if !containsSearchTerm(dirName, searchTerm, searchOptions.conditions) {
if !containsSearchTerm(dirName, searchTerm, searchOptions.Conditions) {
continue
}
pathName := scopedPathNameFilter(dirName, scope)
@ -173,13 +177,51 @@ func scopedPathNameFilter(pathName string, scope string) string {
return pathName
}
func containsSearchTerm(pathName string, searchTerm string, conditions []string) bool {
func containsSearchTerm(pathName string, searchTerm string, conditions map[string]bool) bool {
path := getLastPathComponent(pathName)
// Perform case-insensitive search
pathNameLower := strings.ToLower(path)
searchTermLower := strings.ToLower(searchTerm)
return strings.Contains(pathNameLower, searchTermLower)
if !conditions["exact"] {
path = strings.ToLower(path)
searchTerm = strings.ToLower(searchTerm)
}
matchesCondition := true
if conditions["audio"] {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
matchesCondition = strings.HasPrefix(mimetype, "audio")
}
if conditions["video"] {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
matchesCondition = strings.HasPrefix(mimetype, "video")
}
if conditions["image"] {
extension := filepath.Ext(path)
mimetype := mime.TypeByExtension(extension)
matchesCondition = strings.HasPrefix(mimetype, "image")
}
if conditions["doc"] {
extension := filepath.Ext(path)
for _, typefile := range documentTypes {
if extension == typefile {
matchesCondition = true
continue
} else {
matchesCondition = false
}
}
}
if conditions["zip"] {
extension := filepath.Ext(path)
for _, typefile := range compressedFile {
if extension == typefile {
matchesCondition = true
continue
} else {
matchesCondition = false
}
}
}
return strings.Contains(path, searchTerm) && matchesCondition
}
func getLastPathComponent(path string) string {