1//  Copyright (c) 2014 Couchbase, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// 		http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package bleve
16
17import (
18	"fmt"
19	"os"
20	"testing"
21	"time"
22
23	"github.com/blevesearch/bleve/mapping"
24	"github.com/blevesearch/bleve/search"
25	"github.com/blevesearch/bleve/search/highlight/highlighter/ansi"
26)
27
28var indexMapping mapping.IndexMapping
29var exampleIndex Index
30var err error
31
32func TestMain(m *testing.M) {
33	err = os.RemoveAll("path_to_index")
34	if err != nil {
35		panic(err)
36	}
37	toRun := m.Run()
38	if exampleIndex != nil {
39		err = exampleIndex.Close()
40		if err != nil {
41			panic(err)
42		}
43	}
44	err = os.RemoveAll("path_to_index")
45	if err != nil {
46		panic(err)
47	}
48	os.Exit(toRun)
49}
50
51func ExampleNew() {
52	indexMapping = NewIndexMapping()
53	exampleIndex, err = New("path_to_index", indexMapping)
54	if err != nil {
55		panic(err)
56	}
57	count, err := exampleIndex.DocCount()
58	if err != nil {
59		panic(err)
60	}
61
62	fmt.Println(count)
63	// Output:
64	// 0
65}
66
67func ExampleIndex_indexing() {
68	data := struct {
69		Name    string
70		Created time.Time
71		Age     int
72	}{Name: "named one", Created: time.Now(), Age: 50}
73	data2 := struct {
74		Name    string
75		Created time.Time
76		Age     int
77	}{Name: "great nameless one", Created: time.Now(), Age: 25}
78
79	// index some data
80	err = exampleIndex.Index("document id 1", data)
81	if err != nil {
82		panic(err)
83	}
84	err = exampleIndex.Index("document id 2", data2)
85	if err != nil {
86		panic(err)
87	}
88
89	// 2 documents have been indexed
90	count, err := exampleIndex.DocCount()
91	if err != nil {
92		panic(err)
93	}
94
95	fmt.Println(count)
96	// Output:
97	// 2
98}
99
100// Examples for query related functions
101
102func ExampleNewMatchQuery() {
103	// finds documents with fields fully matching the given query text
104	query := NewMatchQuery("named one")
105	searchRequest := NewSearchRequest(query)
106	searchResults, err := exampleIndex.Search(searchRequest)
107	if err != nil {
108		panic(err)
109	}
110
111	fmt.Println(searchResults.Hits[0].ID)
112	// Output:
113	// document id 1
114}
115
116func ExampleNewMatchAllQuery() {
117	// finds all documents in the index
118	query := NewMatchAllQuery()
119	searchRequest := NewSearchRequest(query)
120	searchResults, err := exampleIndex.Search(searchRequest)
121	if err != nil {
122		panic(err)
123	}
124
125	fmt.Println(len(searchResults.Hits))
126	// Output:
127	// 2
128}
129
130func ExampleNewMatchNoneQuery() {
131	// matches no documents in the index
132	query := NewMatchNoneQuery()
133	searchRequest := NewSearchRequest(query)
134	searchResults, err := exampleIndex.Search(searchRequest)
135	if err != nil {
136		panic(err)
137	}
138
139	fmt.Println(len(searchResults.Hits))
140	// Output:
141	// 0
142}
143
144func ExampleNewMatchPhraseQuery() {
145	// finds all documents with the given phrase in the index
146	query := NewMatchPhraseQuery("nameless one")
147	searchRequest := NewSearchRequest(query)
148	searchResults, err := exampleIndex.Search(searchRequest)
149	if err != nil {
150		panic(err)
151	}
152
153	fmt.Println(searchResults.Hits[0].ID)
154	// Output:
155	// document id 2
156}
157
158func ExampleNewNumericRangeQuery() {
159	value1 := float64(11)
160	value2 := float64(100)
161	data := struct{ Priority float64 }{Priority: float64(15)}
162	data2 := struct{ Priority float64 }{Priority: float64(10)}
163
164	err = exampleIndex.Index("document id 3", data)
165	if err != nil {
166		panic(err)
167	}
168	err = exampleIndex.Index("document id 4", data2)
169	if err != nil {
170		panic(err)
171	}
172
173	query := NewNumericRangeQuery(&value1, &value2)
174	searchRequest := NewSearchRequest(query)
175	searchResults, err := exampleIndex.Search(searchRequest)
176	if err != nil {
177		panic(err)
178	}
179
180	fmt.Println(searchResults.Hits[0].ID)
181	// Output:
182	// document id 3
183}
184
185func ExampleNewNumericRangeInclusiveQuery() {
186	value1 := float64(10)
187	value2 := float64(100)
188	v1incl := false
189	v2incl := false
190
191	query := NewNumericRangeInclusiveQuery(&value1, &value2, &v1incl, &v2incl)
192	searchRequest := NewSearchRequest(query)
193	searchResults, err := exampleIndex.Search(searchRequest)
194	if err != nil {
195		panic(err)
196	}
197
198	fmt.Println(searchResults.Hits[0].ID)
199	// Output:
200	// document id 3
201}
202
203func ExampleNewPhraseQuery() {
204	// finds all documents with the given phrases in the given field in the index
205	query := NewPhraseQuery([]string{"nameless", "one"}, "Name")
206	searchRequest := NewSearchRequest(query)
207	searchResults, err := exampleIndex.Search(searchRequest)
208	if err != nil {
209		panic(err)
210	}
211
212	fmt.Println(searchResults.Hits[0].ID)
213	// Output:
214	// document id 2
215}
216
217func ExampleNewPrefixQuery() {
218	// finds all documents with terms having the given prefix in the index
219	query := NewPrefixQuery("name")
220	searchRequest := NewSearchRequest(query)
221	searchResults, err := exampleIndex.Search(searchRequest)
222	if err != nil {
223		panic(err)
224	}
225
226	fmt.Println(len(searchResults.Hits))
227	// Output:
228	// 2
229}
230
231func ExampleNewQueryStringQuery() {
232	query := NewQueryStringQuery("+one -great")
233	searchRequest := NewSearchRequest(query)
234	searchResults, err := exampleIndex.Search(searchRequest)
235	if err != nil {
236		panic(err)
237	}
238
239	fmt.Println(searchResults.Hits[0].ID)
240	// Output:
241	// document id 1
242}
243
244func ExampleNewTermQuery() {
245	query := NewTermQuery("great")
246	searchRequest := NewSearchRequest(query)
247	searchResults, err := exampleIndex.Search(searchRequest)
248	if err != nil {
249		panic(err)
250	}
251
252	fmt.Println(searchResults.Hits[0].ID)
253	// Output:
254	// document id 2
255}
256
257func ExampleNewFacetRequest() {
258	facet := NewFacetRequest("Name", 1)
259	query := NewMatchAllQuery()
260	searchRequest := NewSearchRequest(query)
261	searchRequest.AddFacet("facet name", facet)
262	searchResults, err := exampleIndex.Search(searchRequest)
263	if err != nil {
264		panic(err)
265	}
266
267	// total number of terms
268	fmt.Println(searchResults.Facets["facet name"].Total)
269	// numer of docs with no value for this field
270	fmt.Println(searchResults.Facets["facet name"].Missing)
271	// term with highest occurrences in field name
272	fmt.Println(searchResults.Facets["facet name"].Terms[0].Term)
273	// Output:
274	// 5
275	// 2
276	// one
277}
278
279func ExampleFacetRequest_AddDateTimeRange() {
280	facet := NewFacetRequest("Created", 1)
281	facet.AddDateTimeRange("range name", time.Unix(0, 0), time.Now())
282	query := NewMatchAllQuery()
283	searchRequest := NewSearchRequest(query)
284	searchRequest.AddFacet("facet name", facet)
285	searchResults, err := exampleIndex.Search(searchRequest)
286	if err != nil {
287		panic(err)
288	}
289
290	// dates in field Created since starting of unix time till now
291	fmt.Println(searchResults.Facets["facet name"].DateRanges[0].Count)
292	// Output:
293	// 2
294}
295
296func ExampleFacetRequest_AddNumericRange() {
297	value1 := float64(11)
298
299	facet := NewFacetRequest("Priority", 1)
300	facet.AddNumericRange("range name", &value1, nil)
301	query := NewMatchAllQuery()
302	searchRequest := NewSearchRequest(query)
303	searchRequest.AddFacet("facet name", facet)
304	searchResults, err := exampleIndex.Search(searchRequest)
305	if err != nil {
306		panic(err)
307	}
308
309	// number documents with field Priority in the given range
310	fmt.Println(searchResults.Facets["facet name"].NumericRanges[0].Count)
311	// Output:
312	// 1
313}
314
315func ExampleNewHighlight() {
316	query := NewMatchQuery("nameless")
317	searchRequest := NewSearchRequest(query)
318	searchRequest.Highlight = NewHighlight()
319	searchResults, err := exampleIndex.Search(searchRequest)
320	if err != nil {
321		panic(err)
322	}
323
324	fmt.Println(searchResults.Hits[0].Fragments["Name"][0])
325	// Output:
326	// great <mark>nameless</mark> one
327}
328
329func ExampleNewHighlightWithStyle() {
330	query := NewMatchQuery("nameless")
331	searchRequest := NewSearchRequest(query)
332	searchRequest.Highlight = NewHighlightWithStyle(ansi.Name)
333	searchResults, err := exampleIndex.Search(searchRequest)
334	if err != nil {
335		panic(err)
336	}
337
338	fmt.Println(searchResults.Hits[0].Fragments["Name"][0])
339	// Output:
340	// great nameless one
341}
342
343func ExampleSearchRequest_AddFacet() {
344	facet := NewFacetRequest("Name", 1)
345	query := NewMatchAllQuery()
346	searchRequest := NewSearchRequest(query)
347	searchRequest.AddFacet("facet name", facet)
348	searchResults, err := exampleIndex.Search(searchRequest)
349	if err != nil {
350		panic(err)
351	}
352
353	// total number of terms
354	fmt.Println(searchResults.Facets["facet name"].Total)
355	// numer of docs with no value for this field
356	fmt.Println(searchResults.Facets["facet name"].Missing)
357	// term with highest occurrences in field name
358	fmt.Println(searchResults.Facets["facet name"].Terms[0].Term)
359	// Output:
360	// 5
361	// 2
362	// one
363}
364
365func ExampleNewSearchRequest() {
366	// finds documents with fields fully matching the given query text
367	query := NewMatchQuery("named one")
368	searchRequest := NewSearchRequest(query)
369	searchResults, err := exampleIndex.Search(searchRequest)
370	if err != nil {
371		panic(err)
372	}
373
374	fmt.Println(searchResults.Hits[0].ID)
375	// Output:
376	// document id 1
377}
378
379func ExampleNewBooleanQuery() {
380	must := NewMatchQuery("one")
381	mustNot := NewMatchQuery("great")
382	query := NewBooleanQuery()
383	query.AddMust(must)
384	query.AddMustNot(mustNot)
385	searchRequest := NewSearchRequest(query)
386	searchResults, err := exampleIndex.Search(searchRequest)
387	if err != nil {
388		panic(err)
389	}
390
391	fmt.Println(searchResults.Hits[0].ID)
392	// Output:
393	// document id 1
394}
395
396func ExampleNewConjunctionQuery() {
397	conjunct1 := NewMatchQuery("great")
398	conjunct2 := NewMatchQuery("one")
399	query := NewConjunctionQuery(conjunct1, conjunct2)
400	searchRequest := NewSearchRequest(query)
401	searchResults, err := exampleIndex.Search(searchRequest)
402	if err != nil {
403		panic(err)
404	}
405
406	fmt.Println(searchResults.Hits[0].ID)
407	// Output:
408	// document id 2
409}
410
411func ExampleNewDisjunctionQuery() {
412	disjunct1 := NewMatchQuery("great")
413	disjunct2 := NewMatchQuery("named")
414	query := NewDisjunctionQuery(disjunct1, disjunct2)
415	searchRequest := NewSearchRequest(query)
416	searchResults, err := exampleIndex.Search(searchRequest)
417	if err != nil {
418		panic(err)
419	}
420
421	fmt.Println(len(searchResults.Hits))
422	// Output:
423	// 2
424}
425
426func ExampleSearchRequest_SortBy() {
427	// find docs containing "one", order by Age instead of score
428	query := NewMatchQuery("one")
429	searchRequest := NewSearchRequest(query)
430	searchRequest.SortBy([]string{"Age"})
431	searchResults, err := exampleIndex.Search(searchRequest)
432	if err != nil {
433		panic(err)
434	}
435
436	fmt.Println(searchResults.Hits[0].ID)
437	fmt.Println(searchResults.Hits[1].ID)
438	// Output:
439	// document id 2
440	// document id 1
441}
442
443func ExampleSearchRequest_SortByCustom() {
444	// find all docs, order by Age, with docs missing Age field first
445	query := NewMatchAllQuery()
446	searchRequest := NewSearchRequest(query)
447	searchRequest.SortByCustom(search.SortOrder{
448		&search.SortField{
449			Field:   "Age",
450			Missing: search.SortFieldMissingFirst,
451		},
452	})
453	searchResults, err := exampleIndex.Search(searchRequest)
454	if err != nil {
455		panic(err)
456	}
457
458	fmt.Println(searchResults.Hits[0].ID)
459	fmt.Println(searchResults.Hits[1].ID)
460	fmt.Println(searchResults.Hits[2].ID)
461	fmt.Println(searchResults.Hits[3].ID)
462	// Output:
463	// document id 3
464	// document id 4
465	// document id 2
466	// document id 1
467}
468