-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathbleve.go
112 lines (100 loc) · 3.09 KB
/
bleve.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Copyright 2015 Jeremy Wall ([email protected])
// Use of this source code is governed by the Artistic License 2.0.
// That License is included in the LICENSE file.
package main
import (
"fmt"
"log"
"os"
"strings"
"github.com/blevesearch/bleve"
"github.com/blevesearch/bleve/analysis"
"github.com/blevesearch/bleve/analysis/char/html"
"github.com/blevesearch/bleve/analysis/lang/en"
"github.com/blevesearch/bleve/index/scorch"
"github.com/blevesearch/bleve/mapping"
"github.com/blevesearch/bleve/registry"
"github.com/blevesearch/bleve/search/highlight/highlighter/ansi"
)
const htmlMimeType = "text/html"
// handle text/html types
func init() {
registry.RegisterAnalyzer(htmlMimeType, func(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {
a, err := en.AnalyzerConstructor(config, cache)
if err != nil {
if cf, err := cache.CharFilterNamed(html.Name); err == nil {
a.CharFilters = []analysis.CharFilter{cf}
} else {
return nil, err
}
}
return a, err
})
}
func buildHtmlDocumentMapping() *mapping.DocumentMapping {
dm := bleve.NewDocumentMapping()
dm.DefaultAnalyzer = htmlMimeType
return dm
}
type Index interface {
Put(data *IFile) error
Query(terms []string) (*bleve.SearchResult, error)
Close() error
}
type bleveIndex struct {
index bleve.Index
}
func (i *bleveIndex) Put(data *IFile) error {
if err := i.index.Index((*data).Path(), data); err != nil {
return fmt.Errorf("Error writing to index: %q", err)
}
return nil
}
func (i *bleveIndex) Query(terms []string) (*bleve.SearchResult, error) {
searchQuery := strings.Join(terms, " ")
query := bleve.NewQueryStringQuery(searchQuery)
// TODO(jwall): limit, skip, and explain should be configurable.
request := bleve.NewSearchRequestOptions(query, *limit, *from, false)
if *useHighlight {
request.Highlight = bleve.NewHighlightWithStyle(ansi.Name)
} else {
request.Highlight = bleve.NewHighlight()
}
result, err := i.index.Search(request)
if err != nil {
log.Printf("Search Error: %q", err)
return nil, err
}
return result, nil
}
func (i *bleveIndex) Close() error {
return i.index.Close()
}
func NewIndex(indexLocation string) (Index, error) {
// TODO(jwall): An abstract indexing interface?
var index bleve.Index
if _, err := os.Stat(indexLocation); os.IsNotExist(err) {
mapping := bleve.NewIndexMapping()
mapping.DefaultAnalyzer = "en"
mapping.AddDocumentMapping(htmlMimeType, buildHtmlDocumentMapping())
// TODO(jwall): Create document mappings for our custom types.
log.Printf("Creating new index %q", indexLocation)
bleve.Config.DefaultIndexType = scorch.Name
if index, err = bleve.New(indexLocation, mapping); err != nil {
return nil, fmt.Errorf("Error creating index %q\n", err)
}
} else {
readOnly := false
if *isQuery {
readOnly = true
}
opts := map[string]interface{}{
"read_only": readOnly,
}
Debugf("Opening index %q (readonly: %t)\n", indexLocation, readOnly)
if index, err = bleve.OpenUsing(indexLocation, opts); err != nil {
return nil, fmt.Errorf("Error opening index %q\n", err)
}
}
return &bleveIndex{index}, nil
}