Some checks failed
Coverage / coverage (push) Failing after 6s
Tests / test (1.24.x, ubuntu-latest) (push) Failing after 42s
Tests / test (1.26.x, ubuntu-latest) (push) Failing after 38s
Tests / test (1.25.x, ubuntu-latest) (push) Failing after 35s
Tests / test (1.25.x, windows-latest) (push) Has been cancelled
Tests / test (1.26.x, macos-latest) (push) Has been cancelled
Tests / test (1.26.x, windows-latest) (push) Has been cancelled
Tests / test (1.24.x, macos-latest) (push) Has been cancelled
Tests / test (1.24.x, windows-latest) (push) Has been cancelled
Tests / test (1.25.x, macos-latest) (push) Has been cancelled
227 lines
5.0 KiB
Markdown
227 lines
5.0 KiB
Markdown
# Creating a Bleve Index
|
|
|
|
A simple how-to example using Bleve in Go to create an index, add documents, and run search queries with results.
|
|
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
|
|
bleve "github.com/blevesearch/bleve/v2"
|
|
)
|
|
|
|
type Document struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
Content string `json:"content"`
|
|
}
|
|
|
|
func main() {
|
|
indexPath := "example.bleve"
|
|
// Create a new index
|
|
mapping := bleve.NewIndexMapping()
|
|
index, err := bleve.New(indexPath, mapping)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer index.Close()
|
|
|
|
// Add documents
|
|
documents := []Document{
|
|
{
|
|
ID: "doc",
|
|
Title: "Bleve documentation",
|
|
Content: "Bleve provides full-text search capabilities.",
|
|
},
|
|
{
|
|
ID: "doc1",
|
|
Title: "Elasticsearch documentation",
|
|
Content: "Elasticsearch provides full-text search capabilities as well.",
|
|
},
|
|
}
|
|
|
|
// Iterate and index the documents
|
|
batch := index.NewBatch()
|
|
for _, doc := range documents {
|
|
batch.Index(doc.ID, doc)
|
|
}
|
|
if err := index.Batch(batch); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Search the created index
|
|
query := bleve.NewQueryStringQuery("bleve")
|
|
searchRequest := bleve.NewSearchRequest(query)
|
|
searchRequest.Explain = true
|
|
searchRequest.Fields = []string{"title", "content"}
|
|
searchResult, err := index.Search(searchRequest)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Println(searchResult)
|
|
}
|
|
|
|
```
|
|
|
|
## Output
|
|
|
|
```bash
|
|
$ go run main.go
|
|
|
|
1 matches, showing 1 through 1, took 262.333µs
|
|
1. doc (0.471405)
|
|
title
|
|
Bleve documentation
|
|
content
|
|
Bleve provides full-text search capabilities.
|
|
```
|
|
|
|
## Step-by-Step Breakdown
|
|
|
|
### 1. Index Creation
|
|
|
|
```go
|
|
// Create a new index mapping
|
|
mapping := bleve.NewIndexMapping()
|
|
// Create a new index (this creates a directory on disk)
|
|
index, err := bleve.New(indexPath, mapping)
|
|
```
|
|
|
|
**What happens:**
|
|
|
|
- Creates an index mapping with default settings
|
|
- Creates a new index directory `example.bleve/`
|
|
- Sets up the underlying storage (Scorch engine by default)
|
|
|
|
### 2. Document Indexing
|
|
|
|
```go
|
|
// Index a document with a unique ID
|
|
err := index.Index("doc", map[string]interface{}{
|
|
"title": "My Document",
|
|
"content": "This is the document content",
|
|
"author": "John Doe",
|
|
})
|
|
```
|
|
|
|
**What happens:**
|
|
|
|
- Document gets a unique ID (`doc`)
|
|
- Fields are automatically mapped based on their Go types
|
|
- Text fields are analyzed (tokenized, lowercased, etc.) based on the chosen mapping (here, the default one)
|
|
- Document is stored in the search index
|
|
|
|
### 3. Searching
|
|
|
|
```go
|
|
// Create a query
|
|
query := bleve.NewQueryStringQuery("search terms")
|
|
request := bleve.NewSearchRequest(query)
|
|
|
|
// Execute search
|
|
results, err := index.Search(request)
|
|
```
|
|
|
|
**What happens:**
|
|
|
|
- Query string is parsed and analyzed
|
|
- Index is searched for matching documents
|
|
- Results are scored and ranked by relevance by the algorithm used
|
|
- Document metadata and highlights are returned
|
|
|
|
## Working with Existing Indexes
|
|
|
|
To open an existing index instead of creating a new one:
|
|
|
|
```go
|
|
// Open existing index
|
|
index, err := bleve.Open("example.bleve")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer index.Close()
|
|
```
|
|
|
|
## Different Query Types
|
|
|
|
### 1. Query String Query (Simple)
|
|
|
|
```go
|
|
query := bleve.NewQueryStringQuery("golang programming")
|
|
```
|
|
|
|
### 2. Match Query (Exact Field)
|
|
|
|
```go
|
|
query := bleve.NewMatchQuery("bleve")
|
|
query.SetField("title") // Search only in title field
|
|
```
|
|
|
|
### 3. Boolean Query (Complex)
|
|
|
|
```go
|
|
mustQuery := bleve.NewMatchQuery("golang")
|
|
shouldQuery := bleve.NewMatchQuery("programming")
|
|
|
|
boolQuery := bleve.NewBooleanQuery()
|
|
boolQuery.AddMust(mustQuery)
|
|
boolQuery.AddShould(shouldQuery)
|
|
```
|
|
|
|
### 4. Range Query (Numeric/Date)
|
|
|
|
```go
|
|
minPrice := 20.50
|
|
maxPrice := 40.75
|
|
query := bleve.NewNumericRangeQuery(&minPrice, &maxPrice)
|
|
query.SetField("price")
|
|
```
|
|
|
|
## Advanced Index Configuration
|
|
|
|
### Custom Field Mapping
|
|
|
|
```go
|
|
// We can create customized mappings as well with configurable analyzers
|
|
mapping := bleve.NewIndexMapping()
|
|
|
|
// Text field with custom analyzer
|
|
titleMapping := bleve.NewTextFieldMapping()
|
|
titleMapping.Analyzer = "en" // English analyzer
|
|
|
|
// Numeric field
|
|
priceMapping := bleve.NewNumericFieldMapping()
|
|
|
|
// Date field
|
|
dateMapping := bleve.NewDateTimeFieldMapping()
|
|
|
|
// Document mapping
|
|
docMapping := bleve.NewDocumentMapping()
|
|
docMapping.AddFieldMappingsAt("title", titleMapping)
|
|
docMapping.AddFieldMappingsAt("price", priceMapping)
|
|
docMapping.AddFieldMappingsAt("created_at", dateMapping)
|
|
|
|
// Add to index mapping
|
|
mapping.AddDocumentMapping("product", docMapping)
|
|
|
|
// Create index with custom mapping
|
|
index, err := bleve.New("products.bleve", mapping)
|
|
```
|
|
|
|
### Batch Operations
|
|
|
|
For better performance when indexing many documents, we can do indexing in batches:
|
|
|
|
```go
|
|
batch := index.NewBatch()
|
|
|
|
for _, doc := range documents {
|
|
batch.Index(doc.ID, doc)
|
|
}
|
|
|
|
// Execute batch
|
|
err := index.Batch(batch)
|
|
```
|