Skip to content

Commit 2399a95

Browse files
author
Matthew Borders
committed
Added search functionality to find verses based on a query string; using trie data structure
1 parent 66b27b5 commit 2399a95

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

bible.go

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,33 @@ import (
55
"compress/gzip"
66
"encoding/json"
77
"fmt"
8+
"github.com/derekparker/trie"
89
"io"
910
"os"
1011
"path"
1112
"runtime"
13+
"strings"
1214
)
1315

1416
// Bible contains the old testament and new testament
1517
type Bible struct {
1618
OldTestament Testament
1719
NewTestament Testament
20+
searchTree *trie.Trie
21+
}
22+
23+
type SearchNode struct {
24+
Book *Book
25+
Chapter *Chapter
26+
Verse *Verse
27+
}
28+
29+
// String creates a string representation for the SearchNode, ex. Genesis 1:1
30+
func (s *SearchNode) String() string {
31+
return fmt.Sprintf("%s %d:%d",
32+
s.Book.Title,
33+
s.Chapter.ChapterNumber,
34+
s.Verse.VerseNumber)
1835
}
1936

2037
const bibleTar = "bible.tar.gz"
@@ -26,7 +43,9 @@ func NewBible() *Bible {
2643
_, currFile, _, _ := runtime.Caller(0)
2744
filename := fmt.Sprintf("%s/%s", path.Dir(currFile), bibleTar)
2845

29-
bible := &Bible{}
46+
bible := &Bible{
47+
searchTree: trie.New(),
48+
}
3049

3150
f, _ := os.Open(filename)
3251
defer f.Close()
@@ -36,6 +55,7 @@ func NewBible() *Bible {
3655

3756
tr := tar.NewReader(gzf)
3857

58+
// Build testaments, books, chapters, verses
3959
for {
4060
h, err := tr.Next()
4161
if err == io.EOF {
@@ -50,6 +70,28 @@ func NewBible() *Bible {
5070
}
5171
}
5272

73+
// Build search tree
74+
var books []Book
75+
books = append(books, bible.OldTestament.Books...)
76+
books = append(books, bible.NewTestament.Books...)
77+
78+
for i := range books {
79+
bk := books[i]
80+
81+
for j := range bk.Chapters {
82+
ch := bk.Chapters[j]
83+
84+
for k := range ch.Verses {
85+
vr := strings.ToLower(ch.Verses[k].Text)
86+
bible.searchTree.Add(vr, SearchNode{
87+
Book: &bk,
88+
Chapter: &ch,
89+
Verse: &ch.Verses[k],
90+
})
91+
}
92+
}
93+
}
94+
5395
return bible
5496
}
5597

@@ -58,3 +100,22 @@ func decode(r io.Reader) []Book {
58100
json.NewDecoder(r).Decode(&books)
59101
return books
60102
}
103+
104+
// Search finds top matching verses based on the given query.
105+
// The number of search results are restricted by maxResults
106+
func (b *Bible) Search(query string, maxResults int) []SearchNode {
107+
t := b.searchTree
108+
keys := t.FuzzySearch(strings.ToLower(query))
109+
var verses []SearchNode
110+
111+
for k := range keys {
112+
res, _ := t.Find(keys[k])
113+
verses = append(verses, res.Meta().(SearchNode))
114+
115+
if len(verses) >= maxResults {
116+
break
117+
}
118+
}
119+
120+
return verses
121+
}

bible_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,10 @@ func TestTestament_GetVerse_InvalidVerse(t *testing.T) {
8181
_, err = b.OldTestament.GetVerse(1, 1, 1000)
8282
assert.Equal(t, "invalid verse number", err.Error())
8383
}
84+
85+
func TestBible_Search(t *testing.T) {
86+
v := b.Search("truth make you free", 10)
87+
88+
assert.NotEmpty(t, v)
89+
assert.Equal(t, v[0].String(), "John 8:32")
90+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module github.com/borderstech/vulgata
22

33
require (
44
github.com/davecgh/go-spew v1.1.1 // indirect
5+
github.com/derekparker/trie v0.0.0-20180212171413-e608c2733dc7
56
github.com/pmezard/go-difflib v1.0.0 // indirect
67
github.com/stretchr/testify v1.2.2
78
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/derekparker/trie v0.0.0-20180212171413-e608c2733dc7 h1:Cab9yoTQh1TxObKfis1DzZ6vFLK5kbeenMjRES/UE3o=
4+
github.com/derekparker/trie v0.0.0-20180212171413-e608c2733dc7/go.mod h1:D6ICZm05D9VN1n/8iOtBxLpXtoGp6HDFUJ1RNVieOSE=
35
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
46
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
57
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=

0 commit comments

Comments
 (0)