mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 17:25:32 +00:00
Basis Suche Inhalte
This commit is contained in:
484
pages/suche.go
484
pages/suche.go
@@ -1,11 +1,9 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/app"
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||
@@ -23,9 +21,9 @@ const (
|
||||
URL_SUCHE = "/suche/{type}"
|
||||
URL_SUCHE_ALT = "/suche/{$}"
|
||||
DEFAULT_SUCHE = "/suche/baende"
|
||||
PARAM_QUERY = "q"
|
||||
PARAM_EXTENDED = "extended"
|
||||
TEMPLATE_SUCHE = "/suche/"
|
||||
PARAM_QUERY = "q"
|
||||
)
|
||||
|
||||
var availableTypes = []string{"baende", "beitraege"}
|
||||
@@ -60,6 +58,10 @@ func (p *SuchePage) Setup(router *router.Router[*core.RequestEvent], app core.Ap
|
||||
return p.SearchBaendeRequest(app, engine, e, *allparas)
|
||||
}
|
||||
|
||||
if allparas.IsBeitraegeSearch() {
|
||||
return p.SearchBeitraegeRequest(app, engine, e, *allparas)
|
||||
}
|
||||
|
||||
data := make(map[string]interface{})
|
||||
data["parameters"] = allparas
|
||||
return engine.Response200(e, p.Template+paras.Collection+"/", data, p.Layout)
|
||||
@@ -72,10 +74,10 @@ func (p *SuchePage) SimpleSearchReihenRequest(app core.App, engine *templating.E
|
||||
return engine.Response404(e, nil, nil)
|
||||
}
|
||||
|
||||
func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
||||
func (p *SuchePage) SearchBeitraegeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
||||
data := make(map[string]interface{})
|
||||
|
||||
result, err := SimpleSearchBaende(app, params)
|
||||
result, err := NewSearchBeitraege(app, params)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, nil)
|
||||
}
|
||||
@@ -85,38 +87,20 @@ func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine,
|
||||
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)
|
||||
}
|
||||
|
||||
const (
|
||||
BEITRAEGE_PARAM_ALM_NR = "nr"
|
||||
BEITRAEGE_PARAM_TITLE = "title"
|
||||
BEITRAEGE_PARAM_INCIPT = "incipit"
|
||||
BEITRAEGE_PARAM_PERSONS = "persons"
|
||||
BEITRAEGE_PARAM_ANNOTATIONS = "annotations"
|
||||
// INFO: this is expanded search only:
|
||||
BEITRAEGE_PARAM_PSEUDONYMS = "pseudonyms"
|
||||
// INFO: these are filter types & expanded search:
|
||||
BEITRAEGE_PARAM_TYPE = "type"
|
||||
BEITRAEGE_PARAM_SCANS = "scans"
|
||||
func (p *SuchePage) SearchBaendeRequest(app core.App, engine *templating.Engine, e *core.RequestEvent, params SearchParameters) error {
|
||||
data := make(map[string]interface{})
|
||||
|
||||
REIHEN_PARAM_TITLE = "title"
|
||||
REIHEN_PARAM_ANNOTATIONS = "annotations"
|
||||
REIHEN_PARAM_REFERENCES = "references"
|
||||
result, err := NewSearchBaende(app, params)
|
||||
if err != nil {
|
||||
return engine.Response404(e, err, nil)
|
||||
}
|
||||
|
||||
BAENDE_PARAM_ALM_NR = "alm"
|
||||
BAENDE_PARAM_TITLE = "title"
|
||||
BAENDE_PARAM_SERIES = "series"
|
||||
BAENDE_PARAM_PERSONS = "persons"
|
||||
BAENDE_PARAM_PLACES = "places"
|
||||
BAENDE_PARAM_REFS = "references"
|
||||
BAENDE_PARAM_ANNOTATIONS = "annotations"
|
||||
BAENDE_PARAM_YEAR = "year"
|
||||
// INFO: this is expanded search only:
|
||||
BAENDE_PARAM_PSEUDONYMS = "pseudonyms"
|
||||
// INFO: this is a filter type & expanded search:
|
||||
BAENDE_PARAM_STATE = "state" // STATE: "full" "partial" "none"
|
||||
)
|
||||
data["parameters"] = params
|
||||
data["result"] = result
|
||||
return engine.Response200(e, p.Template+params.Collection+"/", data, p.Layout)
|
||||
}
|
||||
|
||||
var ErrInvalidCollectionType = fmt.Errorf("Invalid collection type")
|
||||
var ErrNoQuery = fmt.Errorf("No query")
|
||||
|
||||
type Parameters struct {
|
||||
Extended bool
|
||||
@@ -145,437 +129,3 @@ func NewParameters(e *core.RequestEvent) (*Parameters, error) {
|
||||
func (p *Parameters) NormalizeQuery() dbmodels.Query {
|
||||
return dbmodels.NormalizeQuery(p.Query)
|
||||
}
|
||||
|
||||
type SearchParameters struct {
|
||||
Parameters
|
||||
Sort string
|
||||
|
||||
Annotations bool
|
||||
Persons bool
|
||||
Title bool
|
||||
Series bool
|
||||
Places bool
|
||||
Refs bool
|
||||
Year bool
|
||||
|
||||
AnnotationsString string
|
||||
PersonsString string
|
||||
TitleString string
|
||||
AlmString string
|
||||
SeriesString string
|
||||
PlacesString string
|
||||
RefsString string
|
||||
YearString string
|
||||
|
||||
TypeFilter string
|
||||
}
|
||||
|
||||
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
||||
title := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE) == "on"
|
||||
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
||||
persons := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS) == "on"
|
||||
places := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES) == "on"
|
||||
refs := e.Request.URL.Query().Get(BAENDE_PARAM_REFS) == "on"
|
||||
annotations := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS) == "on"
|
||||
year := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR) == "on"
|
||||
|
||||
almstring := e.Request.URL.Query().Get(BAENDE_PARAM_ALM_NR + "string")
|
||||
|
||||
titlestring := e.Request.URL.Query().Get(BAENDE_PARAM_TITLE + "string")
|
||||
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
||||
personsstring := e.Request.URL.Query().Get(BAENDE_PARAM_PERSONS + "string")
|
||||
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
||||
annotationsstring := e.Request.URL.Query().Get(BAENDE_PARAM_ANNOTATIONS + "string")
|
||||
yearstring := e.Request.URL.Query().Get(BAENDE_PARAM_YEAR + "string")
|
||||
|
||||
refss := e.Request.URL.Query().Get(BAENDE_PARAM_REFS + "string")
|
||||
if refss != "" {
|
||||
refss = "\"" + refss + "\""
|
||||
}
|
||||
|
||||
sort := e.Request.URL.Query().Get("sort")
|
||||
if sort == "" {
|
||||
sort = "year"
|
||||
}
|
||||
|
||||
return &SearchParameters{
|
||||
Parameters: p,
|
||||
Sort: sort,
|
||||
// INFO: Common parameters
|
||||
Title: title,
|
||||
Persons: persons,
|
||||
Annotations: annotations,
|
||||
|
||||
// INFO: Baende parameters
|
||||
Places: places,
|
||||
Refs: refs,
|
||||
Year: year,
|
||||
Series: series,
|
||||
|
||||
// INFO: Expanded search
|
||||
AlmString: almstring,
|
||||
TitleString: titlestring,
|
||||
SeriesString: seriesstring,
|
||||
PersonsString: personsstring,
|
||||
PlacesString: placesstring,
|
||||
RefsString: refss,
|
||||
AnnotationsString: annotationsstring,
|
||||
YearString: yearstring,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p SearchParameters) AllSearchTerms() string {
|
||||
res := []string{}
|
||||
res = append(res, p.includedParams(p.Query)...)
|
||||
res = append(res, p.includedParams(p.AnnotationsString)...)
|
||||
res = append(res, p.includedParams(p.PersonsString)...)
|
||||
res = append(res, p.includedParams(p.TitleString)...)
|
||||
res = append(res, p.includedParams(p.SeriesString)...)
|
||||
res = append(res, p.includedParams(p.PlacesString)...)
|
||||
res = append(res, p.includedParams(p.RefsString)...)
|
||||
res = append(res, p.includedParams(p.YearString)...)
|
||||
res = append(res, p.AlmString)
|
||||
return strings.Join(res, " ")
|
||||
}
|
||||
|
||||
func (p SearchParameters) includedParams(q string) []string {
|
||||
res := []string{}
|
||||
que := dbmodels.NormalizeQuery(q)
|
||||
for _, qq := range que.Include {
|
||||
res = append(res, qq)
|
||||
}
|
||||
for _, qq := range que.UnsafeI {
|
||||
res = append(res, qq)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (p SearchParameters) ToQueryParams() string {
|
||||
q := "?"
|
||||
|
||||
// TODO: use variables, url escape
|
||||
if p.Extended {
|
||||
q += "extended=true"
|
||||
}
|
||||
|
||||
if p.Query != "" {
|
||||
q += fmt.Sprintf("q=%s", p.Query)
|
||||
|
||||
if p.Title {
|
||||
q += "&title=on"
|
||||
}
|
||||
if p.Persons {
|
||||
q += "&persons=on"
|
||||
}
|
||||
if p.Annotations {
|
||||
q += "&annotations=on"
|
||||
}
|
||||
if p.Series {
|
||||
q += "&series=on"
|
||||
}
|
||||
if p.Places {
|
||||
q += "&places=on"
|
||||
}
|
||||
if p.Refs {
|
||||
q += "&references=on"
|
||||
}
|
||||
if p.Year {
|
||||
q += "&year=on"
|
||||
}
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
||||
}
|
||||
if p.AnnotationsString != "" {
|
||||
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
||||
}
|
||||
if p.PersonsString != "" {
|
||||
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
||||
}
|
||||
if p.TitleString != "" {
|
||||
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||
}
|
||||
if p.SeriesString != "" {
|
||||
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
||||
}
|
||||
if p.PlacesString != "" {
|
||||
q += fmt.Sprintf("&placesstring=%s", p.PlacesString)
|
||||
}
|
||||
if p.RefsString != "" {
|
||||
q += fmt.Sprintf("&refsstring=%s", p.RefsString)
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (p SearchParameters) IsBaendeSearch() bool {
|
||||
return p.Collection == "baende" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "")
|
||||
}
|
||||
|
||||
func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
||||
ret := []dbmodels.FTS5QueryRequest{}
|
||||
if p.Query != "" {
|
||||
fields := []string{dbmodels.ID_FIELD}
|
||||
if p.Title {
|
||||
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
||||
fields = append(fields,
|
||||
dbmodels.TITLE_STMT_FIELD,
|
||||
dbmodels.SUBTITLE_STMT_FIELD,
|
||||
dbmodels.INCIPIT_STMT_FIELD,
|
||||
dbmodels.VARIANT_TITLE_FIELD,
|
||||
dbmodels.PARALLEL_TITLE_FIELD,
|
||||
)
|
||||
}
|
||||
if p.Series {
|
||||
fields = append(fields, dbmodels.SERIES_TABLE)
|
||||
}
|
||||
if p.Persons {
|
||||
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
||||
}
|
||||
if p.Places {
|
||||
fields = append(fields, dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD)
|
||||
}
|
||||
if p.Refs {
|
||||
fields = append(fields, dbmodels.REFERENCES_FIELD)
|
||||
}
|
||||
if p.Annotations {
|
||||
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
||||
}
|
||||
if p.Year {
|
||||
fields = append(fields, dbmodels.YEAR_FIELD)
|
||||
}
|
||||
|
||||
que := p.NormalizeQuery()
|
||||
req := dbmodels.IntoQueryRequests(fields, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.AnnotationsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.PersonsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.TitleString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.INCIPIT_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.SeriesString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.SeriesString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.SERIES_TABLE}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.PlacesString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.PlacesString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.RefsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.RefsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.REFERENCES_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.YearString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p SearchParameters) IsExtendedSearch() bool {
|
||||
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != ""
|
||||
}
|
||||
|
||||
func (p SearchParameters) NormalizeQuery() dbmodels.Query {
|
||||
return dbmodels.NormalizeQuery(p.Query)
|
||||
}
|
||||
|
||||
type SearchResultBaende struct {
|
||||
Queries []dbmodels.FTS5QueryRequest
|
||||
|
||||
// these are the sorted IDs for hits
|
||||
Hits []string
|
||||
Series map[string]*dbmodels.Series // <- Key: Series ID
|
||||
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||
Places map[string]*dbmodels.Place // <- All places, Key: Place IDs
|
||||
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||
|
||||
// INFO: this is as they say doppelt gemoppelt bc of a logic error i made while tired
|
||||
EntriesSeries map[string][]*dbmodels.REntriesSeries // <- Key: Entry ID
|
||||
SeriesEntries map[string][]*dbmodels.REntriesSeries // <- Key: Series ID
|
||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
||||
}
|
||||
|
||||
func EmptyResultBaende() *SearchResultBaende {
|
||||
return &SearchResultBaende{
|
||||
Hits: []string{},
|
||||
Series: make(map[string]*dbmodels.Series),
|
||||
Entries: make(map[string]*dbmodels.Entry),
|
||||
Places: make(map[string]*dbmodels.Place),
|
||||
Agents: make(map[string]*dbmodels.Agent),
|
||||
EntriesSeries: make(map[string][]*dbmodels.REntriesSeries),
|
||||
SeriesEntries: make(map[string][]*dbmodels.REntriesSeries),
|
||||
EntriesAgents: make(map[string][]*dbmodels.REntriesAgents),
|
||||
}
|
||||
}
|
||||
|
||||
func SimpleSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
||||
entries := []*dbmodels.Entry{}
|
||||
queries := params.FieldSetBaende()
|
||||
|
||||
if params.AlmString != "" {
|
||||
e, err := dbmodels.Entries_MusenalmID(app, params.AlmString)
|
||||
if err != nil && err == sql.ErrNoRows {
|
||||
return EmptyResultBaende(), nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries = append(entries, e)
|
||||
} else {
|
||||
if len(queries) == 0 {
|
||||
return nil, ErrNoQuery
|
||||
}
|
||||
|
||||
ids, err := dbmodels.FTS5Search(app, dbmodels.ENTRIES_TABLE, queries...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resultids := []any{}
|
||||
for _, id := range ids {
|
||||
resultids = append(resultids, id.ID)
|
||||
}
|
||||
|
||||
e, err := dbmodels.Entries_IDs(app, resultids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries = e
|
||||
}
|
||||
|
||||
resultids := []any{}
|
||||
for _, entry := range entries {
|
||||
resultids = append(resultids, entry.Id)
|
||||
}
|
||||
|
||||
entriesmap := make(map[string]*dbmodels.Entry)
|
||||
for _, entry := range entries {
|
||||
entriesmap[entry.Id] = entry
|
||||
}
|
||||
|
||||
series, relations, err := Series_Entries(app, entries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seriesmap := make(map[string]*dbmodels.Series)
|
||||
for _, s := range series {
|
||||
seriesmap[s.Id] = s
|
||||
}
|
||||
|
||||
relationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||
invrelationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||
for _, r := range relations {
|
||||
invrelationsmap[r.Series()] = append(invrelationsmap[r.Series()], r)
|
||||
relationsmap[r.Entry()] = append(relationsmap[r.Entry()], r)
|
||||
}
|
||||
|
||||
agents, arelations, err := Agents_Entries_IDs(app, resultids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
agentsmap := make(map[string]*dbmodels.Agent)
|
||||
for _, a := range agents {
|
||||
agentsmap[a.Id] = a
|
||||
}
|
||||
|
||||
relationsagentsmap := make(map[string][]*dbmodels.REntriesAgents)
|
||||
for _, r := range arelations {
|
||||
relationsagentsmap[r.Entry()] = append(relationsagentsmap[r.Entry()], r)
|
||||
}
|
||||
|
||||
placesids := []any{}
|
||||
for _, entry := range entries {
|
||||
for _, place := range entry.Places() {
|
||||
placesids = append(placesids, place)
|
||||
}
|
||||
}
|
||||
|
||||
places, err := dbmodels.Places_IDs(app, placesids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
placesmap := make(map[string]*dbmodels.Place)
|
||||
for _, place := range places {
|
||||
placesmap[place.Id] = place
|
||||
}
|
||||
|
||||
hits := []string{}
|
||||
if params.Sort == "series" {
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
for _, s := range series {
|
||||
hits = append(hits, s.Id)
|
||||
}
|
||||
} else {
|
||||
dbmodels.Sort_Entries_Year_Title(entries)
|
||||
for _, e := range entries {
|
||||
hits = append(hits, e.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return &SearchResultBaende{
|
||||
Hits: hits,
|
||||
Series: seriesmap,
|
||||
Entries: entriesmap,
|
||||
Places: placesmap,
|
||||
Agents: agentsmap,
|
||||
EntriesSeries: relationsmap,
|
||||
SeriesEntries: invrelationsmap,
|
||||
EntriesAgents: relationsagentsmap,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (r SearchResultBaende) Count() int {
|
||||
return len(r.Entries)
|
||||
}
|
||||
|
||||
func (r SearchResultBaende) SeriesCount() int {
|
||||
return len(r.Series)
|
||||
}
|
||||
|
||||
func Agents_Entries_IDs(app core.App, ids []any) ([]*dbmodels.Agent, []*dbmodels.REntriesAgents, error) {
|
||||
relations, err := dbmodels.REntriesAgents_Entries(app, ids)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
agentids := []any{}
|
||||
for _, r := range relations {
|
||||
agentids = append(agentids, r.Agent())
|
||||
}
|
||||
|
||||
agents, err := dbmodels.Agents_IDs(app, agentids)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return agents, relations, nil
|
||||
}
|
||||
|
||||
186
pages/suche_baende.go
Normal file
186
pages/suche_baende.go
Normal file
@@ -0,0 +1,186 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
type SearchResultBaende struct {
|
||||
Queries []dbmodels.FTS5QueryRequest
|
||||
|
||||
// these are the sorted IDs for hits
|
||||
Hits []string
|
||||
Series map[string]*dbmodels.Series // <- Key: Series ID
|
||||
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||
Places map[string]*dbmodels.Place // <- All places, Key: Place IDs
|
||||
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||
|
||||
// INFO: this is as they say doppelt gemoppelt bc of a logic error i made while tired
|
||||
EntriesSeries map[string][]*dbmodels.REntriesSeries // <- Key: Entry ID
|
||||
SeriesEntries map[string][]*dbmodels.REntriesSeries // <- Key: Series ID
|
||||
EntriesAgents map[string][]*dbmodels.REntriesAgents // <- Key: Entry ID
|
||||
}
|
||||
|
||||
func EmptyResultBaende() *SearchResultBaende {
|
||||
return &SearchResultBaende{
|
||||
Hits: []string{},
|
||||
Series: make(map[string]*dbmodels.Series),
|
||||
Entries: make(map[string]*dbmodels.Entry),
|
||||
Places: make(map[string]*dbmodels.Place),
|
||||
Agents: make(map[string]*dbmodels.Agent),
|
||||
EntriesSeries: make(map[string][]*dbmodels.REntriesSeries),
|
||||
SeriesEntries: make(map[string][]*dbmodels.REntriesSeries),
|
||||
EntriesAgents: make(map[string][]*dbmodels.REntriesAgents),
|
||||
}
|
||||
}
|
||||
|
||||
func NewSearchBaende(app core.App, params SearchParameters) (*SearchResultBaende, error) {
|
||||
entries := []*dbmodels.Entry{}
|
||||
queries := params.FieldSetBaende()
|
||||
|
||||
if params.AlmString != "" {
|
||||
e, err := dbmodels.Entries_MusenalmID(app, params.AlmString)
|
||||
if err != nil && err == sql.ErrNoRows {
|
||||
return EmptyResultBaende(), nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
entries = append(entries, e)
|
||||
} else {
|
||||
if len(queries) == 0 {
|
||||
return nil, ErrNoQuery
|
||||
}
|
||||
|
||||
ids, err := dbmodels.FTS5Search(app, dbmodels.ENTRIES_TABLE, queries...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(ids) == 0 {
|
||||
return EmptyResultBaende(), nil
|
||||
}
|
||||
|
||||
resultids := []any{}
|
||||
for _, id := range ids {
|
||||
resultids = append(resultids, id.ID)
|
||||
}
|
||||
|
||||
e, err := dbmodels.Entries_IDs(app, resultids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries = e
|
||||
}
|
||||
|
||||
resultids := []any{}
|
||||
for _, entry := range entries {
|
||||
resultids = append(resultids, entry.Id)
|
||||
}
|
||||
|
||||
entriesmap := make(map[string]*dbmodels.Entry)
|
||||
for _, entry := range entries {
|
||||
entriesmap[entry.Id] = entry
|
||||
}
|
||||
|
||||
series, relations, err := Series_Entries(app, entries)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
seriesmap := make(map[string]*dbmodels.Series)
|
||||
for _, s := range series {
|
||||
seriesmap[s.Id] = s
|
||||
}
|
||||
|
||||
relationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||
invrelationsmap := make(map[string][]*dbmodels.REntriesSeries)
|
||||
for _, r := range relations {
|
||||
invrelationsmap[r.Series()] = append(invrelationsmap[r.Series()], r)
|
||||
relationsmap[r.Entry()] = append(relationsmap[r.Entry()], r)
|
||||
}
|
||||
|
||||
agents, arelations, err := Agents_Entries_IDs(app, resultids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
agentsmap := make(map[string]*dbmodels.Agent)
|
||||
for _, a := range agents {
|
||||
agentsmap[a.Id] = a
|
||||
}
|
||||
|
||||
relationsagentsmap := make(map[string][]*dbmodels.REntriesAgents)
|
||||
for _, r := range arelations {
|
||||
relationsagentsmap[r.Entry()] = append(relationsagentsmap[r.Entry()], r)
|
||||
}
|
||||
|
||||
placesids := []any{}
|
||||
for _, entry := range entries {
|
||||
for _, place := range entry.Places() {
|
||||
placesids = append(placesids, place)
|
||||
}
|
||||
}
|
||||
|
||||
places, err := dbmodels.Places_IDs(app, placesids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
placesmap := make(map[string]*dbmodels.Place)
|
||||
for _, place := range places {
|
||||
placesmap[place.Id] = place
|
||||
}
|
||||
|
||||
hits := []string{}
|
||||
if params.Sort == "series" {
|
||||
dbmodels.Sort_Series_Title(series)
|
||||
for _, s := range series {
|
||||
hits = append(hits, s.Id)
|
||||
}
|
||||
} else {
|
||||
dbmodels.Sort_Entries_Year_Title(entries)
|
||||
for _, e := range entries {
|
||||
hits = append(hits, e.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return &SearchResultBaende{
|
||||
Hits: hits,
|
||||
Series: seriesmap,
|
||||
Entries: entriesmap,
|
||||
Places: placesmap,
|
||||
Agents: agentsmap,
|
||||
EntriesSeries: relationsmap,
|
||||
SeriesEntries: invrelationsmap,
|
||||
EntriesAgents: relationsagentsmap,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (r SearchResultBaende) Count() int {
|
||||
return len(r.Entries)
|
||||
}
|
||||
|
||||
func (r SearchResultBaende) SeriesCount() int {
|
||||
return len(r.Series)
|
||||
}
|
||||
|
||||
func Agents_Entries_IDs(app core.App, ids []any) ([]*dbmodels.Agent, []*dbmodels.REntriesAgents, error) {
|
||||
relations, err := dbmodels.REntriesAgents_Entries(app, ids)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
agentids := []any{}
|
||||
for _, r := range relations {
|
||||
agentids = append(agentids, r.Agent())
|
||||
}
|
||||
|
||||
agents, err := dbmodels.Agents_IDs(app, agentids)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return agents, relations, nil
|
||||
}
|
||||
188
pages/suche_beitraege.go
Normal file
188
pages/suche_beitraege.go
Normal file
@@ -0,0 +1,188 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/helpers/datatypes"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT_PAGESIZE = 80
|
||||
)
|
||||
|
||||
type SearchResultBeitraege struct {
|
||||
Queries []dbmodels.FTS5QueryRequest
|
||||
|
||||
// these are the sorted IDs for hits
|
||||
Hits []string
|
||||
Entries map[string]*dbmodels.Entry // <- Key: Entry ID
|
||||
Agents map[string]*dbmodels.Agent // <- Key: Agent IDs
|
||||
Contents map[string][]*dbmodels.Content // <- Key: Entry ID, or year
|
||||
|
||||
ContentsAgents map[string][]*dbmodels.RContentsAgents // <- Key: Content ID
|
||||
Pages []int
|
||||
}
|
||||
|
||||
func EmptyResultBeitraege() *SearchResultBeitraege {
|
||||
return &SearchResultBeitraege{
|
||||
Hits: []string{},
|
||||
Entries: make(map[string]*dbmodels.Entry),
|
||||
Agents: make(map[string]*dbmodels.Agent),
|
||||
Contents: make(map[string][]*dbmodels.Content),
|
||||
ContentsAgents: make(map[string][]*dbmodels.RContentsAgents),
|
||||
}
|
||||
}
|
||||
|
||||
func NewSearchBeitraege(app core.App, params SearchParameters) (*SearchResultBeitraege, error) {
|
||||
contents := []*dbmodels.Content{}
|
||||
queries := params.FieldSetBeitraege()
|
||||
|
||||
if params.AlmString != "" {
|
||||
e, err := dbmodels.Contents_MusenalmID(app, params.AlmString)
|
||||
if err != nil && err == sql.ErrNoRows {
|
||||
return EmptyResultBeitraege(), nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contents = append(contents, e)
|
||||
} else {
|
||||
if len(queries) == 0 {
|
||||
return nil, ErrNoQuery
|
||||
}
|
||||
|
||||
hits, err := dbmodels.FTS5Search(app, dbmodels.CONTENTS_TABLE, queries...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(hits) == 0 {
|
||||
return EmptyResultBeitraege(), nil
|
||||
}
|
||||
|
||||
ids := []any{}
|
||||
for _, hit := range hits {
|
||||
ids = append(ids, hit.ID)
|
||||
}
|
||||
|
||||
cs, err := dbmodels.Contents_IDs(app, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contents = append(contents, cs...)
|
||||
}
|
||||
|
||||
resultids := []any{}
|
||||
resultentryids := []string{}
|
||||
for _, content := range contents {
|
||||
resultids = append(resultids, content.Id)
|
||||
resultentryids = append(resultentryids, content.Entry())
|
||||
}
|
||||
|
||||
entries, err := dbmodels.Entries_IDs(app, datatypes.ToAny(resultentryids))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if params.Sort == "year" {
|
||||
dbmodels.Sort_Entries_Year_Title(entries)
|
||||
} else {
|
||||
dbmodels.Sort_Entries_Title_Year(entries)
|
||||
}
|
||||
|
||||
arels, err := dbmodels.RContentsAgents_Contents(app, resultids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aids := []any{}
|
||||
for _, a := range arels {
|
||||
aids = append(aids, a.Agent())
|
||||
}
|
||||
|
||||
agents, err := dbmodels.Agents_IDs(app, aids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
contentsmap := make(map[string][]*dbmodels.Content)
|
||||
for _, c := range contents {
|
||||
contentsmap[c.Entry()] = append(contentsmap[c.Entry()], c)
|
||||
}
|
||||
|
||||
contentsagents := make(map[string][]*dbmodels.RContentsAgents)
|
||||
for _, a := range arels {
|
||||
contentsagents[a.Content()] = append(contentsagents[a.Content()], a)
|
||||
}
|
||||
|
||||
agentsmap := make(map[string]*dbmodels.Agent)
|
||||
for _, a := range agents {
|
||||
agentsmap[a.Id] = a
|
||||
}
|
||||
|
||||
entriesmap := make(map[string]*dbmodels.Entry)
|
||||
for _, e := range entries {
|
||||
entriesmap[e.Id] = e
|
||||
}
|
||||
|
||||
hits := []string{}
|
||||
for _, e := range entries {
|
||||
hits = append(hits, e.Id)
|
||||
}
|
||||
|
||||
pages := PagesEntries(hits, contentsmap, DEFAULT_PAGESIZE)
|
||||
if params.Page < 1 || params.Page > len(pages) {
|
||||
params.Page = 1
|
||||
}
|
||||
|
||||
if params.Page == len(pages) {
|
||||
hits = hits[pages[params.Page-1]:]
|
||||
} else {
|
||||
hits = hits[pages[params.Page-1]:pages[params.Page]]
|
||||
}
|
||||
|
||||
return &SearchResultBeitraege{
|
||||
Queries: queries,
|
||||
Hits: hits,
|
||||
Entries: entriesmap,
|
||||
Agents: agentsmap,
|
||||
Contents: contentsmap,
|
||||
ContentsAgents: contentsagents,
|
||||
Pages: pages,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *SearchResultBeitraege) CountEntries() int {
|
||||
return len(p.Entries)
|
||||
}
|
||||
|
||||
func (p *SearchResultBeitraege) Count() int {
|
||||
cnt := 0
|
||||
for _, c := range p.Contents {
|
||||
cnt += len(c)
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
func (p *SearchResultBeitraege) PagesCount() int {
|
||||
return len(p.Pages) - 1
|
||||
}
|
||||
|
||||
func PagesEntries[T any](hits []string, hitmap map[string][]*T, pagesize int) []int {
|
||||
ret := []int{0}
|
||||
m := 0
|
||||
for i, hit := range hits {
|
||||
m += len(hitmap[hit])
|
||||
if m >= pagesize {
|
||||
ret = append(ret, i)
|
||||
m = 0
|
||||
}
|
||||
}
|
||||
|
||||
if m > 0 {
|
||||
ret = append(ret, len(hits))
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
465
pages/suche_parameters.go
Normal file
465
pages/suche_parameters.go
Normal file
@@ -0,0 +1,465 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/musenalm/dbmodels"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
var ErrNoQuery = fmt.Errorf("No query")
|
||||
|
||||
const (
|
||||
SEARCH_PARAM_ALM_NR = "alm"
|
||||
SEARCH_PARAM_TITLE = "title"
|
||||
SEARCH_PARAM_PERSONS = "persons"
|
||||
SEARCH_PARAM_ANNOTATIONS = "annotations"
|
||||
SEARCH_PARAM_YEAR = "year"
|
||||
BAENDE_PARAM_PLACES = "places"
|
||||
BAENDE_PARAM_SERIES = "series"
|
||||
BAENDE_PARAM_REFS = "references"
|
||||
BEITRAEGE_PARAM_ENTRY = "entry"
|
||||
BEITRAEGE_PARAM_INCIPT = "incipit"
|
||||
)
|
||||
|
||||
type SearchParameters struct {
|
||||
Parameters
|
||||
Sort string // year, entry,
|
||||
|
||||
Annotations bool
|
||||
Persons bool
|
||||
Title bool
|
||||
Series bool
|
||||
Places bool
|
||||
Refs bool
|
||||
Year bool
|
||||
Entry bool
|
||||
Incipit bool
|
||||
|
||||
AnnotationsString string
|
||||
PersonsString string
|
||||
TitleString string
|
||||
AlmString string
|
||||
SeriesString string
|
||||
PlacesString string
|
||||
RefsString string
|
||||
YearString string
|
||||
EntryString string
|
||||
IncipitString string
|
||||
|
||||
Page int
|
||||
}
|
||||
|
||||
func NewSearchParameters(e *core.RequestEvent, p Parameters) (*SearchParameters, error) {
|
||||
almstring := e.Request.URL.Query().Get(SEARCH_PARAM_ALM_NR + "string")
|
||||
title := e.Request.URL.Query().Get(SEARCH_PARAM_TITLE) == "on"
|
||||
titlestring := e.Request.URL.Query().Get(SEARCH_PARAM_TITLE + "string")
|
||||
persons := e.Request.URL.Query().Get(SEARCH_PARAM_PERSONS) == "on"
|
||||
personsstring := e.Request.URL.Query().Get(SEARCH_PARAM_PERSONS + "string")
|
||||
annotations := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS) == "on"
|
||||
annotationsstring := e.Request.URL.Query().Get(SEARCH_PARAM_ANNOTATIONS + "string")
|
||||
year := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR) == "on"
|
||||
yearstring := e.Request.URL.Query().Get(SEARCH_PARAM_YEAR + "string")
|
||||
|
||||
series := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES) == "on"
|
||||
seriesstring := e.Request.URL.Query().Get(BAENDE_PARAM_SERIES + "string")
|
||||
places := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES) == "on"
|
||||
placesstring := e.Request.URL.Query().Get(BAENDE_PARAM_PLACES + "string")
|
||||
refs := e.Request.URL.Query().Get(BAENDE_PARAM_REFS) == "on"
|
||||
|
||||
refss := e.Request.URL.Query().Get(BAENDE_PARAM_REFS + "string")
|
||||
if refss != "" {
|
||||
refss = "\"" + refss + "\""
|
||||
}
|
||||
|
||||
incipit := e.Request.URL.Query().Get(BEITRAEGE_PARAM_INCIPT) == "on"
|
||||
incipitstring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_INCIPT + "string")
|
||||
entry := e.Request.URL.Query().Get(BEITRAEGE_PARAM_ENTRY) == "on"
|
||||
entrystring := e.Request.URL.Query().Get(BEITRAEGE_PARAM_ENTRY + "string")
|
||||
|
||||
sort := e.Request.URL.Query().Get("sort")
|
||||
if sort == "" {
|
||||
sort = "year"
|
||||
}
|
||||
|
||||
page := e.Request.URL.Query().Get("page")
|
||||
if page == "" {
|
||||
page = "1"
|
||||
}
|
||||
|
||||
pageint, err := strconv.Atoi(page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SearchParameters{
|
||||
Parameters: p,
|
||||
Sort: sort,
|
||||
Page: pageint,
|
||||
|
||||
// INFO: Common parameters
|
||||
Title: title,
|
||||
Persons: persons,
|
||||
Annotations: annotations,
|
||||
Year: year,
|
||||
|
||||
// INFO: Baende parameters
|
||||
Places: places,
|
||||
Refs: refs,
|
||||
Series: series,
|
||||
|
||||
// INFO: Beitraege parameters
|
||||
Entry: entry,
|
||||
Incipit: incipit,
|
||||
|
||||
// INFO: Expanded search
|
||||
AlmString: almstring,
|
||||
TitleString: titlestring,
|
||||
SeriesString: seriesstring,
|
||||
PersonsString: personsstring,
|
||||
PlacesString: placesstring,
|
||||
RefsString: refss,
|
||||
AnnotationsString: annotationsstring,
|
||||
YearString: yearstring,
|
||||
EntryString: entrystring,
|
||||
IncipitString: incipitstring,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p SearchParameters) AllSearchTermsBaende() string {
|
||||
res := []string{}
|
||||
res = append(res, p.includedParams(p.Query)...)
|
||||
res = append(res, p.includedParams(p.AnnotationsString)...)
|
||||
res = append(res, p.includedParams(p.PersonsString)...)
|
||||
res = append(res, p.includedParams(p.TitleString)...)
|
||||
res = append(res, p.includedParams(p.SeriesString)...)
|
||||
res = append(res, p.includedParams(p.PlacesString)...)
|
||||
res = append(res, p.includedParams(p.RefsString)...)
|
||||
res = append(res, p.includedParams(p.YearString)...)
|
||||
res = append(res, p.AlmString)
|
||||
return strings.Join(res, " ")
|
||||
}
|
||||
|
||||
func (p SearchParameters) AllSearchTermsBeitraege() string {
|
||||
res := []string{}
|
||||
res = append(res, p.includedParams(p.Query)...)
|
||||
res = append(res, p.includedParams(p.AnnotationsString)...)
|
||||
res = append(res, p.includedParams(p.PersonsString)...)
|
||||
res = append(res, p.includedParams(p.TitleString)...)
|
||||
res = append(res, p.includedParams(p.YearString)...)
|
||||
res = append(res, p.includedParams(p.EntryString)...)
|
||||
res = append(res, p.includedParams(p.IncipitString)...)
|
||||
return strings.Join(res, " ")
|
||||
}
|
||||
|
||||
func (p SearchParameters) includedParams(q string) []string {
|
||||
res := []string{}
|
||||
que := dbmodels.NormalizeQuery(q)
|
||||
for _, qq := range que.Include {
|
||||
res = append(res, qq)
|
||||
}
|
||||
for _, qq := range que.UnsafeI {
|
||||
res = append(res, qq)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (p SearchParameters) ToQueryParamsBeitraege() string {
|
||||
q := "?"
|
||||
|
||||
if p.Extended {
|
||||
q += "extended=true"
|
||||
}
|
||||
|
||||
if p.Query != "" {
|
||||
q += fmt.Sprintf("q=%s", p.Query)
|
||||
|
||||
if p.Title {
|
||||
q += "&title=on"
|
||||
}
|
||||
|
||||
if p.Persons {
|
||||
q += "&persons=on"
|
||||
}
|
||||
|
||||
if p.Annotations {
|
||||
q += "&annotations=on"
|
||||
}
|
||||
|
||||
if p.Year {
|
||||
q += "&year=on"
|
||||
}
|
||||
|
||||
if p.Entry {
|
||||
q += "&entry=on"
|
||||
}
|
||||
|
||||
if p.Incipit {
|
||||
q += "&incipit=on"
|
||||
}
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
||||
}
|
||||
|
||||
if p.AnnotationsString != "" {
|
||||
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
||||
}
|
||||
|
||||
if p.PersonsString != "" {
|
||||
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
||||
}
|
||||
|
||||
if p.TitleString != "" {
|
||||
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||
}
|
||||
|
||||
if p.EntryString != "" {
|
||||
q += fmt.Sprintf("&entrystring=%s", p.EntryString)
|
||||
}
|
||||
|
||||
if p.IncipitString != "" {
|
||||
q += fmt.Sprintf("&incipitstring=%s", p.IncipitString)
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (p SearchParameters) ToQueryParamsBaende() string {
|
||||
q := "?"
|
||||
|
||||
// TODO: use variables, url escape
|
||||
if p.Extended {
|
||||
q += "extended=true"
|
||||
}
|
||||
|
||||
if p.Query != "" {
|
||||
q += fmt.Sprintf("q=%s", p.Query)
|
||||
|
||||
if p.Title {
|
||||
q += "&title=on"
|
||||
}
|
||||
if p.Persons {
|
||||
q += "&persons=on"
|
||||
}
|
||||
if p.Annotations {
|
||||
q += "&annotations=on"
|
||||
}
|
||||
if p.Series {
|
||||
q += "&series=on"
|
||||
}
|
||||
if p.Places {
|
||||
q += "&places=on"
|
||||
}
|
||||
if p.Refs {
|
||||
q += "&references=on"
|
||||
}
|
||||
if p.Year {
|
||||
q += "&year=on"
|
||||
}
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
q += fmt.Sprintf("&yearstring=%s", p.YearString)
|
||||
}
|
||||
if p.AnnotationsString != "" {
|
||||
q += fmt.Sprintf("&annotationsstring=%s", p.AnnotationsString)
|
||||
}
|
||||
if p.PersonsString != "" {
|
||||
q += fmt.Sprintf("&personsstring=%s", p.PersonsString)
|
||||
}
|
||||
if p.TitleString != "" {
|
||||
q += fmt.Sprintf("&titlestring=%s", p.TitleString)
|
||||
}
|
||||
if p.SeriesString != "" {
|
||||
q += fmt.Sprintf("&seriesstring=%s", p.SeriesString)
|
||||
}
|
||||
if p.PlacesString != "" {
|
||||
q += fmt.Sprintf("&placesstring=%s", p.PlacesString)
|
||||
}
|
||||
if p.RefsString != "" {
|
||||
q += fmt.Sprintf("&refsstring=%s", p.RefsString)
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (p SearchParameters) IsBeitraegeSearch() bool {
|
||||
return p.Collection == "beitraege" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.YearString != "" || p.EntryString != "" || p.IncipitString != "")
|
||||
}
|
||||
|
||||
func (p SearchParameters) IsBaendeSearch() bool {
|
||||
return p.Collection == "baende" && (p.Query != "" || p.AlmString != "" || p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "")
|
||||
}
|
||||
|
||||
func (p SearchParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequest {
|
||||
ret := []dbmodels.FTS5QueryRequest{}
|
||||
if p.Query != "" {
|
||||
fields := []string{dbmodels.ID_FIELD}
|
||||
if p.Title {
|
||||
fields = append(fields, dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD)
|
||||
}
|
||||
if p.Persons {
|
||||
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
||||
}
|
||||
if p.Annotations {
|
||||
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
||||
}
|
||||
if p.Year {
|
||||
fields = append(fields, dbmodels.YEAR_FIELD)
|
||||
}
|
||||
if p.Entry {
|
||||
fields = append(fields, dbmodels.ENTRIES_TABLE)
|
||||
}
|
||||
if p.Incipit {
|
||||
fields = append(fields, dbmodels.INCIPIT_STMT_FIELD)
|
||||
}
|
||||
|
||||
que := p.NormalizeQuery()
|
||||
req := dbmodels.IntoQueryRequests(fields, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.AnnotationsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.PersonsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.TitleString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.YearString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.EntryString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.EntryString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.ENTRIES_TABLE}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.IncipitString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.IncipitString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.INCIPIT_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p SearchParameters) FieldSetBaende() []dbmodels.FTS5QueryRequest {
|
||||
ret := []dbmodels.FTS5QueryRequest{}
|
||||
if p.Query != "" {
|
||||
fields := []string{dbmodels.ID_FIELD}
|
||||
if p.Title {
|
||||
// INFO: Preferred Title is not here to avoid hitting the Reihentitel
|
||||
fields = append(fields,
|
||||
dbmodels.TITLE_STMT_FIELD,
|
||||
dbmodels.SUBTITLE_STMT_FIELD,
|
||||
dbmodels.INCIPIT_STMT_FIELD,
|
||||
dbmodels.VARIANT_TITLE_FIELD,
|
||||
dbmodels.PARALLEL_TITLE_FIELD,
|
||||
)
|
||||
}
|
||||
if p.Series {
|
||||
fields = append(fields, dbmodels.SERIES_TABLE)
|
||||
}
|
||||
if p.Persons {
|
||||
fields = append(fields, dbmodels.RESPONSIBILITY_STMT_FIELD, dbmodels.AGENTS_TABLE)
|
||||
}
|
||||
if p.Places {
|
||||
fields = append(fields, dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD)
|
||||
}
|
||||
if p.Refs {
|
||||
fields = append(fields, dbmodels.REFERENCES_FIELD)
|
||||
}
|
||||
if p.Annotations {
|
||||
fields = append(fields, dbmodels.ANNOTATION_FIELD)
|
||||
}
|
||||
if p.Year {
|
||||
fields = append(fields, dbmodels.YEAR_FIELD)
|
||||
}
|
||||
|
||||
que := p.NormalizeQuery()
|
||||
req := dbmodels.IntoQueryRequests(fields, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.AnnotationsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.AnnotationsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.ANNOTATION_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.PersonsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.PersonsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.AGENTS_TABLE, dbmodels.RESPONSIBILITY_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.TitleString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.TitleString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.TITLE_STMT_FIELD, dbmodels.SUBTITLE_STMT_FIELD, dbmodels.INCIPIT_STMT_FIELD, dbmodels.VARIANT_TITLE_FIELD, dbmodels.PARALLEL_TITLE_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.SeriesString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.SeriesString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.SERIES_TABLE}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.PlacesString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.PlacesString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.PLACES_TABLE, dbmodels.PLACE_STMT_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.RefsString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.RefsString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.REFERENCES_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
if p.YearString != "" {
|
||||
que := dbmodels.NormalizeQuery(p.YearString)
|
||||
req := dbmodels.IntoQueryRequests([]string{dbmodels.YEAR_FIELD}, que)
|
||||
ret = append(ret, req...)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p SearchParameters) IsExtendedSearch() bool {
|
||||
return p.AnnotationsString != "" || p.PersonsString != "" || p.TitleString != "" || p.AlmString != "" || p.SeriesString != "" || p.PlacesString != "" || p.RefsString != "" || p.YearString != "" || p.EntryString != "" || p.IncipitString != ""
|
||||
}
|
||||
|
||||
func (p SearchParameters) NormalizeQuery() dbmodels.Query {
|
||||
return dbmodels.NormalizeQuery(p.Query)
|
||||
}
|
||||
|
||||
func (p SearchParameters) Prev() int {
|
||||
if p.Page > 1 {
|
||||
return p.Page - 1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func (p SearchParameters) Next() int {
|
||||
return p.Page + 1
|
||||
}
|
||||
Reference in New Issue
Block a user