144 lines
3 KiB
Go
144 lines
3 KiB
Go
// Copyright (C) 2019 Marius Schellenberger
|
|
|
|
package index
|
|
|
|
import (
|
|
"errors"
|
|
"git.giftfish.de/ston1th/docstore/pkg/core"
|
|
"github.com/blevesearch/bleve"
|
|
"github.com/blevesearch/bleve/document"
|
|
"github.com/blevesearch/bleve/mapping"
|
|
"html/template"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const maxSearchResult = 101
|
|
|
|
const docType = "document"
|
|
|
|
type Document struct {
|
|
Text string `json:"text"`
|
|
Tags []string `json:"tags"`
|
|
Created time.Time `json:"created"`
|
|
}
|
|
|
|
func (d *Document) Type() string {
|
|
return docType
|
|
}
|
|
|
|
type Index struct {
|
|
i bleve.Index
|
|
}
|
|
|
|
func NewIndex(path string) (i *Index, err error) {
|
|
var bi bleve.Index
|
|
if _, err = os.Stat(path); os.IsNotExist(err) {
|
|
var m *mapping.IndexMappingImpl
|
|
m, err = createMapping()
|
|
if err != nil {
|
|
err = errors.New("index: " + err.Error())
|
|
return
|
|
}
|
|
//m := bleve.NewIndexMapping()
|
|
bi, err = bleve.New(path, m)
|
|
if err != nil {
|
|
err = errors.New("index: " + err.Error())
|
|
return
|
|
}
|
|
} else {
|
|
bi, err = bleve.Open(path)
|
|
if err != nil {
|
|
err = errors.New("index: " + err.Error())
|
|
return
|
|
}
|
|
}
|
|
i = &Index{i: bi}
|
|
return
|
|
}
|
|
|
|
func (i *Index) Close() error {
|
|
return i.i.Close()
|
|
}
|
|
|
|
func (i *Index) Add(text string, tags []string) (id string, err error) {
|
|
id = newID()
|
|
for {
|
|
doc, _ := i.i.Document(id)
|
|
if doc == nil {
|
|
break
|
|
}
|
|
id = newID()
|
|
}
|
|
err = i.i.Index(id, &Document{text, tags, time.Now()})
|
|
return
|
|
}
|
|
|
|
func (i *Index) Reindex(id string, doc *Document) error {
|
|
return i.i.Index(id, doc)
|
|
}
|
|
|
|
func (i *Index) Get(id string) (doc *Document, err error) {
|
|
d, err := i.i.Document(id)
|
|
if d == nil || err != nil {
|
|
return
|
|
}
|
|
doc = new(Document)
|
|
for _, f := range d.Fields {
|
|
n := f.Name()
|
|
switch n {
|
|
case "text":
|
|
text := document.NewTextField(n, f.ArrayPositions(), f.Value())
|
|
doc.Text = string(text.Value())
|
|
//case "tags":
|
|
// tags := document.NewTextField(n, f.ArrayPositions(), f.Value())
|
|
// doc.Tags = append(doc.Tags, string(tags.Value()))
|
|
case "created":
|
|
created := document.NewDateTimeFieldFromBytes(n, f.ArrayPositions(), f.Value())
|
|
doc.Created, _ = created.DateTime()
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (i *Index) Delete(id string) error {
|
|
return i.i.Delete(id)
|
|
}
|
|
|
|
func (i *Index) Search(search string) (results core.Results, err error) {
|
|
req := bleve.NewSearchRequest(bleve.NewQueryStringQuery(search))
|
|
req.Highlight = bleve.NewHighlightWithStyle("html")
|
|
req.Size = maxSearchResult
|
|
res, err := i.i.Search(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
for _, hit := range res.Hits {
|
|
if hit == nil {
|
|
continue
|
|
}
|
|
r := core.Result{ID: hit.ID}
|
|
d, err := i.i.Document(hit.ID)
|
|
if d == nil || err != nil {
|
|
continue
|
|
}
|
|
for fragField, frags := range hit.Fragments {
|
|
if fragField == "tags" {
|
|
var t string
|
|
for _, f := range frags {
|
|
t += f
|
|
}
|
|
r.Tags = strings.ReplaceAll(strings.ReplaceAll(t, "<mark>", ""), "</mark>", "")
|
|
}
|
|
if fragField == "text" || fragField == "created" {
|
|
for _, f := range frags {
|
|
r.HTML += template.HTML(f)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
results = append(results, r)
|
|
}
|
|
return
|
|
}
|