Introduction
Currently, files are still tightly coupled with scenes, images and galleries. As the next step for making files more independent of their logical objects, we should introduce the ability to query files.
This is mostly for myself. However since I won’t get to it until I’m finished with the sidebar stuff, if you feel confident enough to start on this, please let me know.
Scope
This design covers the server-side only. While the frontend client will be considered in the graphql API design, the graphical design of any user interfaces should be discussed as a separate topic.
There will need to be a similar design done for folder querying, which I expect to be a smaller job. I will not be including its design here.
Design
graphql interface
input FingerprintFilterInput {
type: String!
value: String!
"Hamming distance - defaults to 0"
distance: Int
}
input VideoFileFilterInput {
resolution: ResolutionCriterionInput
orientation: OrientationCriterionInput
framerate: IntCriterionInput
bitrate: IntCriterionInput
video_codec: StringCriterionInput
audio_codec: StringCriterionInput
"in seconds"
duration: IntCriterionInput
captions: StringCriterionInput
interactive: Boolean
interactive_speed: IntCriterionInput
}
input ImageFileFilterType {
resolution: ResolutionCriterionInput
orientation: OrientationCriterionInput
}
input FileFilterType {
AND: FileFilterType
OR: FileFilterType
NOT: FileFilterType
path: StringCriterionInput
basename: StringCriterionInput
dir: StringCriterionInput
parent_folder: HierarchicalMultiCriterionInput
"Filter by modification time"
mod_time: TimestampCriterionInput
"Filter files that have an exact match available"
duplicated: PHashDuplicationCriterionInput
"find files based on hash"
hashes: [FingerprintFilterInput!]
video_file_filter: VideoFileFilterInput
image_file_filter: ImageFileFilterType
scene_count: IntCriterionInput
image_count: IntCriterionInput
gallery_count: IntCriterionInput
"Filter by related scenes that meet this criteria"
scenes_filter: SceneFilterType
"Filter by related images that meet this criteria"
images_filter: ImageFilterType
"Filter by related galleries that meet this criteria"
galleries_filter: GalleryFilterType
"Filter by creation time"
created_at: TimestampCriterionInput
"Filter by last update time"
updated_at: TimestampCriterionInput
}
type FindFilesResultType {
count: Int!
"Total megapixels of any image files"
megapixels: Float!
"Total duration in seconds of any video files"
duration: Float!
"Total file size in bytes"
filesize: Int!
files: [BaseFile!]!
}
type Query {
"Find a file by its id or path"
findFile(id: ID, path: String): BaseFile!
"Queries for Files"
findFiles(
file_filter: FileFilterType
filter: FindFilterType
ids: [ID!]
): FindFilesResultType!
}
We should consider adding dirname: String!
field to BaseFile
. This will return the path up to the basename. We will need to write a resolver for this. A folder: Folder!
would also be useful, but this will require a dataloader batch operation.
sqlite
package
FileStore
has Find
and FindByPath
defined already, so these can be used for findFile
.
Embarassingly, we actually have FileStore.Query
in the current code, but it’s not called by anything and is completely untested. Unit tests will need to be written for it. See scene_test.go
for a starting point.
FileQueryOptions
will need to add options for getting the total duration, megapixels, file size. FileQueryResult
will need results for these.
FileStore.makeQuery
should be rewritten to follow the conventions in SceneStore.makeQuery
. FileStore.Query
will need to be adjusted accordingly. q
handling will need to be changed to include fingerprints (see SceenStore.makeFilter
).
fileFilterHandler
will need to be declared in file_filter.go
. The scene_filter.go
code will do as a good starting point. image_filter.go
should also be used to reuse the image-specific filtering code.
Next steps
After this is complete, the next priority would be the folder querying functionality, then a proper think about how this would fit in the UI.
Feedback
Let me know if I missed something or anything seems incorrect.