Bluge Documentation

repository·master·Indexed 24 days ago

https://github.com/blugelabs/bluge

Bluge is a modern text indexing and search engine library for Go. It provides high-performance indexing, complex querying, and advanced aggregations, including BM25 scoring and highlighting. The library supports various field types such as text, numeric, date, and geo points, and offers a CLI tool for interacting with indices and inspecting snapshots.

Tokens
6.4K
Snippets
3
Records
65
Agent score
85%

What's inside Bluge

  1. Overview of Bluge features

    master

    Bluge is a modern text indexing library written in Go. It supports various field types, query types, and advanced search features like BM25 scoring and highlighting.

    Supported Field Types

    • Text
    • Numeric
    • Date
    • Geo Point

    Supported Query Types

    • Term, Phrase, Match, Match Phrase, Prefix
    • Conjunction, Disjunction, Boolean
    • Numeric Range, Date Range

    Aggregations

    Bluge provides extendable aggregations including:

    • Bucketing: Terms, Numeric Range, Date Range
    • Metrics: Min, Max, Count, Sum, Avg, Weighted Avg, Cardinality Estimation (via HyperLogLog++), and Quantile Approximation (via T-Digest).
  2. Understand Bluge geo support conventions

    master

    Bluge's geo support is a Go adaptation of the Lucene 5.3.2 sandbox geo support. When working with geographic data, keep the following conventions in mind:

    • Coordinate Types: All APIs use float64 for longitude and latitude values.
    • Coordinate Order: When providing points in function arguments or receiving them in return values, always use the order longitude, latitude (lon, lat).
    • Bounding Boxes:
      • High-level APIs: Use TopLeft and BottomRight to describe bounding boxes. Note that these may not map cleanly to min/max longitude/latitude when crossing the dateline.
      • Low-level APIs: Use min/max longitude/latitude. If you are using high-level bounding boxes that cross the dateline, you must use the higher-level code to split the boxes into multiple parts before using low-level APIs.
  3. Index documents with Bluge

    master

    To index data, use bluge.DefaultConfig(path) to define the index location, then open a writer using bluge.OpenWriter(config). Documents are created using bluge.NewDocument(id) and fields are added via methods like AddField. Use writer.Update(doc.ID(), doc) to persist the document to the index. Always ensure you defer writer.Close() to flush changes and release resources.

        config := bluge.DefaultConfig(path)
        writer, err := bluge.OpenWriter(config)
        if err != nil {
            log.Fatalf("error opening writer: %v", err)
        }
        defer writer.Close()
    
        doc := bluge.NewDocument("example").
            AddField(bluge.NewTextField("name", "bluge"))
    
        err = writer.Update(doc.ID(), doc)
        if err != nil {
            log.Fatalf("error updating document: %v", err)
        }
  4. Query and search the index with Bluge

    master

    To perform searches, obtain a reader from your writer using writer.Reader(). Construct a query (e.g., bluge.NewMatchQuery("term").SetField("field_name")) and wrap it in a search request using bluge.NewTopNSearch(n, query). You can enable standard aggregations with .WithStandardAggregations().

    Execute the search with reader.Search(ctx, request), which returns a documentMatchIterator. Iterate through matches using documentMatchIterator.Next() and access stored fields using match.VisitStoredFields(func(field string, value []byte) bool { ... }).

        reader, err := writer.Reader()
        if err != nil {
            log.Fatalf("error getting index reader: %v", err)
        }
        defer reader.Close()
    
        query := bluge.NewMatchQuery("bluge").SetField("name")
        request := bluge.NewTopNSearch(10, query).
            WithStandardAggregations()
        documentMatchIterator, err := reader.Search(context.Background(), request)
        if err != nil {
            log.Fatalf("error executing search: %v", err)
        }
        match, err := documentMatchIterator.Next()
        for err == nil && match != nil {
            err = match.VisitStoredFields(func(field string, value []byte) bool {
                if field == "_id" {
                    fmt.Printf("match: %s\n", string(value))
                }
                return true
            })
            if err != nil {
                log.Fatalf("error loading stored fields: %v", err)
            }
            match, err = documentMatchIterator.Next()
        }
        if err != nil {
            log.Fatalf("error iterator document matches: %v", err)
        }
  5. Implement FieldConsumer to create composite fields

    master

    The FieldConsumer interface allows a field to 'consume' the content of other fields during the Analyze() phase of a document. This is useful for creating composite fields that depend on the analyzed output of other fields in the same document.

    To implement this, define a type that satisfies the interface:

    type MyCompositeField struct {
        // ...
    }
    
    func (m *MyCompositeField) Consume(f bluge.Field) {
        // Process the field f
    }
  6. Use virtual fields in Bluge configuration

    master

    A virtual field allows you to define a field that the index treats as if every document contains those terms, even though the data is not physically stored in the index. This is useful for creating catch-all search behaviors or metadata overlays. Use the WithVirtualField(field Field) method on a Config object to register it.

    Note: The field must be analyzed before being passed to WithVirtualField to ensure the index configuration is correctly updated.

  7. Initialize a Bluge Config

    master

    Use DefaultConfig(path) to create a configuration for an index stored at the specified path. Alternatively, use InMemoryOnlyConfig() for an index that exists only in memory, or DefaultConfigWithDirectory(df) to provide a custom directory implementation via a function df func() index.Directory.

    By default, a Config instance includes:

    • A Logger (defaults to ioutil.Discard).
    • DefaultSearchField set to "_all".
    • DefaultSearchAnalyzer using a standard analyzer.
    • DefaultSimilarity using BM25 similarity.
    • A virtual field "_all" that acts as a catch-all for documents.
  8. Use the Bluge CLI

    master
    The bluge command is the primary entrypoint for interacting with the Bluge search engine via the command line. It is implemented using the cmd.Execute() function from the github.com/blugelabs/bluge/cmd/bluge/cmd package. To use the CLI, you must have the binary compiled and available in your system path.
  9. Configure field indexing and storage options

    master

    Bluge uses FieldOptions to control how fields are handled during indexing and retrieval. You can chain these options when creating or configuring a TermField.

    Available options:

    • Index: Enables indexing for the field.
    • Store: Stores the original value for retrieval.
    • SearchTermPositions: Stores term positions (required for proximity searches).
    • HighlightMatches: Enables highlighting of search matches.
    • Sortable: Enables the field to be used for sorting.
    • Aggregatable: Enables the field to be used for aggregations.
  10. Sort search results using SortBy

    master

    The SortBy(order []string) method is a convenience for specifying sort orders using field names.

    Rules for the order slice:

    • A string like "field_name" sorts that field in ascending order.
    • A prefix of "-" (e.g., "-field_name") sorts that field in descending order.
    • The special field "_score" can be used to sort by the document score.

    Example:

    // Sort by price descending, then by name ascending
    s.SortBy([]string{"-price", "name"})