tantivy-py Documentation

repository·master·Indexed 19 days ago

https://github.com/quickwit-oss/tantivy-py

Python bindings for Tantivy, a high-performance full-text search engine library written in Rust. Version 0.26.0. Provides tools for defining schemas via SchemaBuilder, managing indices, and performing searches. Includes detailed API references for Document manipulation, query parsing, and comprehensive error handling for query failures such as FieldDoesNotExistError, ExpectedIntError, and SyntaxError.

Tokens
31.4K
Snippets
99
Records
149
Agent score
65%

What's inside tantivy-py

  1. What is a Tantivy Document?

    master

    A tantivy.Document is the primary object used for indexing and searching. Conceptually, a document is an unordered collection of tuples consisting of a field_name and a value. A single field can appear multiple times within a document, meaning a field can hold multiple values.

    You can construct a document in several ways:

    1. Empty constructor + explicit addition: Create an empty Document() and use add_* methods to populate it.
    2. Constructor with field values: Pass field values directly to the Document constructor. You can pass lists of values or single values (syntactic sugar).
    3. From a dictionary: Use Document.from_dict(py_dict, schema=None) to create a document from a Python dictionary. This is highly recommended when dealing with numeric fields to ensure correct type mapping via the provided schema.
    # Method 1: Explicit addition
    doc = tantivy.Document()
    doc.add_text("title", "The Old Man and the Sea")
    
    # Method 2: Constructor with single values (syntactic sugar)
    doc = tantivy.Document(title="The Old Man and the Sea", body="...")
    
    # Method 3: From dictionary with schema (recommended for numeric types)
    schema = SchemaBuilder().add_integer_field("signed").build()
    doc = tantivy.Document.from_dict({"signed": -5}, schema=schema)
  2. What is a DocAddress?

    master

    A DocAddress object contains the necessary information to uniquely identify a specific document within the context of a Searcher.

    It consists of two parts:

    • segment_ord: An integer identifying the specific segment hosting the document. This ordinal is only meaningful when used in the context of a Searcher.
    • doc: The segment-local DocId (an integer) for the document.
  3. Work with Facets for hierarchical data

    master

    A Facet represents a point in a hierarchy, typically modeled like a filepath (e.g., /electronics/tv_and_video/led_tv). Documents associated with a facet are implicitly associated with all its ancestor facets.

    Key operations:

    • Creation: Use Facet.from_string(facet_string) to create a facet from a string or Facet.from_encoded(encoded_bytes) from binary data. The root facet / can be accessed via Facet.root().
    • Hierarchy: Use is_prefix_of(other_facet) to check if other_facet is a subfacet of the current one.
    • Path Manipulation: Use to_path() to get a list of segments (e.g., ['europe', 'france']) or to_path_str() to get the string representation.
    # Create a facet from a string
    facet = Facet.from_string("/europe/france")
    
    # Check hierarchy
    root = Facet.root()
    print(facet.is_prefix_of(root)) # Returns True if root is prefix
    
    # Get path segments
    segments = facet.to_path() # ['europe', 'france']
    
    # Get string representation
    path_str = facet.to_path_str() # "/europe/france"
  4. Define a Tantivy Schema using SchemaBuilder

    master

    In tantivy-py, the Schema object defines the structure of your index. The schema is strictly typed. Because of this strictness, you should not attempt to instantiate Schema directly; instead, use the SchemaBuilder class to construct your schema definition.

    # Note: Actual usage requires SchemaBuilder as mentioned in the documentation
    # Example pattern based on documentation description:
    from tantivy import SchemaBuilder
    
    schema_builder = SchemaBuilder()
    # ... add fields using schema_builder ...
    schema = schema_builder.build()
  5. Use the Tokenizer class to create built-in tokenizers

    master

    The Tokenizer class provides access to all of Tantivy's built-in tokenizers via static methods. Each method returns a wrapper around a specific Tantivy tokenizer.

    These tokenizer objects are primarily intended to be passed to a TextAnalyzerBuilder using the tokenizer= parameter to define how text should be broken down into tokens during indexing or searching.

    tokenizer = Tokenizer.regex(r"\w+")
    # Typically used as: 
    # builder = TextAnalyzerBuilder(tokenizer=tokenizer)
  6. How tokenizers and text analyzers work together

    master

    In Tantivy-py, there is a distinction between a Tokenizer and a Text Analyzer, though the Index API uses the term 'tokenizer' to refer to both:

    • Tokenizer: A component that segments raw text into individual tokens.
    • Text Analyzer: A complete pipeline that starts with one Tokenizer and applies zero or more Filter objects (like lowercase or stopword removal) to the tokens.

    Important API Note: When using SchemaBuilder.add_text_field(..., tokenizer_name=...) or Index.register_tokenizer(...), the parameter expects the name of a Text Analyzer, not just a raw tokenizer.

  7. How to build a Tantivy schema using SchemaBuilder

    master

    Tantivy requires a strict schema where you must specify in advance whether a field is indexed, stored, or configured as a fast field. You use the SchemaBuilder class to define fields one by one and then finalize the process by calling .build().

    Key Concepts:

    • Stored: If True, the field's content can be retrieved from a Searcher later.
    • Indexed: If True, the field is indexed for searching.
    • Fast Fields: A column-oriented storage format designed for fast random access of document fields given a document ID.
    • Build Lifecycle: Once .build() is called, the SchemaBuilder instance can no longer be used.
    >>> builder = tantivy.SchemaBuilder()
    >>> title = builder.add_text_field("title", stored=True)
    >>> body = builder.add_text_field("body")
    >>> schema = builder.build()
  8. Use the Filter class for text analysis

    master

    The Filter class provides access to all of Tantivy's built-in TokenFilters. These filter objects are designed to be passed to the filter() method of a TextAnalyzerBuilder instance to customize how text is processed during indexing or searching.

    Common use cases include removing stopwords, stemming words, or normalizing text (e.g., converting to lowercase or ASCII folding).

    # Example of creating a filter
    filter = Filter.alpha_num()
  9. How segment merging works in tantivy-py

    master

    When you add documents to a tantivy index, the data is stored in multiple sections called segments. To maintain index performance, these segments are merged together in background threads.

    Currently, tantivy-py uses the LogMergePolicy as the default merge policy, which is suitable for most use cases. Because merging happens in background threads, you must ensure these processes complete before finishing your indexing task to avoid data inconsistencies or incomplete segments.

  10. Ensure background merging threads complete after indexing

    master

    After adding documents and calling writer.commit(), you must call writer.wait_merging_threads() to allow background segment merging to finish.

    Warning: Calling wait_merging_threads() will consume the writer object, making the identifier no longer usable for further operations. This should be the final step in your indexing workflow.

    schema = Schema(...) # Define your schema
    index = Index(schema)
    writer = index.writer()
    
    for ... in data:
        document = Document(...) # Create your document
        writer.add_document(document)
    
    writer.commit()
    # Final step: wait for background threads to finish
    writer.wait_merging_threads()
  11. Handle query parsing errors in tantivy-py

    master

    The tantivy.query_parser_error submodule contains all possible errors raised during query parsing. When using lenient parsing methods like index.parse_query_lenient(), errors are returned as a list rather than being raised as exceptions. You can inspect this list to identify specific issues such as missing fields or type mismatches.

    To use these errors, import the query_parser_error submodule and check the type of the error objects returned by the parser.

    import tantivy
    from tantivy import query_parser_error
    
    builder = tantivy.SchemaBuilder()
    title = builder.add_text_field("title", stored=True)
    body = builder.add_text_field("body")
    id = builder.add_unsigned_field("id")
    rating = builder.add_float_field("rating")
    
    schema = builder.build()
    index = tantivy.Index(schema)
    
    # parse_query_lenient returns (query, errors)
    query, errors = index.parse_query_lenient(
        "bod:'world' AND id:<3.5 AND rating:5.0"
    )
    
    assert len(errors) == 2
    # errors[0] might be a FieldDoesNotExistError
    # errors[1] might be an ExpectedIntError