Repository: quickwit-oss/tantivy Branch: main Commit: 545169c0d843 Files: 504 Total size: 29.6 MB Directory structure: gitextract_0oj2913e/ ├── .claude/ │ └── skills/ │ ├── rationalize-deps/ │ │ └── SKILL.md │ └── simple-pr/ │ └── SKILL.md ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── actions.md │ │ ├── bug_report.md │ │ ├── feature_request.md │ │ └── question.md │ ├── dependabot.yml │ └── workflows/ │ ├── coverage.yml │ ├── long_running.yml │ └── test.yml ├── .gitignore ├── ARCHITECTURE.md ├── AUTHORS ├── CHANGELOG.md ├── CITATION.cff ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── RELEASE.md ├── TODO.txt ├── benches/ │ ├── agg_bench.rs │ ├── alice.txt │ ├── analyzer.rs │ ├── and_or_queries.rs │ ├── bool_queries_with_range.rs │ ├── exists_json.rs │ ├── gh.json │ ├── hdfs.json │ ├── index-bench.rs │ ├── merge_segments.rs │ ├── range_queries.rs │ ├── range_query.rs │ ├── regex_all_terms.rs │ ├── str_search_and_get.rs │ └── wiki.json ├── bitpacker/ │ ├── Cargo.toml │ ├── benches/ │ │ └── bench.rs │ └── src/ │ ├── bitpacker.rs │ ├── blocked_bitpacker.rs │ ├── filter_vec/ │ │ ├── avx2.rs │ │ ├── mod.rs │ │ └── scalar.rs │ └── lib.rs ├── cliff.toml ├── columnar/ │ ├── Cargo.toml │ ├── README.md │ ├── benches/ │ │ ├── bench_access.rs │ │ ├── bench_column_values_get.rs │ │ ├── bench_create_column_values.rs │ │ ├── bench_first_vals.rs │ │ ├── bench_merge.rs │ │ ├── bench_optional_index.rs │ │ ├── bench_values_u128.rs │ │ ├── bench_values_u64.rs │ │ └── common.rs │ ├── columnar-cli/ │ │ ├── Cargo.toml │ │ └── src/ │ │ └── main.rs │ ├── columnar-cli-inspect/ │ │ ├── Cargo.toml │ │ └── src/ │ │ └── main.rs │ ├── compat_tests_data/ │ │ ├── v1.columnar │ │ └── v2.columnar │ └── src/ │ ├── TODO.md │ ├── block_accessor.rs │ ├── column/ │ │ ├── dictionary_encoded.rs │ │ ├── mod.rs │ │ └── serialize.rs │ ├── column_index/ │ │ ├── merge/ │ │ │ ├── mod.rs │ │ │ ├── shuffled.rs │ │ │ └── stacked.rs │ │ ├── mod.rs │ │ ├── multivalued_index.rs │ │ ├── optional_index/ │ │ │ ├── mod.rs │ │ │ ├── set.rs │ │ │ ├── set_block/ │ │ │ │ ├── dense.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── sparse.rs │ │ │ │ └── tests.rs │ │ │ └── tests.rs │ │ └── serialize.rs │ ├── column_values/ │ │ ├── merge.rs │ │ ├── mod.rs │ │ ├── monotonic_column.rs │ │ ├── monotonic_mapping.rs │ │ ├── monotonic_mapping_u128.rs │ │ ├── stats.rs │ │ ├── u128_based/ │ │ │ ├── compact_space/ │ │ │ │ ├── blank_range.rs │ │ │ │ ├── build_compact_space.rs │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── u64_based/ │ │ │ ├── bitpacked.rs │ │ │ ├── blockwise_linear.rs │ │ │ ├── line.rs │ │ │ ├── linear.rs │ │ │ ├── mod.rs │ │ │ ├── stats_collector.rs │ │ │ └── tests.rs │ │ └── vec_column.rs │ ├── columnar/ │ │ ├── column_type.rs │ │ ├── format_version.rs │ │ ├── merge/ │ │ │ ├── merge_dict_column.rs │ │ │ ├── merge_mapping.rs │ │ │ ├── mod.rs │ │ │ ├── term_merger.rs │ │ │ └── tests.rs │ │ ├── mod.rs │ │ ├── reader/ │ │ │ └── mod.rs │ │ └── writer/ │ │ ├── column_operation.rs │ │ ├── column_writers.rs │ │ ├── mod.rs │ │ ├── serializer.rs │ │ └── value_index.rs │ ├── compat_tests.rs │ ├── dictionary.rs │ ├── dynamic_column.rs │ ├── iterable.rs │ ├── lib.rs │ ├── tests.rs │ ├── utils.rs │ └── value.rs ├── common/ │ ├── Cargo.toml │ ├── benches/ │ │ └── bench.rs │ └── src/ │ ├── bitset.rs │ ├── bounds.rs │ ├── byte_count.rs │ ├── datetime.rs │ ├── file_slice.rs │ ├── group_by.rs │ ├── json_path_writer.rs │ ├── lib.rs │ ├── serialize.rs │ ├── vint.rs │ └── writer.rs ├── doc/ │ ├── .gitignore │ ├── book.toml │ └── src/ │ ├── SUMMARY.md │ ├── avant-propos.md │ ├── basis.md │ ├── best_practise.md.rs │ ├── examples.md │ ├── facetting.md │ ├── faq.md │ ├── index_sorting.md │ ├── innerworkings.md │ ├── inverted_index.md │ ├── json.md │ └── schema.md ├── examples/ │ ├── aggregation.rs │ ├── basic_search.rs │ ├── custom_collector.rs │ ├── custom_tokenizer.rs │ ├── date_time_field.rs │ ├── deleting_updating_documents.rs │ ├── faceted_search.rs │ ├── faceted_search_with_tweaked_score.rs │ ├── filter_aggregation.rs │ ├── fuzzy_search.rs │ ├── index_from_multiple_threads.rs │ ├── index_with_json.rs │ ├── integer_range_search.rs │ ├── ip_field.rs │ ├── iterating_docs_and_positions.rs │ ├── json_field.rs │ ├── phrase_prefix_search.rs │ ├── pre_tokenized_text.rs │ ├── snippet.rs │ ├── stop_words.rs │ └── warmer.rs ├── ownedbytes/ │ ├── Cargo.toml │ └── src/ │ └── lib.rs ├── query-grammar/ │ ├── Cargo.toml │ ├── README.md │ └── src/ │ ├── infallible.rs │ ├── lib.rs │ ├── occur.rs │ ├── query_grammar.rs │ └── user_input_ast.rs ├── rustfmt.toml ├── src/ │ ├── aggregation/ │ │ ├── README.md │ │ ├── accessor_helpers.rs │ │ ├── agg_data.rs │ │ ├── agg_limits.rs │ │ ├── agg_req.rs │ │ ├── agg_result.rs │ │ ├── agg_tests.rs │ │ ├── bucket/ │ │ │ ├── composite/ │ │ │ │ ├── accessors.rs │ │ │ │ ├── calendar_interval.rs │ │ │ │ ├── collector.rs │ │ │ │ ├── map.rs │ │ │ │ ├── mod.rs │ │ │ │ └── numeric_types.rs │ │ │ ├── filter.rs │ │ │ ├── histogram/ │ │ │ │ ├── date_histogram.rs │ │ │ │ ├── histogram.rs │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ ├── range.rs │ │ │ ├── term_agg.rs │ │ │ └── term_missing_agg.rs │ │ ├── cached_sub_aggs.rs │ │ ├── collector.rs │ │ ├── date.rs │ │ ├── error.rs │ │ ├── intermediate_agg_result.rs │ │ ├── metric/ │ │ │ ├── average.rs │ │ │ ├── cardinality.rs │ │ │ ├── count.rs │ │ │ ├── extended_stats.rs │ │ │ ├── max.rs │ │ │ ├── min.rs │ │ │ ├── mod.rs │ │ │ ├── percentiles.rs │ │ │ ├── stats.rs │ │ │ ├── sum.rs │ │ │ └── top_hits.rs │ │ ├── mod.rs │ │ └── segment_agg_result.rs │ ├── collector/ │ │ ├── count_collector.rs │ │ ├── docset_collector.rs │ │ ├── facet_collector.rs │ │ ├── filter_collector_wrapper.rs │ │ ├── histogram_collector.rs │ │ ├── mod.rs │ │ ├── multi_collector.rs │ │ ├── sort_key/ │ │ │ ├── mod.rs │ │ │ ├── order.rs │ │ │ ├── sort_by_bytes.rs │ │ │ ├── sort_by_erased_type.rs │ │ │ ├── sort_by_score.rs │ │ │ ├── sort_by_static_fast_value.rs │ │ │ ├── sort_by_string.rs │ │ │ └── sort_key_computer.rs │ │ ├── sort_key_top_collector.rs │ │ ├── tests.rs │ │ ├── top_collector.rs │ │ └── top_score_collector.rs │ ├── compat_tests.rs │ ├── core/ │ │ ├── executor.rs │ │ ├── json_utils.rs │ │ ├── mod.rs │ │ ├── searcher.rs │ │ └── tests.rs │ ├── directory/ │ │ ├── composite_file.rs │ │ ├── directory.rs │ │ ├── directory_lock.rs │ │ ├── error.rs │ │ ├── footer.rs │ │ ├── managed_directory.rs │ │ ├── mmap_directory/ │ │ │ ├── file_watcher.rs │ │ │ └── mod.rs │ │ ├── mod.rs │ │ ├── ram_directory.rs │ │ ├── tests.rs │ │ └── watch_event_router.rs │ ├── docset.rs │ ├── error.rs │ ├── fastfield/ │ │ ├── alive_bitset.rs │ │ ├── error.rs │ │ ├── facet_reader.rs │ │ ├── mod.rs │ │ ├── readers.rs │ │ └── writer.rs │ ├── fieldnorm/ │ │ ├── code.rs │ │ ├── mod.rs │ │ ├── reader.rs │ │ ├── serializer.rs │ │ └── writer.rs │ ├── functional_test.rs │ ├── future_result.rs │ ├── index/ │ │ ├── index.rs │ │ ├── index_meta.rs │ │ ├── inverted_index_reader.rs │ │ ├── mod.rs │ │ ├── segment.rs │ │ ├── segment_component.rs │ │ ├── segment_id.rs │ │ └── segment_reader.rs │ ├── indexer/ │ │ ├── delete_queue.rs │ │ ├── doc_id_mapping.rs │ │ ├── doc_opstamp_mapping.rs │ │ ├── flat_map_with_buffer.rs │ │ ├── index_writer.rs │ │ ├── index_writer_status.rs │ │ ├── indexing_term.rs │ │ ├── log_merge_policy.rs │ │ ├── merge_index_test.rs │ │ ├── merge_operation.rs │ │ ├── merge_policy.rs │ │ ├── merger.rs │ │ ├── mod.rs │ │ ├── operation.rs │ │ ├── path_to_unordered_id.rs │ │ ├── prepared_commit.rs │ │ ├── segment_entry.rs │ │ ├── segment_manager.rs │ │ ├── segment_register.rs │ │ ├── segment_serializer.rs │ │ ├── segment_updater.rs │ │ ├── segment_writer.rs │ │ ├── single_segment_index_writer.rs │ │ └── stamper.rs │ ├── lib.rs │ ├── macros.rs │ ├── positions/ │ │ ├── mod.rs │ │ ├── reader.rs │ │ └── serializer.rs │ ├── postings/ │ │ ├── block_search.rs │ │ ├── block_segment_postings.rs │ │ ├── compression/ │ │ │ ├── mod.rs │ │ │ └── vint.rs │ │ ├── indexing_context.rs │ │ ├── json_postings_writer.rs │ │ ├── loaded_postings.rs │ │ ├── mod.rs │ │ ├── per_field_postings_writer.rs │ │ ├── postings.rs │ │ ├── postings_writer.rs │ │ ├── recorder.rs │ │ ├── segment_postings.rs │ │ ├── serializer.rs │ │ ├── skip.rs │ │ └── term_info.rs │ ├── query/ │ │ ├── all_query.rs │ │ ├── automaton_weight.rs │ │ ├── bitset/ │ │ │ └── mod.rs │ │ ├── bm25.rs │ │ ├── boolean_query/ │ │ │ ├── block_wand.rs │ │ │ ├── boolean_query.rs │ │ │ ├── boolean_weight.rs │ │ │ └── mod.rs │ │ ├── boost_query.rs │ │ ├── const_score_query.rs │ │ ├── disjunction.rs │ │ ├── disjunction_max_query.rs │ │ ├── empty_query.rs │ │ ├── exclude.rs │ │ ├── exist_query.rs │ │ ├── explanation.rs │ │ ├── fuzzy_query.rs │ │ ├── intersection.rs │ │ ├── mod.rs │ │ ├── more_like_this/ │ │ │ ├── mod.rs │ │ │ ├── more_like_this.rs │ │ │ └── query.rs │ │ ├── phrase_prefix_query/ │ │ │ ├── mod.rs │ │ │ ├── phrase_prefix_query.rs │ │ │ ├── phrase_prefix_scorer.rs │ │ │ └── phrase_prefix_weight.rs │ │ ├── phrase_query/ │ │ │ ├── mod.rs │ │ │ ├── phrase_query.rs │ │ │ ├── phrase_scorer.rs │ │ │ ├── phrase_weight.rs │ │ │ ├── regex_phrase_query.rs │ │ │ └── regex_phrase_weight.rs │ │ ├── query.rs │ │ ├── query_parser/ │ │ │ ├── logical_ast.rs │ │ │ ├── mod.rs │ │ │ └── query_parser.rs │ │ ├── range_query/ │ │ │ ├── fast_field_range_doc_set.rs │ │ │ ├── mod.rs │ │ │ ├── range_query.rs │ │ │ └── range_query_fastfield.rs │ │ ├── regex_query.rs │ │ ├── reqopt_scorer.rs │ │ ├── score_combiner.rs │ │ ├── scorer.rs │ │ ├── set_query.rs │ │ ├── size_hint.rs │ │ ├── term_query/ │ │ │ ├── mod.rs │ │ │ ├── term_query.rs │ │ │ ├── term_scorer.rs │ │ │ └── term_weight.rs │ │ ├── union/ │ │ │ ├── bitset_union.rs │ │ │ ├── buffered_union.rs │ │ │ ├── mod.rs │ │ │ └── simple_union.rs │ │ ├── vec_docset.rs │ │ └── weight.rs │ ├── reader/ │ │ ├── mod.rs │ │ └── warming.rs │ ├── schema/ │ │ ├── bytes_options.rs │ │ ├── date_time_options.rs │ │ ├── document/ │ │ │ ├── de.rs │ │ │ ├── default_document.rs │ │ │ ├── existing_type_impls.rs │ │ │ ├── mod.rs │ │ │ ├── owned_value.rs │ │ │ ├── se.rs │ │ │ └── value.rs │ │ ├── facet.rs │ │ ├── facet_options.rs │ │ ├── field.rs │ │ ├── field_entry.rs │ │ ├── field_type.rs │ │ ├── flags.rs │ │ ├── index_record_option.rs │ │ ├── ip_options.rs │ │ ├── json_object_options.rs │ │ ├── mod.rs │ │ ├── named_field_document.rs │ │ ├── numeric_options.rs │ │ ├── schema.rs │ │ ├── term.rs │ │ └── text_options.rs │ ├── snippet/ │ │ └── mod.rs │ ├── space_usage/ │ │ └── mod.rs │ ├── store/ │ │ ├── compression_lz4_block.rs │ │ ├── compression_zstd_block.rs │ │ ├── compressors.rs │ │ ├── decompressors.rs │ │ ├── footer.rs │ │ ├── index/ │ │ │ ├── block.rs │ │ │ ├── mod.rs │ │ │ ├── skip_index.rs │ │ │ └── skip_index_builder.rs │ │ ├── mod.rs │ │ ├── reader.rs │ │ ├── store_compressor.rs │ │ └── writer.rs │ ├── termdict/ │ │ ├── fst_termdict/ │ │ │ ├── merger.rs │ │ │ ├── mod.rs │ │ │ ├── streamer.rs │ │ │ ├── term_info_store.rs │ │ │ └── termdict.rs │ │ ├── mod.rs │ │ ├── sstable_termdict/ │ │ │ ├── merger.rs │ │ │ └── mod.rs │ │ └── tests.rs │ └── tokenizer/ │ ├── alphanum_only.rs │ ├── ascii_folding_filter.rs │ ├── empty_tokenizer.rs │ ├── facet_tokenizer.rs │ ├── lower_caser.rs │ ├── mod.rs │ ├── ngram_tokenizer.rs │ ├── raw_tokenizer.rs │ ├── regex_tokenizer.rs │ ├── remove_long.rs │ ├── simple_tokenizer.rs │ ├── split_compound_words.rs │ ├── stemmer.rs │ ├── stop_word_filter/ │ │ ├── gen_stopwords.py │ │ ├── mod.rs │ │ └── stopwords.rs │ ├── tokenized_string.rs │ ├── tokenizer.rs │ ├── tokenizer_manager.rs │ └── whitespace_tokenizer.rs ├── sstable/ │ ├── Cargo.toml │ ├── README.md │ ├── benches/ │ │ ├── ord_to_term.rs │ │ └── stream_bench.rs │ ├── src/ │ │ ├── block_match_automaton.rs │ │ ├── block_reader.rs │ │ ├── delta.rs │ │ ├── dictionary.rs │ │ ├── lib.rs │ │ ├── merge/ │ │ │ ├── heap_merge.rs │ │ │ └── mod.rs │ │ ├── sstable_index_v2.rs │ │ ├── sstable_index_v3.rs │ │ ├── streamer.rs │ │ ├── value/ │ │ │ ├── index.rs │ │ │ ├── mod.rs │ │ │ ├── range.rs │ │ │ ├── u64_monotonic.rs │ │ │ ├── vec_u32.rs │ │ │ └── void.rs │ │ └── vint.rs │ └── tests/ │ └── sstable_test.rs ├── stacker/ │ ├── Cargo.toml │ ├── Performance.md │ ├── benches/ │ │ └── bench.rs │ ├── example/ │ │ └── hashmap.rs │ ├── fuzz_test/ │ │ ├── Cargo.toml │ │ └── src/ │ │ └── main.rs │ └── src/ │ ├── arena_hashmap.rs │ ├── expull.rs │ ├── fastcmp.rs │ ├── fastcpy.rs │ ├── lib.rs │ ├── memory_arena.rs │ └── shared_arena_hashmap.rs ├── tests/ │ ├── compat_tests_data/ │ │ ├── index_v6/ │ │ │ ├── .managed.json │ │ │ ├── 00000000000000000000000000000000.fast │ │ │ ├── 00000000000000000000000000000000.fieldnorm │ │ │ ├── 00000000000000000000000000000000.idx │ │ │ ├── 00000000000000000000000000000000.pos │ │ │ ├── 00000000000000000000000000000000.store │ │ │ ├── 00000000000000000000000000000000.term │ │ │ └── meta.json │ │ └── index_v7/ │ │ ├── .managed.json │ │ ├── 000002f0000000000000000000000000.fast │ │ ├── 000002f0000000000000000000000000.fieldnorm │ │ ├── 000002f0000000000000000000000000.idx │ │ ├── 000002f0000000000000000000000000.pos │ │ ├── 000002f0000000000000000000000000.store │ │ ├── 000002f0000000000000000000000000.term │ │ └── meta.json │ └── failpoints/ │ └── mod.rs └── tokenizer-api/ ├── Cargo.toml ├── README.md └── src/ └── lib.rs ================================================ FILE CONTENTS ================================================ ================================================ FILE: .claude/skills/rationalize-deps/SKILL.md ================================================ --- name: rationalize-deps description: Analyze Cargo.toml dependencies and attempt to remove unused features to reduce compile times and binary size --- # Rationalize Dependencies This skill analyzes Cargo.toml dependencies to identify and remove unused features. ## Overview Many crates enable features by default that may not be needed. This skill: 1. Identifies dependencies with default features enabled 2. Tests if `default-features = false` works 3. Identifies which specific features are actually needed 4. Verifies compilation after changes ## Step 1: Identify the target Ask the user which crate(s) to analyze: - A specific crate name (e.g., "tokio", "serde") - A specific workspace member (e.g., "quickwit-search") - "all" to scan the entire workspace ## Step 2: Analyze current dependencies For the workspace Cargo.toml (`quickwit/Cargo.toml`), list dependencies that: - Do NOT have `default-features = false` - Have default features that might be unnecessary Run: `cargo tree -p -f "{p} {f}" --edges features` to see what features are actually used. ## Step 3: For each candidate dependency ### 3a: Check the crate's default features Look up the crate on crates.io or check its Cargo.toml to understand: - What features are enabled by default - What each feature provides Use: `cargo metadata --format-version=1 | jq '.packages[] | select(.name == "") | .features'` ### 3b: Try disabling default features Modify the dependency in `quickwit/Cargo.toml`: From: ```toml some-crate = { version = "1.0" } ``` To: ```toml some-crate = { version = "1.0", default-features = false } ``` ### 3c: Run cargo check Run: `cargo check --workspace` (or target specific packages for faster feedback) If compilation fails: 1. Read the error messages to identify which features are needed 2. Add only the required features explicitly: ```toml some-crate = { version = "1.0", default-features = false, features = ["needed-feature"] } ``` 3. Re-run cargo check ### 3d: Binary search for minimal features If there are many default features, use binary search: 1. Start with no features 2. If it fails, add half the default features 3. Continue until you find the minimal set ## Step 4: Document findings For each dependency analyzed, report: - Original configuration - New configuration (if changed) - Features that were removed - Any features that are required ## Step 5: Verify full build After all changes, run: ```bash cargo check --workspace --all-targets cargo test --workspace --no-run ``` ## Common Patterns ### Serde Often only needs `derive`: ```toml serde = { version = "1.0", default-features = false, features = ["derive", "std"] } ``` ### Tokio Identify which runtime features are actually used: ```toml tokio = { version = "1.0", default-features = false, features = ["rt-multi-thread", "macros", "sync"] } ``` ### Reqwest Often doesn't need all TLS backends: ```toml reqwest = { version = "0.11", default-features = false, features = ["rustls-tls", "json"] } ``` ## Rollback If changes cause issues: ```bash git checkout quickwit/Cargo.toml cargo check --workspace ``` ## Tips - Start with large crates that have many default features (tokio, reqwest, hyper) - Use `cargo bloat --crates` to identify large dependencies - Check `cargo tree -d` for duplicate dependencies that might indicate feature conflicts - Some features are needed only for tests - consider using `[dev-dependencies]` features ================================================ FILE: .claude/skills/simple-pr/SKILL.md ================================================ --- name: simple-pr description: Create a simple PR from staged changes with an auto-generated commit message disable-model-invocation: true --- # Simple PR Follow these steps to create a simple PR from staged changes: ## Step 1: Check workspace state Run: `git status` Verify that all changes have been staged (no unstaged changes). If there are unstaged changes, abort and ask the user to stage their changes first with `git add`. Also verify that we are on the `main` branch. If not, abort and ask the user to switch to main first. ## Step 2: Ensure main is up to date Run: `git pull origin main` This ensures we're working from the latest code. ## Step 3: Review staged changes Run: `git diff --cached` Review the staged changes to understand what the PR will contain. ## Step 4: Generate commit message Based on the staged changes, generate a concise commit message (1-2 sentences) that describes the "why" rather than the "what". Display the proposed commit message to the user and ask for confirmation before proceeding. ## Step 5: Create a new branch Get the git username: `git config user.name | tr ' ' '-' | tr '[:upper:]' '[:lower:]'` Create a short, descriptive branch name based on the changes (e.g., `fix-typo-in-readme`, `add-retry-logic`, `update-deps`). Create and checkout the branch: `git checkout -b {username}/{short-descriptive-name}` ## Step 6: Commit changes Commit with the message from step 3: ``` git commit -m "{commit-message}" ``` ## Step 7: Push and open a PR Push the branch and open a PR: ``` git push -u origin {branch-name} gh pr create --title "{commit-message-title}" --body "{longer-description-if-needed}" ``` Report the PR URL to the user when complete. ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: fulmicoton patreon: # Replace with a single Patreon username open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/ISSUE_TEMPLATE/actions.md ================================================ --- name: Actions about: Actions not directly related to producing code. --- # Actions title Action description. e.g. - benchmark - investigate and report - etc. ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve --- **Describe the bug** - What did you do? - What happened? - What was expected? **Which version of tantivy are you using?** If "master", ideally give the specific sha1 revision. **To Reproduce** If your bug is deterministic, can you give a minimal reproducing code? Some bugs are not deterministic. Can you describe with precision in which context it happened? If this is possible, can you share your code? ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **[Optional] describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. ================================================ FILE: .github/ISSUE_TEMPLATE/question.md ================================================ --- name: Question about: Ask any question about tantivy's usage... --- Try to be specific about your use case... ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: cargo directory: "/" schedule: interval: daily time: "20:00" open-pull-requests-limit: 10 - package-ecosystem: "github-actions" directory: "/" schedule: interval: daily time: "20:00" open-pull-requests-limit: 10 ================================================ FILE: .github/workflows/coverage.yml ================================================ name: Coverage on: push: branches: [main] # Ensures that we cancel running jobs for the same PR / same workflow. concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust run: rustup toolchain install nightly-2025-12-01 --profile minimal --component llvm-tools-preview - uses: Swatinem/rust-cache@v2 - uses: taiki-e/install-action@cargo-llvm-cov - name: Generate code coverage run: cargo +nightly-2025-12-01 llvm-cov --all-features --workspace --doctests --lcov --output-path lcov.info - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 continue-on-error: true with: token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos files: lcov.info fail_ci_if_error: true ================================================ FILE: .github/workflows/long_running.yml ================================================ name: Long running tests on: push: branches: [ main ] env: CARGO_TERM_COLOR: always NUM_FUNCTIONAL_TEST_ITERATIONS: 20000 # Ensures that we cancel running jobs for the same PR / same workflow. concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install stable uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal override: true - name: Run indexing_unsorted run: cargo test indexing_unsorted -- --ignored - name: Run indexing_sorted run: cargo test indexing_sorted -- --ignored ================================================ FILE: .github/workflows/test.yml ================================================ name: Unit tests on: push: branches: [ main ] pull_request: branches: [ main ] env: CARGO_TERM_COLOR: always # Ensures that we cancel running jobs for the same PR / same workflow. concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install nightly uses: actions-rs/toolchain@v1 with: toolchain: nightly profile: minimal components: rustfmt - name: Install stable uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal components: clippy - uses: Swatinem/rust-cache@v2 - name: Check Formatting run: cargo +nightly fmt --all -- --check - name: Check Stable Compilation run: cargo build --all-features - name: Check Bench Compilation run: cargo +nightly bench --no-run --profile=dev --all-features - uses: actions-rs/clippy-check@v1 with: toolchain: stable token: ${{ secrets.GITHUB_TOKEN }} args: --tests test: runs-on: ubuntu-latest strategy: matrix: features: - { label: "all", flags: "mmap,stopwords,lz4-compression,zstd-compression,failpoints,stemmer" } - { label: "quickwit", flags: "mmap,quickwit,failpoints" } - { label: "none", flags: "" } name: test-${{ matrix.features.label}} steps: - uses: actions/checkout@v4 - name: Install stable uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal override: true - uses: taiki-e/install-action@nextest - uses: Swatinem/rust-cache@v2 - name: Run tests run: | # if matrix.feature.flags is empty then run on --lib to avoid compiling examples # (as most of them rely on mmap) otherwise run all if [ -z "${{ matrix.features.flags }}" ]; then cargo +stable nextest run --lib --no-default-features --verbose --workspace else cargo +stable nextest run --features ${{ matrix.features.flags }} --no-default-features --verbose --workspace fi - name: Run doctests run: | # if matrix.feature.flags is empty then run on --lib to avoid compiling examples # (as most of them rely on mmap) otherwise run all if [ -z "${{ matrix.features.flags }}" ]; then echo "no doctest for no feature flag" else cargo +stable test --doc --features ${{ matrix.features.flags }} --verbose --workspace fi ================================================ FILE: .gitignore ================================================ tantivy.iml .cargo proptest-regressions *.swp target target/debug .vscode target/release Cargo.lock benchmark .DS_Store *.bk .idea trace.dat cargo-timing* control variable ================================================ FILE: ARCHITECTURE.md ================================================ # Tantivy ## What is tantivy? Tantivy is a library that is meant to build search engines. Although it is by no means a port of Lucene, its architecture is strongly inspired by it. If you are familiar with Lucene, you may be struck by the overlapping vocabulary. This is not fortuitous. Tantivy's bread and butter is to address the problem of full-text search : Given a large set of textual documents, and a text query, return the K-most relevant documents in a very efficient way. To execute these queries rapidly, the tantivy needs to build an index beforehand. The relevance score implemented in the tantivy is not configurable. Tantivy uses the same score as the default similarity used in Lucene / Elasticsearch, called [BM25](https://en.wikipedia.org/wiki/Okapi_BM25). But tantivy's scope does not stop there. Numerous features are required to power rich-search applications. For instance, one may want to: - compute the count of documents matching a query in the different section of an e-commerce website, - display an average price per meter square for a real estate search engine, - take into account historical user data to rank documents in a specific way, - or even use tantivy to power an OLAP database. A more abstract description of the problem space tantivy is trying to address is the following. Ingest a large set of documents, create an index that makes it possible to rapidly select all documents matching a given predicate (also known as a query) and collect some information about them ([See collector](#collector-define-what-to-do-with-matched-documents)). Roughly speaking the design is following these guiding principles: - Search should be O(1) in memory. - Indexing should be O(1) in memory. (In practice it is just sublinear) - Search should be as fast as possible This comes at the cost of the dynamicity of the index: while it is possible to add, and delete documents from our corpus, the tantivy is designed to handle these updates in large batches. ## [core/](src/core): Index, segments, searchers Core contains all of the high-level code to make it possible to create an index, add documents, delete documents and commit. This is both the most high-level part of tantivy, the least performance-sensitive one, the seemingly most mundane code... And paradoxically the most complicated part. ### Index and Segments A tantivy index is a collection of smaller independent immutable segments. Each segment contains its own independent set of data structures. A segment is identified by a segment id that is in fact a UUID. The file of a segment has the format ```segment-id . ext``` The extension signals which data structure (or [`SegmentComponent`](src/index/segment_component.rs)) is stored in the file. A small `meta.json` file is in charge of keeping track of the list of segments, as well as the schema. On commit, one segment per indexing thread is written to disk, and the `meta.json` is then updated atomically. For a better idea of how indexing works, you may read the [following blog post](https://fulmicoton.com/posts/behold-tantivy-part2/). ### Deletes Deletes happen by deleting a "term". Tantivy does not offer any notion of primary id, so it is up to the user to use a field in their schema as if it was a primary id, and delete the associated term if they want to delete only one specific document. On commit, tantivy will find all of the segments with documents matching this existing term and remove from [alive bitset file](src/fastfield/alive_bitset.rs) that represents the bitset of the alive document ids. Like all segment files, this file is immutable. Because it is possible to have more than one alive bitset file at a given instant, the alive bitset filename has the format ```segment_id . commit_opstamp . del```. An opstamp is simply an incremental id that identifies any operation applied to the index. For instance, performing a commit or adding a document. ### DocId Within a segment, all documents are identified by a DocId that ranges within `[0, max_doc)`. where `max_doc` is the number of documents in the segment, (deleted or not). Having such a compact `DocId` space is key to the compression of our data structures. The DocIds are simply allocated in the order documents are added to the index. ### Merges In separate threads, tantivy's index writer search for opportunities to merge segments. The point of segment merge is to: - eventually get rid of tombstoned documents - reduce the otherwise ever-growing number of segments. Indeed, while having several segments instead of one does not hurt search too much, having hundreds can have a measurable impact on the search performance. ### Searcher The user of the library usually does not need to know about the existence of Segments. Searching is done through an object called a [`Searcher`](src/core/searcher.rs), that captures a snapshot of the index at one point of time, by holding a list of [SegmentReader](src/core/segment_reader.rs). In other words, regardless of commits, file garbage collection, or segment merge that might happen, as long as the user holds and reuse the same [Searcher](src/core/searcher.rs), search will happen on an immutable snapshot of the index. ## [directory/](src/directory): Where should the data be stored? Tantivy, like Lucene, abstracts the place where the data should be stored in a key-trait called [`Directory`](src/directory/directory.rs). Contrary to Lucene however, "files" are quite different from some kind of `io::Read` object. Check out [`src/directory/directory.rs`](src/directory/directory.rs) trait for more details. Tantivy ships two main directory implementation: the `MmapDirectory` and the `RamDirectory`, but users can extend tantivy with their own implementation. ## [schema/](src/schema): What are documents? Tantivy's document follows a very strict schema, decided before building any index. The schema defines all of the fields that the indexes [`Document`](src/schema/document/mod.rs) may and should contain, their types (`text`, `i64`, `u64`, `Date`, ...) as well as how it should be indexed / represented in tantivy. Depending on the type of the field, you can decide to - put it in the docstore - store it as a fast field - index it Practically, tantivy will push values associated with this type to up to 3 respective data structures. *Limitations* As of today, tantivy's schema imposes a 1:1 relationship between a field that is being ingested and a field represented in the search index. In sophisticated search application, it is fairly common to want to index a field twice using different tokenizers, or to index the concatenation of several fields together into one field. This is not something tantivy supports, and it is up to the user to duplicate field / concatenate fields before feeding them to tantivy. ## General information about these data structures All data structures in tantivy, have: - a writer - a serializer - a reader The writer builds an in-memory representation of a batch of documents. This representation is not searchable. It is just meant as an intermediary mutable representation, to which we can sequentially add the document of a batch. At the end of the batch (or if a memory limit is reached), this representation is then converted into an on-disk immutable representation, that is extremely compact. This conversion is done by the serializer. Finally, the reader is in charge of offering an API to read on this on-disk read-only representation. In tantivy, readers are designed to require very little anonymous memory. The data is read straight from an mmapped file, and loading an index is as fast as mmapping its files. ## [store/](src/store): Here is my DocId, Gimme my document The docstore is a row-oriented storage that, for each document, stores a subset of the fields that are marked as stored in the schema. The docstore is compressed using a general-purpose algorithm like LZ4. **Useful for** In search engines, it is often used to display search results. Once the top 10 documents have been identified, we fetch them from the store, and display them or their snippet on the search result page (aka SERP). **Not useful for** Fetching a document from the store is typically a "slow" operation. It usually consists in - searching into a compact tree-like data structure to find the position of the right block. - decompressing a small block - returning the document from this block. It is NOT meant to be called for every document matching a query. As a rule of thumb, if you hit the docstore more than 100 times per search query, you are probably misusing tantivy. ## [fastfield/](src/fastfield): Here is my DocId, Gimme my value Fast fields are stored in a column-oriented storage that allows for random access. The only compression applied is bitpacking. The column comes with two meta data. The minimum value in the column and the number of bits per doc. Fetching a value for a `DocId` is then as simple as computing ```rust min_value + fetch_bits(num_bits * doc_id..num_bits * (doc_id+1)) ``` This operation just requires one memory fetch. Because, DocSets are scanned through in order (DocId are iterated in a sorted manner) which also help locality. In Lucene's jargon, fast fields are called DocValues. **Useful for** They are typically integer values that are useful to either rank or compute aggregate over all of the documents matching a query (aka [DocSet](src/docset.rs)). For instance, one could define a function to combine upvotes with tantivy's internal relevancy score. This can be done by fetching a fast field during scoring. One could also compute the mean price of the items matching a query in an e-commerce website. This can be done by fetching a fast field in a collector. Finally one could decide to post-filter a docset to remove docset with a price within a specific range. If the ratio of filtered out documents is not too low, an efficient way to do this is to fetch the price and apply the filter on the collector side. Aside from integer values, it is also possible to store an actual byte payload. For advanced search engine, it is possible to store all of the features required for learning-to-rank in a byte payload, access it during search, and apply the learning-to-rank model. Finally facets are a specific kind of fast field, and the associated source code is in [`fastfield/facet_reader.rs`](src/fastfield/facet_reader.rs). # The inverted search index The inverted index is the core part of full-text search. When presented a new document with the text field "Hello, happy tax payer!", tantivy breaks it into a list of so-called tokens. In addition to just splitting these strings into tokens, it might also do different kinds of operations like dropping the punctuation, converting the character to lowercase, apply stemming, etc. Tantivy makes it possible to configure the operations to be applied in the schema (tokenizer/ is the place where these operations are implemented). For instance, the default tokenizer of tantivy would break our text into: `[hello, happy, tax, payer]`. The document will therefore be registered in the inverted index as containing the terms `[text:hello, text:happy, text:tax, text:payer]`. The role of the inverted index is, when given a term, gives us in return a very fast iterator over the sorted doc ids that match the term. Such an iterator is called a posting list. In addition to giving us `DocId`, they can also give us optionally the number of occurrence of the term for each document, also called term frequency or TF. These iterators being sorted by DocId, one can create an iterator over the document containing `text:tax AND text:payer`, `(text:tax AND text:payer) OR (text:contribuable)` or any boolean expression. In order to represent the function ```Term ⟶ Posting``` The inverted index actually consists of two data structures chained together. - [Term](src/schema/term.rs) ⟶ [TermInfo](src/postings/term_info.rs) is addressed by the term dictionary. - [TermInfo](src/postings/term_info.rs) ⟶ [Posting](src/postings/postings.rs) is addressed by the posting lists. Where [TermInfo](src/postings/term_info.rs) is an object containing some meta data about a term. ## [termdict/](src/termdict): Here is a term, give me the [TermInfo](src/postings/term_info.rs) Tantivy's term dictionary is mainly in charge of supplying the function [Term](src/schema/term.rs) ⟶ [TermInfo](src/postings/term_info.rs) It is itself broken into two parts. - [Term](src/schema/term.rs) ⟶ [TermOrdinal](src/termdict/mod.rs) is addressed by a finite state transducer, implemented by the fst crate. - [TermOrdinal](src/termdict/mod.rs) ⟶ [TermInfo](src/postings/term_info.rs) is addressed by the term info store. ## [postings/](src/postings): Iterate over documents... very fast A posting list makes it possible to store a sorted list of doc ids and for each doc store a term frequency as well. The posting lists are stored in a separate file. The [TermInfo](src/postings/term_info.rs) contains an offset into that file and a number of documents for the given posting list. Both are required and sufficient to read the posting list. The posting list is organized in block of 128 documents. One block of doc ids is followed by one block of term frequencies. The doc ids are delta encoded and bitpacked. The term frequencies are bitpacked. Because the number of docs is rarely a multiple of 128, the last block may contain an arbitrary number of docs between 1 and 127 documents. We then use variable int encoding instead of bitpacking. ## [positions/](src/positions): Where are my terms within the documents? Phrase queries make it possible to search for documents containing a specific sequence of terms. For instance, when the phrase query "the art of war" does not match "the war of art". To make it possible, it is possible to specify in the schema that a field should store positions in addition to being indexed. The token positions of all of the terms are then stored in a separate file with the extension `.pos`. The [TermInfo](src/postings/term_info.rs) gives an offset (expressed in position this time) in this file. As we iterate through the docset, we advance the position reader by the number of term frequencies of the current document. ## [fieldnorm/](src/fieldnorm): Here is my doc, how many tokens in this field? The [BM25](https://en.wikipedia.org/wiki/Okapi_BM25) formula also requires to know the number of tokens stored in a specific field for a given document. We store this information on one byte per document in the fieldnorm. The fieldnorm is therefore compressed. Values up to 40 are encoded unchanged. ## [tokenizer/](src/tokenizer): How should we process text? Text processing is key to a good search experience. Splits or normalize your text too much, and the search results will have a less precision and a higher recall. Do not normalize, or under split your text, you will end up with a higher precision and a lesser recall. Text processing can be configured by selecting an off-the-shelf [`Tokenizer`](./src/tokenizer/tokenizer.rs) or implementing your own to first split the text into tokens, and then chain different [`TokenFilter`](src/tokenizer/tokenizer.rs)'s to it. Tantivy's comes with few tokenizers, but external crates are offering advanced tokenizers, such as [Lindera](https://crates.io/crates/lindera) for Japanese. ## [query/](src/query): Define and compose queries The [Query](src/query/query.rs) trait defines what a query is. Due to the necessity for some queries to compute some statistics over the entire index, and because the index is composed of several `SegmentReader`, the path from transforming a `Query` to an iterator over documents is slightly convoluted, but fundamentally, this is what a Query is. The iterator over a document comes with some scoring function. The resulting trait is called a [Scorer](src/query/scorer.rs) and is specific to a segment. Different queries can be combined using the [BooleanQuery](src/query/boolean_query/). Tantivy comes with different types of queries and can be extended by implementing the `Query`, `Weight`, and `Scorer` traits. ## [collector](src/collector): Define what to do with matched documents Collectors define how to aggregate the documents matching a query, in the broadest sense possible. The search will push matched documents one by one, calling their `fn collect(doc: DocId, score: Score);` method. Users may implement their own collectors by implementing the [Collector](src/collector/mod.rs) trait. ## [query-grammar](query-grammar): Defines the grammar of the query parser While the [QueryParser](src/query/query_parser/query_parser.rs) struct is located in the `query/` directory, the actual parser combinator used to convert user queries into an AST is in an external crate called `query-grammar`. This part was externalized to lighten the work of the compiler. ================================================ FILE: AUTHORS ================================================ # This is the list of authors of tantivy for copyright purposes. Paul Masurel Laurentiu Nicola Dru Sellers Ashley Mannix Michael J. Curry Jason Wolfe # As an employee of Google I am required to add Google LLC # in the list of authors, but this project is not affiliated to Google # in any other way. Google LLC ================================================ FILE: CHANGELOG.md ================================================ Tantivy 0.25 ================================ ## Bugfixes - fix union performance regression in tantivy 0.24 [#2663](https://github.com/quickwit-oss/tantivy/pull/2663)(@PSeitz) - make zstd optional in sstable [#2633](https://github.com/quickwit-oss/tantivy/pull/2633)(@Parth) - Fix TopDocs::order_by_string_fast_field for asc order [#2672](https://github.com/quickwit-oss/tantivy/pull/2672)(@stuhood @PSeitz) ## Features/Improvements - add docs/example and Vec values to sstable [#2660](https://github.com/quickwit-oss/tantivy/pull/2660)(@PSeitz) - Add string fast field support to `TopDocs`. [#2642](https://github.com/quickwit-oss/tantivy/pull/2642)(@stuhood) - update edition to 2024 [#2620](https://github.com/quickwit-oss/tantivy/pull/2620)(@PSeitz) - Allow optional spaces between the field name and the value in the query parser [#2678](https://github.com/quickwit-oss/tantivy/pull/2678)(@Darkheir) - Support mixed field types in query parser [#2676](https://github.com/quickwit-oss/tantivy/pull/2676)(@trinity-1686a) - Add per-field size details [#2679](https://github.com/quickwit-oss/tantivy/pull/2679)(@fulmicoton) Tantivy 0.24.2 ================================ - Fix TopNComputer for reverse order. [#2672](https://github.com/quickwit-oss/tantivy/pull/2672)(@stuhood @PSeitz) Affected queries are [order_by_fast_field](https://docs.rs/tantivy/latest/tantivy/collector/struct.TopDocs.html#method.order_by_fast_field) and [order_by_u64_field](https://docs.rs/tantivy/latest/tantivy/collector/struct.TopDocs.html#method.order_by_u64_field) for `Order::Asc` Tantivy 0.24.1 ================================ - Fix: bump required rust version to 1.81 Tantivy 0.24 ================================ Tantivy 0.24 will be backwards compatible with indices created with v0.22 and v0.21. The new minimum rust version will be 1.75. Tantivy 0.23 will be skipped. #### Bugfixes - fix potential endless loop in merge [#2457](https://github.com/quickwit-oss/tantivy/pull/2457)(@PSeitz) - fix bug that causes out-of-order sstable key. [#2445](https://github.com/quickwit-oss/tantivy/pull/2445)(@fulmicoton) - fix ReferenceValue API flaw [#2372](https://github.com/quickwit-oss/tantivy/pull/2372)(@PSeitz) - fix `OwnedBytes` debug panic [#2512](https://github.com/quickwit-oss/tantivy/pull/2512)(@b41sh) - catch panics during merges [#2582](https://github.com/quickwit-oss/tantivy/pull/2582)(@rdettai) - switch from u32 to usize in bitpacker. This enables multivalued columns larger than 4GB, which crashed during merge before. [#2581](https://github.com/quickwit-oss/tantivy/pull/2581) [#2586](https://github.com/quickwit-oss/tantivy/pull/2586)(@fulmicoton-dd @PSeitz) #### Breaking API Changes - remove index sorting [#2434](https://github.com/quickwit-oss/tantivy/pull/2434)(@PSeitz) #### Features/Improvements - **Aggregation** - Support for cardinality aggregation [#2337](https://github.com/quickwit-oss/tantivy/pull/2337) [#2446](https://github.com/quickwit-oss/tantivy/pull/2446) (@raphaelcoeffic @PSeitz) - Support for extended stats aggregation [#2247](https://github.com/quickwit-oss/tantivy/pull/2247)(@giovannicuccu) - Add Key::I64 and Key::U64 variants in aggregation to avoid f64 precision issues [#2468](https://github.com/quickwit-oss/tantivy/pull/2468)(@PSeitz) - Faster term aggregation fetch terms [#2447](https://github.com/quickwit-oss/tantivy/pull/2447)(@PSeitz) - Improve custom order deserialization [#2451](https://github.com/quickwit-oss/tantivy/pull/2451)(@PSeitz) - Change AggregationLimits behavior [#2495](https://github.com/quickwit-oss/tantivy/pull/2495)(@PSeitz) - lower contention on AggregationLimits [#2394](https://github.com/quickwit-oss/tantivy/pull/2394)(@PSeitz) - fix postcard compatibility for top_hits, add postcard test [#2346](https://github.com/quickwit-oss/tantivy/pull/2346)(@PSeitz) - reduce top hits memory consumption [#2426](https://github.com/quickwit-oss/tantivy/pull/2426)(@PSeitz) - check unsupported parameters top_hits [#2351](https://github.com/quickwit-oss/tantivy/pull/2351)(@PSeitz) - Change AggregationLimits to AggregationLimitsGuard [#2495](https://github.com/quickwit-oss/tantivy/pull/2495)(@PSeitz) - add support for counting non integer in aggregation [#2547](https://github.com/quickwit-oss/tantivy/pull/2547)(@trinity-1686a) - **Range Queries** - Support fast field range queries on json fields [#2456](https://github.com/quickwit-oss/tantivy/pull/2456)(@PSeitz) - Add support for str fast field range query [#2460](https://github.com/quickwit-oss/tantivy/pull/2460) [#2452](https://github.com/quickwit-oss/tantivy/pull/2452) [#2453](https://github.com/quickwit-oss/tantivy/pull/2453)(@PSeitz) - modify fastfield range query heuristic [#2375](https://github.com/quickwit-oss/tantivy/pull/2375)(@trinity-1686a) - add FastFieldRangeQuery for explicit range queries on fast field (for `RangeQuery` it is autodetected) [#2477](https://github.com/quickwit-oss/tantivy/pull/2477)(@PSeitz) - add format backwards-compatibility tests [#2485](https://github.com/quickwit-oss/tantivy/pull/2485)(@PSeitz) - add columnar format compatibility tests [#2433](https://github.com/quickwit-oss/tantivy/pull/2433)(@PSeitz) - Improved snippet ranges algorithm [#2474](https://github.com/quickwit-oss/tantivy/pull/2474)(@gezihuzi) - make find_field_with_default return json fields without path [#2476](https://github.com/quickwit-oss/tantivy/pull/2476)(@trinity-1686a) - Make `BooleanQuery` support `minimum_number_should_match` [#2405](https://github.com/quickwit-oss/tantivy/pull/2405)(@LebranceBW) - Make `NUM_MERGE_THREADS` configurable [#2535](https://github.com/quickwit-oss/tantivy/pull/2535)(@Barre) - **RegexPhraseQuery** `RegexPhraseQuery` supports phrase queries with regex. E.g. query "b.* b.* wolf" matches "big bad wolf". Slop is supported as well: "b.* wolf"~2 matches "big bad wolf" [#2516](https://github.com/quickwit-oss/tantivy/pull/2516)(@PSeitz) - **Optional Index in Multivalue Columnar Index** For mostly empty multivalued indices there was a large overhead during creation when iterating all docids (merge case). This is alleviated by placing an optional index in the multivalued index to mark documents that have values. This will slightly increase space and access time. [#2439](https://github.com/quickwit-oss/tantivy/pull/2439)(@PSeitz) - **Store DateTime as nanoseconds in doc store** DateTime in the doc store was truncated to microseconds previously. This removes this truncation, while still keeping backwards compatibility. [#2486](https://github.com/quickwit-oss/tantivy/pull/2486)(@PSeitz) - **Performance/Memory** - lift clauses in LogicalAst for optimized ast during execution [#2449](https://github.com/quickwit-oss/tantivy/pull/2449)(@PSeitz) - Use Vec instead of BTreeMap to back OwnedValue object [#2364](https://github.com/quickwit-oss/tantivy/pull/2364)(@fulmicoton) - Replace TantivyDocument with CompactDoc. CompactDoc is much smaller and provides similar performance. [#2402](https://github.com/quickwit-oss/tantivy/pull/2402)(@PSeitz) - Recycling buffer in PrefixPhraseScorer [#2443](https://github.com/quickwit-oss/tantivy/pull/2443)(@fulmicoton) - **Json Type** - JSON supports now all values on the root level. Previously an object was required. This enables support for flat mixed types. allow more JSON values, fix i64 special case [#2383](https://github.com/quickwit-oss/tantivy/pull/2383)(@PSeitz) - add json path constructor to term [#2367](https://github.com/quickwit-oss/tantivy/pull/2367)(@PSeitz) - **QueryParser** - fix de-escaping too much in query parser [#2427](https://github.com/quickwit-oss/tantivy/pull/2427)(@trinity-1686a) - improve query parser [#2416](https://github.com/quickwit-oss/tantivy/pull/2416)(@trinity-1686a) - Support field grouping `title:(return AND "pink panther")` [#2333](https://github.com/quickwit-oss/tantivy/pull/2333)(@trinity-1686a) - allow term starting with wildcard [#2568](https://github.com/quickwit-oss/tantivy/pull/2568)(@trinity-1686a) - Exist queries match subpath fields [#2558](https://github.com/quickwit-oss/tantivy/pull/2558)(@rdettai) - add access benchmark for columnar [#2432](https://github.com/quickwit-oss/tantivy/pull/2432)(@PSeitz) - extend indexwriter proptests [#2342](https://github.com/quickwit-oss/tantivy/pull/2342)(@PSeitz) - add bench & test for columnar merging [#2428](https://github.com/quickwit-oss/tantivy/pull/2428)(@PSeitz) - Change in Executor API [#2391](https://github.com/quickwit-oss/tantivy/pull/2391)(@fulmicoton) - Removed usage of num_cpus [#2387](https://github.com/quickwit-oss/tantivy/pull/2387)(@fulmicoton) - use bingang for agg and stacker benchmark [#2378](https://github.com/quickwit-oss/tantivy/pull/2378)[#2492](https://github.com/quickwit-oss/tantivy/pull/2492)(@PSeitz) - cleanup top level exports [#2382](https://github.com/quickwit-oss/tantivy/pull/2382)(@PSeitz) - make convert_to_fast_value_and_append_to_json_term pub [#2370](https://github.com/quickwit-oss/tantivy/pull/2370)(@PSeitz) - remove JsonTermWriter [#2238](https://github.com/quickwit-oss/tantivy/pull/2238)(@PSeitz) - validate sort by field type [#2336](https://github.com/quickwit-oss/tantivy/pull/2336)(@PSeitz) - Fix trait bound of StoreReader::iter [#2360](https://github.com/quickwit-oss/tantivy/pull/2360)(@adamreichold) - remove read_postings_no_deletes [#2526](https://github.com/quickwit-oss/tantivy/pull/2526)(@PSeitz) Tantivy 0.22.1 ================================ - Fix TopNComputer for reverse order. [#2672](https://github.com/quickwit-oss/tantivy/pull/2672)(@stuhood @PSeitz) Affected queries are [order_by_fast_field](https://docs.rs/tantivy/latest/tantivy/collector/struct.TopDocs.html#method.order_by_fast_field) and [order_by_u64_field](https://docs.rs/tantivy/latest/tantivy/collector/struct.TopDocs.html#method.order_by_u64_field) for `Order::Asc` Tantivy 0.22 ================================ Tantivy 0.22 will be able to read indices created with Tantivy 0.21. #### Bugfixes - Fix null byte handling in JSON paths (null bytes in json keys caused panic during indexing) [#2345](https://github.com/quickwit-oss/tantivy/pull/2345)(@PSeitz) - Fix bug that can cause `get_docids_for_value_range` to panic. [#2295](https://github.com/quickwit-oss/tantivy/pull/2295)(@fulmicoton) - Avoid 1 document indices by increase min memory to 15MB for indexing [#2176](https://github.com/quickwit-oss/tantivy/pull/2176)(@PSeitz) - Fix merge panic for JSON fields [#2284](https://github.com/quickwit-oss/tantivy/pull/2284)(@PSeitz) - Fix bug occurring when merging JSON object indexed with positions. [#2253](https://github.com/quickwit-oss/tantivy/pull/2253)(@fulmicoton) - Fix empty DateHistogram gap bug [#2183](https://github.com/quickwit-oss/tantivy/pull/2183)(@PSeitz) - Fix range query end check (fields with less than 1 value per doc are affected) [#2226](https://github.com/quickwit-oss/tantivy/pull/2226)(@PSeitz) - Handle exclusive out of bounds ranges on fastfield range queries [#2174](https://github.com/quickwit-oss/tantivy/pull/2174)(@PSeitz) #### Breaking API Changes - rename ReloadPolicy onCommit to onCommitWithDelay [#2235](https://github.com/quickwit-oss/tantivy/pull/2235)(@giovannicuccu) - Move exports from the root into modules [#2220](https://github.com/quickwit-oss/tantivy/pull/2220)(@PSeitz) - Accept field name instead of `Field` in FilterCollector [#2196](https://github.com/quickwit-oss/tantivy/pull/2196)(@PSeitz) - remove deprecated IntOptions and DateTime [#2353](https://github.com/quickwit-oss/tantivy/pull/2353)(@PSeitz) #### Features/Improvements - Tantivy documents as a trait: Index data directly without converting to tantivy types first [#2071](https://github.com/quickwit-oss/tantivy/pull/2071)(@ChillFish8) - encode some part of posting list as -1 instead of direct values (smaller inverted indices) [#2185](https://github.com/quickwit-oss/tantivy/pull/2185)(@trinity-1686a) - **Aggregation** - Support to deserialize f64 from string [#2311](https://github.com/quickwit-oss/tantivy/pull/2311)(@PSeitz) - Add a top_hits aggregator [#2198](https://github.com/quickwit-oss/tantivy/pull/2198)(@ditsuke) - Support bool type in term aggregation [#2318](https://github.com/quickwit-oss/tantivy/pull/2318)(@PSeitz) - Support ip addresses in term aggregation [#2319](https://github.com/quickwit-oss/tantivy/pull/2319)(@PSeitz) - Support date type in term aggregation [#2172](https://github.com/quickwit-oss/tantivy/pull/2172)(@PSeitz) - Support escaped dot when addressing field [#2250](https://github.com/quickwit-oss/tantivy/pull/2250)(@PSeitz) - Add ExistsQuery to check documents that have a value [#2160](https://github.com/quickwit-oss/tantivy/pull/2160)(@imotov) - Expose TopDocs::order_by_u64_field again [#2282](https://github.com/quickwit-oss/tantivy/pull/2282)(@ditsuke) - **Memory/Performance** - Faster TopN: replace BinaryHeap with TopNComputer [#2186](https://github.com/quickwit-oss/tantivy/pull/2186)(@PSeitz) - reduce number of allocations during indexing [#2257](https://github.com/quickwit-oss/tantivy/pull/2257)(@PSeitz) - Less Memory while indexing: docid deltas while indexing [#2249](https://github.com/quickwit-oss/tantivy/pull/2249)(@PSeitz) - Faster indexing: use term hashmap in fastfield [#2243](https://github.com/quickwit-oss/tantivy/pull/2243)(@PSeitz) - term hashmap remove copy in is_empty, unused unordered_id [#2229](https://github.com/quickwit-oss/tantivy/pull/2229)(@PSeitz) - add method to fetch block of first values in columnar [#2330](https://github.com/quickwit-oss/tantivy/pull/2330)(@PSeitz) - Faster aggregations: add fast path for full columns in fetch_block [#2328](https://github.com/quickwit-oss/tantivy/pull/2328)(@PSeitz) - Faster sstable loading: use fst for sstable index [#2268](https://github.com/quickwit-oss/tantivy/pull/2268)(@trinity-1686a) - **QueryParser** - allow newline where we allow space in query parser [#2302](https://github.com/quickwit-oss/tantivy/pull/2302)(@trinity-1686a) - allow some mixing of occur and bool in strict query parser [#2323](https://github.com/quickwit-oss/tantivy/pull/2323)(@trinity-1686a) - handle * inside term in lenient query parser [#2228](https://github.com/quickwit-oss/tantivy/pull/2228)(@trinity-1686a) - add support for exists query syntax in query parser [#2170](https://github.com/quickwit-oss/tantivy/pull/2170)(@trinity-1686a) - Add shared search executor [#2312](https://github.com/quickwit-oss/tantivy/pull/2312)(@MochiXu) - Truncate keys to u16::MAX in term hashmap [#2299](https://github.com/quickwit-oss/tantivy/pull/2299)(@PSeitz) - report if a term matched when warming up posting list [#2309](https://github.com/quickwit-oss/tantivy/pull/2309)(@trinity-1686a) - Support json fields in FuzzyTermQuery [#2173](https://github.com/quickwit-oss/tantivy/pull/2173)(@PingXia-at) - Read list of fields encoded in term dictionary for JSON fields [#2184](https://github.com/quickwit-oss/tantivy/pull/2184)(@PSeitz) - add collect_block to BoxableSegmentCollector [#2331](https://github.com/quickwit-oss/tantivy/pull/2331)(@PSeitz) - expose collect_block buffer size [#2326](https://github.com/quickwit-oss/tantivy/pull/2326)(@PSeitz) - Forward regex parser errors [#2288](https://github.com/quickwit-oss/tantivy/pull/2288)(@adamreichold) - Make FacetCounts defaultable and cloneable. [#2322](https://github.com/quickwit-oss/tantivy/pull/2322)(@adamreichold) - Derive Debug for SchemaBuilder [#2254](https://github.com/quickwit-oss/tantivy/pull/2254)(@GodTamIt) - add missing inlines to tantivy options [#2245](https://github.com/quickwit-oss/tantivy/pull/2245)(@PSeitz) Tantivy 0.21.1 ================================ #### Bugfixes - Range queries on fast fields with less values on that field than documents had an invalid end condition, leading to missing results. [#2226](https://github.com/quickwit-oss/tantivy/issues/2226)(@appaquet @PSeitz) - Increase the minimum memory budget from 3MB to 15MB to avoid single doc segments (API fix). [#2176](https://github.com/quickwit-oss/tantivy/issues/2176)(@PSeitz) Tantivy 0.21 ================================ #### Bugfixes - Fix track fast field memory consumption, which led to higher memory consumption than the budget allowed during indexing [#2148](https://github.com/quickwit-oss/tantivy/issues/2148)[#2147](https://github.com/quickwit-oss/tantivy/issues/2147)(@PSeitz) - Fix a regression from 0.20 where sort index by date wasn't working anymore [#2124](https://github.com/quickwit-oss/tantivy/issues/2124)(@PSeitz) - Fix getting the root facet on the `FacetCollector`. [#2086](https://github.com/quickwit-oss/tantivy/issues/2086)(@adamreichold) - Align numerical type priority order of columnar and query. [#2088](https://github.com/quickwit-oss/tantivy/issues/2088)(@fmassot) #### Breaking Changes - Remove support for Brotli and Snappy compression [#2123](https://github.com/quickwit-oss/tantivy/issues/2123)(@adamreichold) #### Features/Improvements - Implement lenient query parser [#2129](https://github.com/quickwit-oss/tantivy/pull/2129)(@trinity-1686a) - order_by_u64_field and order_by_fast_field allow sorting in ascending and descending order [#2111](https://github.com/quickwit-oss/tantivy/issues/2111)(@naveenann) - Allow dynamic filters in text analyzer builder [#2110](https://github.com/quickwit-oss/tantivy/issues/2110)(@fulmicoton @fmassot) - **Aggregation** - Add missing parameter for term aggregation [#2149](https://github.com/quickwit-oss/tantivy/issues/2149)[#2103](https://github.com/quickwit-oss/tantivy/issues/2103)(@PSeitz) - Add missing parameter for percentiles [#2157](https://github.com/quickwit-oss/tantivy/issues/2157)(@PSeitz) - Add missing parameter for stats,min,max,count,sum,avg [#2151](https://github.com/quickwit-oss/tantivy/issues/2151)(@PSeitz) - Improve aggregation deserialization error message [#2150](https://github.com/quickwit-oss/tantivy/issues/2150)(@PSeitz) - Add validation for type Bytes to term_agg [#2077](https://github.com/quickwit-oss/tantivy/issues/2077)(@PSeitz) - Alternative mixed field collection [#2135](https://github.com/quickwit-oss/tantivy/issues/2135)(@PSeitz) - Add missing query_terms impl for TermSetQuery. [#2120](https://github.com/quickwit-oss/tantivy/issues/2120)(@adamreichold) - Minor improvements to OwnedBytes [#2134](https://github.com/quickwit-oss/tantivy/issues/2134)(@adamreichold) - Remove allocations in split compound words [#2080](https://github.com/quickwit-oss/tantivy/issues/2080)(@PSeitz) - Ngram tokenizer now returns an error with invalid arguments [#2102](https://github.com/quickwit-oss/tantivy/issues/2102)(@fmassot) - Make TextAnalyzerBuilder public [#2097](https://github.com/quickwit-oss/tantivy/issues/2097)(@adamreichold) - Return an error when tokenizer is not found while indexing [#2093](https://github.com/quickwit-oss/tantivy/issues/2093)(@naveenann) - Delayed column opening during merge [#2132](https://github.com/quickwit-oss/tantivy/issues/2132)(@PSeitz) Tantivy 0.20.2 ================================ - Align numerical type priority order on the search side. [#2088](https://github.com/quickwit-oss/tantivy/issues/2088) (@fmassot) - Fix is_child_of function not considering the root facet. [#2086](https://github.com/quickwit-oss/tantivy/issues/2086) (@adamreichhold) Tantivy 0.20.1 ================================ - Fix building on windows with mmap [#2070](https://github.com/quickwit-oss/tantivy/issues/2070) (@ChillFish8) Tantivy 0.20 ================================ #### Bugfixes - Fix phrase queries with slop (slop supports now transpositions, algorithm that carries slop so far for num terms > 2) [#2031](https://github.com/quickwit-oss/tantivy/issues/2031)[#2020](https://github.com/quickwit-oss/tantivy/issues/2020)(@PSeitz) - Handle error for exists on MMapDirectory [#1988](https://github.com/quickwit-oss/tantivy/issues/1988) (@PSeitz) - Aggregation - Fix min doc_count empty merge bug [#2057](https://github.com/quickwit-oss/tantivy/issues/2057) (@PSeitz) - Fix: Sort order for term aggregations (sort order on key was inverted) [#1858](https://github.com/quickwit-oss/tantivy/issues/1858) (@PSeitz) #### Features/Improvements - Add PhrasePrefixQuery [#1842](https://github.com/quickwit-oss/tantivy/issues/1842) (@trinity-1686a) - Add `coerce` option for text and numbers types (convert the value instead of returning an error during indexing) [#1904](https://github.com/quickwit-oss/tantivy/issues/1904) (@PSeitz) - Add regex tokenizer [#1759](https://github.com/quickwit-oss/tantivy/issues/1759)(@mkleen) - Move tokenizer API to separate crate. Having a separate crate with a stable API will allow us to use tokenizers with different tantivy versions. [#1767](https://github.com/quickwit-oss/tantivy/issues/1767) (@PSeitz) - **Columnar crate**: New fast field handling (@fulmicoton @PSeitz) [#1806](https://github.com/quickwit-oss/tantivy/issues/1806)[#1809](https://github.com/quickwit-oss/tantivy/issues/1809) - Support for fast fields with optional values. Previously tantivy supported only single-valued and multi-value fast fields. The encoding of optional fast fields is now very compact. - Fast field Support for JSON (schemaless fast fields). Support multiple types on the same column. [#1876](https://github.com/quickwit-oss/tantivy/issues/1876) (@fulmicoton) - Unified access for fast fields over different cardinalities. - Unified storage for typed and untyped fields. - Move fastfield codecs into columnar. [#1782](https://github.com/quickwit-oss/tantivy/issues/1782) (@fulmicoton) - Sparse dense index for optional values [#1716](https://github.com/quickwit-oss/tantivy/issues/1716) (@PSeitz) - Switch to nanosecond precision in DateTime fastfield [#2016](https://github.com/quickwit-oss/tantivy/issues/2016) (@PSeitz) - **Aggregation** - Add `date_histogram` aggregation (only `fixed_interval` for now) [#1900](https://github.com/quickwit-oss/tantivy/issues/1900) (@PSeitz) - Add `percentiles` aggregations [#1984](https://github.com/quickwit-oss/tantivy/issues/1984) (@PSeitz) - [**breaking**] Drop JSON support on intermediate agg result (we use postcard as format in `quickwit` to send intermediate results) [#1992](https://github.com/quickwit-oss/tantivy/issues/1992) (@PSeitz) - Set memory limit in bytes for aggregations after which they abort (Previously there was only the bucket limit) [#1942](https://github.com/quickwit-oss/tantivy/issues/1942)[#1957](https://github.com/quickwit-oss/tantivy/issues/1957)(@PSeitz) - Add support for u64,i64,f64 fields in term aggregation [#1883](https://github.com/quickwit-oss/tantivy/issues/1883) (@PSeitz) - Allow histogram bounds to be passed as Rfc3339 [#2076](https://github.com/quickwit-oss/tantivy/issues/2076) (@PSeitz) - Add count, min, max, and sum aggregations [#1794](https://github.com/quickwit-oss/tantivy/issues/1794) (@guilload) - Switch to Aggregation without serde_untagged => better deserialization errors. [#2003](https://github.com/quickwit-oss/tantivy/issues/2003) (@PSeitz) - Switch to ms in histogram for date type (ES compatibility) [#2045](https://github.com/quickwit-oss/tantivy/issues/2045) (@PSeitz) - Reduce term aggregation memory consumption [#2013](https://github.com/quickwit-oss/tantivy/issues/2013) (@PSeitz) - Reduce agg memory consumption: Replace generic aggregation collector (which has a high memory requirement per instance) in aggregation tree with optimized versions behind a trait. - Split term collection count and sub_agg (Faster term agg with less memory consumption for cases without sub-aggs) [#1921](https://github.com/quickwit-oss/tantivy/issues/1921) (@PSeitz) - Schemaless aggregations: In combination with stacker tantivy supports now schemaless aggregations via the JSON type. - Add aggregation support for JSON type [#1888](https://github.com/quickwit-oss/tantivy/issues/1888) (@PSeitz) - Mixed types support on JSON fields in aggs [#1971](https://github.com/quickwit-oss/tantivy/issues/1971) (@PSeitz) - Perf: Fetch blocks of vals in aggregation for all cardinality [#1950](https://github.com/quickwit-oss/tantivy/issues/1950) (@PSeitz) - Allow histogram bounds to be passed as Rfc3339 [#2076](https://github.com/quickwit-oss/tantivy/issues/2076) (@PSeitz) - `Searcher` with disabled scoring via `EnableScoring::Disabled` [#1780](https://github.com/quickwit-oss/tantivy/issues/1780) (@shikhar) - Enable tokenizer on json fields [#2053](https://github.com/quickwit-oss/tantivy/issues/2053) (@PSeitz) - Enforcing "NOT" and "-" queries consistency in UserInputAst [#1609](https://github.com/quickwit-oss/tantivy/issues/1609) (@bazhenov) - Faster indexing - Refactor tokenization pipeline to use GATs [#1924](https://github.com/quickwit-oss/tantivy/issues/1924) (@trinity-1686a) - Faster term hash map [#2058](https://github.com/quickwit-oss/tantivy/issues/2058)[#1940](https://github.com/quickwit-oss/tantivy/issues/1940) (@PSeitz) - tokenizer-api: reduce Tokenizer allocation overhead [#2062](https://github.com/quickwit-oss/tantivy/issues/2062) (@PSeitz) - Refactor vint [#2010](https://github.com/quickwit-oss/tantivy/issues/2010) (@PSeitz) - Faster search - Work in batches of docs on the SegmentCollector (Only for cases without score for now) [#1937](https://github.com/quickwit-oss/tantivy/issues/1937) (@PSeitz) - Faster fast field range queries using SIMD [#1954](https://github.com/quickwit-oss/tantivy/issues/1954) (@fulmicoton) - Improve fast field range query performance [#1864](https://github.com/quickwit-oss/tantivy/issues/1864) (@PSeitz) - Make BM25 scoring more flexible [#1855](https://github.com/quickwit-oss/tantivy/issues/1855) (@alexcole) - Switch fs2 to fs4 as it is now unmaintained and does not support illumos [#1944](https://github.com/quickwit-oss/tantivy/issues/1944) (@Toasterson) - Made BooleanWeight and BoostWeight public [#1991](https://github.com/quickwit-oss/tantivy/issues/1991) (@fulmicoton) - Make index compatible with virtual drives on Windows [#1843](https://github.com/quickwit-oss/tantivy/issues/1843) (@gyk) - Add stop words for Hungarian language [#2069](https://github.com/quickwit-oss/tantivy/issues/2069) (@tnxbutno) - Auto downgrade index record option, instead of vint error [#1857](https://github.com/quickwit-oss/tantivy/issues/1857) (@PSeitz) - Enable range query on fast field for u64 compatible types [#1762](https://github.com/quickwit-oss/tantivy/issues/1762) (@PSeitz) [#1876] - sstable - Isolating sstable and stacker in independent crates. [#1718](https://github.com/quickwit-oss/tantivy/issues/1718) (@fulmicoton) - New sstable format [#1943](https://github.com/quickwit-oss/tantivy/issues/1943)[#1953](https://github.com/quickwit-oss/tantivy/issues/1953) (@trinity-1686a) - Use DeltaReader directly to implement Dictionary::ord_to_term [#1928](https://github.com/quickwit-oss/tantivy/issues/1928) (@trinity-1686a) - Use DeltaReader directly to implement Dictionary::term_ord [#1925](https://github.com/quickwit-oss/tantivy/issues/1925) (@trinity-1686a) - Add separate tokenizer manager for fast fields [#2019](https://github.com/quickwit-oss/tantivy/issues/2019) (@PSeitz) - Make construction of LevenshteinAutomatonBuilder for FuzzyTermQuery instances lazy. [#1756](https://github.com/quickwit-oss/tantivy/issues/1756) (@adamreichold) - Added support for madvise when opening an mmapped Index [#2036](https://github.com/quickwit-oss/tantivy/issues/2036) (@fulmicoton) - Rename `DatePrecision` to `DateTimePrecision` [#2051](https://github.com/quickwit-oss/tantivy/issues/2051) (@guilload) - Query Parser - Quotation mark can now be used for phrase queries. [#2050](https://github.com/quickwit-oss/tantivy/issues/2050) (@fulmicoton) - PhrasePrefixQuery is supported in the query parser via: `field:"phrase ter"*` [#2044](https://github.com/quickwit-oss/tantivy/issues/2044) (@adamreichold) - Docs - Update examples for literate docs [#1880](https://github.com/quickwit-oss/tantivy/issues/1880) (@PSeitz) - Add ip field example [#1775](https://github.com/quickwit-oss/tantivy/issues/1775) (@PSeitz) - Fix doc store cache documentation [#1821](https://github.com/quickwit-oss/tantivy/issues/1821) (@PSeitz) - Fix BooleanQuery document [#1999](https://github.com/quickwit-oss/tantivy/issues/1999) (@RT_Enzyme) - Update comments in the faceted search example [#1737](https://github.com/quickwit-oss/tantivy/issues/1737) (@DawChihLiou) Tantivy 0.19 ================================ #### Bugfixes - Fix missing fieldnorms for u64, i64, f64, bool, bytes and date [#1620](https://github.com/quickwit-oss/tantivy/pull/1620) (@PSeitz) - Fix interpolation overflow in linear interpolation fastfield codec [#1480](https://github.com/quickwit-oss/tantivy/pull/1480) (@PSeitz @fulmicoton) #### Features/Improvements - Add support for `IN` in queryparser , e.g. `field: IN [val1 val2 val3]` [#1683](https://github.com/quickwit-oss/tantivy/pull/1683) (@trinity-1686a) - Skip score calculation, when no scoring is required [#1646](https://github.com/quickwit-oss/tantivy/pull/1646) (@PSeitz) - Limit fast fields to u32 (`get_val(u32)`) [#1644](https://github.com/quickwit-oss/tantivy/pull/1644) (@PSeitz) - The `DateTime` type has been updated to hold timestamps with microseconds precision. `DateOptions` and `DatePrecision` have been added to configure Date fields. The precision is used to hint on fast values compression. Otherwise, seconds precision is used everywhere else (i.e terms, indexing) [#1396](https://github.com/quickwit-oss/tantivy/pull/1396) (@evanxg852000) - Add IP address field type [#1553](https://github.com/quickwit-oss/tantivy/pull/1553) (@PSeitz) - Add boolean field type [#1382](https://github.com/quickwit-oss/tantivy/pull/1382) (@boraarslan) - Remove Searcher pool and make `Searcher` cloneable. (@PSeitz) - Validate settings on create [#1570](https://github.com/quickwit-oss/tantivy/pull/1570) (@PSeitz) - Detect and apply gcd on fastfield codecs [#1418](https://github.com/quickwit-oss/tantivy/pull/1418) (@PSeitz) - Doc store - use separate thread to compress block store [#1389](https://github.com/quickwit-oss/tantivy/pull/1389) [#1510](https://github.com/quickwit-oss/tantivy/pull/1510) (@PSeitz @fulmicoton) - Expose doc store cache size [#1403](https://github.com/quickwit-oss/tantivy/pull/1403) (@PSeitz) - Enable compression levels for doc store [#1378](https://github.com/quickwit-oss/tantivy/pull/1378) (@PSeitz) - Make block size configurable [#1374](https://github.com/quickwit-oss/tantivy/pull/1374) (@kryesh) - Make `tantivy::TantivyError` cloneable [#1402](https://github.com/quickwit-oss/tantivy/pull/1402) (@PSeitz) - Add support for phrase slop in query language [#1393](https://github.com/quickwit-oss/tantivy/pull/1393) (@saroh) - Aggregation - Add aggregation support for date type [#1693](https://github.com/quickwit-oss/tantivy/pull/1693)(@PSeitz) - Add support for keyed parameter in range and histogram aggregations [#1424](https://github.com/quickwit-oss/tantivy/pull/1424) (@k-yomo) - Add aggregation bucket limit [#1363](https://github.com/quickwit-oss/tantivy/pull/1363) (@PSeitz) - Faster indexing - [#1610](https://github.com/quickwit-oss/tantivy/pull/1610) (@PSeitz) - [#1594](https://github.com/quickwit-oss/tantivy/pull/1594) (@PSeitz) - [#1582](https://github.com/quickwit-oss/tantivy/pull/1582) (@PSeitz) - [#1611](https://github.com/quickwit-oss/tantivy/pull/1611) (@PSeitz) - Added a pre-configured stop word filter for various language [#1666](https://github.com/quickwit-oss/tantivy/pull/1666) (@adamreichold) Tantivy 0.18 ================================ - For date values `chrono` has been replaced with `time` (@uklotzde) #1304 : - The `time` crate is re-exported as `tantivy::time` instead of `tantivy::chrono`. - The type alias `tantivy::DateTime` has been removed. - `Value::Date` wraps `time::PrimitiveDateTime` without time zone information. - Internally date/time values are stored as seconds since UNIX epoch in UTC. - Converting a `time::OffsetDateTime` to `Value::Date` implicitly converts the value into UTC. If this is not desired do the time zone conversion yourself and use `time::PrimitiveDateTime` directly instead. - Add [histogram](https://github.com/quickwit-oss/tantivy/pull/1306) aggregation (@PSeitz) - Add support for fastfield on text fields (@PSeitz) - Add terms aggregation (@PSeitz) - Add support for zstd compression (@kryesh) Tantivy 0.18.1 ================================ - Hotfix: positions computation. #1629 (@fmassot, @fulmicoton, @PSeitz) Tantivy 0.17 ================================ - LogMergePolicy now triggers merges if the ratio of deleted documents reaches a threshold (@shikhar @fulmicoton) [#115](https://github.com/quickwit-oss/tantivy/issues/115) - Adds a searcher Warmer API (@shikhar @fulmicoton) - Change to non-strict schema. Ignore fields in data which are not defined in schema. Previously this returned an error. #1211 - Facets are necessarily indexed. Existing index with indexed facets should work out of the box. Index without facets that are marked with index: false should be broken (but they were already broken in a sense). (@fulmicoton) #1195 . - Bugfix that could in theory impact durability in theory on some filesystems [#1224](https://github.com/quickwit-oss/tantivy/issues/1224) - Schema now offers not indexing fieldnorms (@lpouget) [#922](https://github.com/quickwit-oss/tantivy/issues/922) - Reduce the number of fsync calls [#1225](https://github.com/quickwit-oss/tantivy/issues/1225) - Fix opening bytes index with dynamic codec (@PSeitz) [#1278](https://github.com/quickwit-oss/tantivy/issues/1278) - Added an aggregation collector for range, average and stats compatible with Elasticsearch. (@PSeitz) - Added a JSON schema type @fulmicoton [#1251](https://github.com/quickwit-oss/tantivy/issues/1251) - Added support for slop in phrase queries @halvorboe [#1068](https://github.com/quickwit-oss/tantivy/issues/1068) Tantivy 0.16.2 ================================ - Bugfix in FuzzyTermQuery. (transposition_cost_one was not doing anything) Tantivy 0.16.1 ======================== - Major Bugfix on multivalued fastfield. #1151 - Demux operation (@PSeitz) Tantivy 0.16.0 ========================= - Bugfix in the filesum check. (@evanxg852000) #1127 - Bugfix in positions when the index is sorted by a field. (@appaquet) #1125 Tantivy 0.15.3 ========================= - Major bugfix. Deleting documents was broken when the index was sorted by a field. (@appaquet, @fulmicoton) #1101 Tantivy 0.15.2 ======================== - Major bugfix. DocStore still panics when a deleted doc is at the beginning of a block. (@appaquet) #1088 Tantivy 0.15.1 ========================= - Major bugfix. DocStore panics when first block is deleted. (@appaquet) #1077 Tantivy 0.15.0 ========================= - API Changes. Using Range instead of (start, end) in the API and internals (`FileSlice`, `OwnedBytes`, `Snippets`, ...) This change is breaking but migration is trivial. - Added an Histogram collector. (@fulmicoton) #994 - Added support for Option. (@fulmicoton) - DocAddress is now a struct (@scampi) #987 - Bugfix consistent tie break handling in facet's topk (@hardikpnsp) #357 - Date field support for range queries (@rihardsk) #516 - Added lz4-flex as the default compression scheme in tantivy (@PSeitz) #1009 - Renamed a lot of symbols to avoid all uppercasing on acronyms, as per new clippy recommendation. For instance, RAMDirectory -> RamDirectory. (@fulmicoton) - Simplified positions index format (@fulmicoton) #1022 - Moved bitpacking to bitpacker subcrate and add BlockedBitpacker, which bitpacks blocks of 128 elements (@PSeitz) #1030 - Added support for more-like-this query in tantivy (@evanxg852000) #1011 - Added support for sorting an index, e.g presorting documents in an index by a timestamp field. This can heavily improve performance for certain scenarios, by utilizing the sorted data (Top-n optimizations)(@PSeitz). #1026 - Add iterator over documents in doc store (@PSeitz). #1044 - Fix log merge policy (@PSeitz). #1043 - Add detection to avoid small doc store blocks on merge (@PSeitz). #1054 - Make doc store compression dynamic (@PSeitz). #1060 - Switch to json for footer version handling (@PSeitz). #1060 - Updated TermMerger implementation to rely on the union feature of the FST (@scampi) #469 - Add boolean marking whether position is required in the query_terms API call (@fulmicoton). #1070 Tantivy 0.14.0 ========================= - Remove dependency to atomicwrites #833 .Implemented by @fulmicoton upon suggestion and research from @asafigan). - Migrated tantivy error from the now deprecated `failure` crate to `thiserror` #760. (@hirevo) - API Change. Accessing the typed value off a `Schema::Value` now returns an Option instead of panicking if the type does not match. - Large API Change in the Directory API. Tantivy used to assume that all files could be somehow memory mapped. After this change, Directory return a `FileSlice` that can be reduced and eventually read into an `OwnedBytes` object. Long and blocking io operation are still required by they do not span over the entire file. - Added support for Brotli compression in the DocStore. (@ppodolsky) - Added helper for building intersections and unions in BooleanQuery (@guilload) - Bugfix in `Query::explain` - Removed dependency on `notify` #924. Replaced with `FileWatcher` struct that polls meta file every 500ms in background thread. (@halvorboe @guilload) - Added `FilterCollector`, which wraps another collector and filters docs using a predicate over a fast field (@barrotsteindev) - Simplified the encoding of the skip reader struct. BlockWAND max tf is now encoded over a single byte. (@fulmicoton) - `FilterCollector` now supports all Fast Field value types (@barrotsteindev) - FastField are not all loaded when opening the segment reader. (@fulmicoton) - Added an API to merge segments, see `tantivy::merge_segments` #1005. (@evanxg852000) This version breaks compatibility and requires users to reindex everything. Tantivy 0.13.2 =================== Bugfix. Acquiring a facet reader on a segment that does not contain any doc with this facet returns `None`. (#896) Tantivy 0.13.1 =================== Made `Query` and `Collector` `Send + Sync`. Updated misc dependency versions. Tantivy 0.13.0 ====================== Tantivy 0.13 introduce a change in the index format that will require you to reindex your index (BlockWAND information are added in the skiplist). The index size increase is minor as this information is only added for full blocks. If you have a massive index for which reindexing is not an option, please contact me so that we can discuss possible solutions. - Bugfix in `FuzzyTermQuery` not matching terms by prefix when it should (@Peachball) - Relaxed constraints on the custom/tweak score functions. At the segment level, they can be mut, and they are not required to be Sync + Send. - `MMapDirectory::open` does not return a `Result` anymore. - Change in the DocSet and Scorer API. (@fulmicoton). A freshly created DocSet point directly to their first doc. A sentinel value called TERMINATED marks the end of a DocSet. `.advance()` returns the new DocId. `Scorer::skip(target)` has been replaced by `Scorer::seek(target)` and returns the resulting DocId. As a result, iterating through DocSet now looks as follows ```rust let mut doc = docset.doc(); while doc != TERMINATED { // ... doc = docset.advance(); } ``` The change made it possible to greatly simplify a lot of the docset's code. - Misc internal optimization and introduction of the `Scorer::for_each_pruning` function. (@fulmicoton) - Added an offset option to the Top(.*)Collectors. (@robyoung) - Added Block WAND. Performance on TOP-K on term-unions should be greatly increased. (@fulmicoton, and special thanks to the PISA team for answering all my questions!) Tantivy 0.12.0 ====================== - Removing static dispatch in tokenizers for simplicity. (#762) - Added backward iteration for `TermDictionary` stream. (@halvorboe) - Fixed a performance issue when searching for the posting lists of a missing term (@audunhalland) - Added a configurable maximum number of docs (10M by default) for a segment to be considered for merge (@hntd187, landed by @halvorboe #713) - Important Bugfix #777, causing tantivy to retain memory mapping. (diagnosed by @poljar) - Added support for field boosting. (#547, @fulmicoton) ## How to update? Crates relying on custom tokenizer, or registering tokenizer in the manager will require some minor changes. Check to check for some code sample. Tantivy 0.11.3 ======================= - Fixed DateTime as a fast field (#735) Tantivy 0.11.2 ======================= - The future returned by `IndexWriter::merge` does not borrow `self` mutably anymore (#732) - Exposing a constructor for `WatchHandle` (#731) Tantivy 0.11.1 ===================== - Bug fix #729 Tantivy 0.11.0 ===================== - Added f64 field. Internally reuse u64 code the same way i64 does (@fdb-hiroshima) - Various bugfixes in the query parser. - Better handling of hyphens in query parser. (#609) - Better handling of whitespaces. - Closes #498 - add support for Elastic-style unbounded range queries for alphanumeric types eg. "title:>hello", "weight:>=70.5", "height:<200" (@petr-tik) - API change around `Box`. See detail in #629 - Avoid rebuilding Regex automaton whenever a regex query is reused. #639 (@brainlock) - Add footer with some metadata to index files. #605 (@fdb-hiroshima) - Add a method to check the compatibility of the footer in the index with the running version of tantivy (@petr-tik) - TopDocs collector: ensure stable sorting on equal score. #671 (@brainlock) - Added handling of pre-tokenized text fields (#642), which will enable users to load tokens created outside tantivy. See usage in examples/pre_tokenized_text. (@kkoziara) - Fix crash when committing multiple times with deleted documents. #681 (@brainlock) ## How to update? - The index format is changed. You are required to reindex your data to use tantivy 0.11. - `Box` has been replaced by a `BoxedTokenizer` struct. - Regex are now compiled when the `RegexQuery` instance is built. As a result, it can now return an error and handling the `Result` is required. - `tantivy::version()` now returns a `Version` object. This object implements `ToString()` Tantivy 0.10.2 ===================== - Closes #656. Solving memory leak. Tantivy 0.10.1 ===================== - Closes #544. A few users experienced problems with the directory watching system. Avoid watching the mmap directory until someone effectively creates a reader that uses this functionality. Tantivy 0.10.0 ===================== *Tantivy 0.10.0 index format is compatible with the index format in 0.9.0.* - Added an API to easily tweak or entirely replace the default score. See `TopDocs::tweak_score`and `TopScore::custom_score` (@fulmicoton) - Added an ASCII folding filter (@drusellers) - Bugfix in `query.count` in presence of deletes (@fulmicoton) - Added `.explain(...)` in `Query` and `Weight` to (@fulmicoton) - Added an efficient way to `delete_all_documents` in `IndexWriter` (@petr-tik). All segments are simply removed. Minor --------- - Switched to Rust 2018 (@uvd) - Small simplification of the code. Calling .freq() or .doc() when .advance() has never been called on segment postings should panic from now on. - Tokens exceeding `u16::max_value() - 4` chars are discarded silently instead of panicking. - Fast fields are now preloaded when the `SegmentReader` is created. - `IndexMeta` is now public. (@hntd187) - `IndexWriter` `add_document`, `delete_term`. `IndexWriter` is `Sync`, making it possible to use it with a `Arc>`. `add_document` and `delete_term` can only require a read lock. (@fulmicoton) - Introducing `Opstamp` as an expressive type alias for `u64`. (@petr-tik) - Stamper now relies on `AtomicU64` on all platforms (@petr-tik) - Bugfix - Files get deleted slightly earlier - Compilation resources improved (@fdb-hiroshima) ## How to update? Your program should be usable as is. ### Fast fields Fast fields used to be accessed directly from the `SegmentReader`. The API changed, you are now required to acquire your fast field reader via the `segment_reader.fast_fields()`, and use one of the typed method: - `.u64()`, `.i64()` if your field is single-valued ; - `.u64s()`, `.i64s()` if your field is multi-valued ; - `.bytes()` if your field is bytes fast field. Tantivy 0.9.0 ===================== *0.9.0 index format is not compatible with the previous index format.* - MAJOR BUGFIX : Some `Mmap` objects were being leaked, and would never get released. (@fulmicoton) - Removed most unsafe (@fulmicoton) - Indexer memory footprint improved. (VInt comp, inlining the first block. (@fulmicoton) - Stemming in other language possible (@pentlander) - Segments with no docs are deleted earlier (@barrotsteindev) - Added grouped add and delete operations. They are guaranteed to happen together (i.e. they cannot be split by a commit). In addition, adds are guaranteed to happen on the same segment. (@elbow-jason) - Removed `INT_STORED` and `INT_INDEXED`. It is now possible to use `STORED` and `INDEXED` for int fields. (@fulmicoton) - Added DateTime field (@barrotsteindev) - Added IndexReader. By default, index is reloaded automatically upon new commits (@fulmicoton) - SIMD linear search within blocks (@fulmicoton) ## How to update ? tantivy 0.9 brought some API breaking change. To update from tantivy 0.8, you will need to go through the following steps. - `schema::INT_INDEXED` and `schema::INT_STORED` should be replaced by `schema::INDEXED` and `schema::INT_STORED`. - The index now does not hold the pool of searcher anymore. You are required to create an intermediary object called `IndexReader` for this. ```rust // create the reader. You typically need to create 1 reader for the entire // lifetime of you program. let reader = index.reader()?; // Acquire a searcher (previously `index.searcher()`) is now written: let searcher = reader.searcher(); // With the default setting of the reader, you are not required to // call `index.load_searchers()` anymore. // // The IndexReader will pick up that change automatically, regardless // of whether the update was done in a different process or not. // If this behavior is not wanted, you can create your reader with // the `ReloadPolicy::Manual`, and manually decide when to reload the index // by calling `reader.reload()?`. ``` Tantivy 0.8.2 ===================== Fixing build for x86_64 platforms. (#496) No need to update from 0.8.1 if tantivy is building on your platform. Tantivy 0.8.1 ===================== Hotfix of #476. Merge was reflecting deletes before commit was passed. Thanks @barrotsteindev for reporting the bug. Tantivy 0.8.0 ===================== *No change in the index format* - API Breaking change in the collector API. (@jwolfe, @fulmicoton) - Multithreaded search (@jwolfe, @fulmicoton) Tantivy 0.7.1 ===================== *No change in the index format* - Bugfix: NGramTokenizer panics on non ascii chars - Added a space usage API Tantivy 0.7 ===================== - Skip data for doc ids and positions (@fulmicoton), greatly improving performance - Tantivy error now rely on the failure crate (@drusellers) - Added support for `AND`, `OR`, `NOT` syntax in addition to the `+`,`-` syntax - Added a snippet generator with highlight (@vigneshsarma, @fulmicoton) - Added a `TopFieldCollector` (@pentlander) Tantivy 0.6.1 ========================= - Bugfix #324. GC removing was removing file that were still in useful - Added support for parsing AllQuery and RangeQuery via QueryParser - AllQuery: `*` - RangeQuery: - Inclusive `field:[startIncl to endIncl]` - Exclusive `field:{startExcl to endExcl}` - Mixed `field:[startIncl to endExcl}` and vice versa - Unbounded `field:[start to *]`, `field:[* to end]` Tantivy 0.6 ========================== Special thanks to @drusellers and @jason-wolfe for their contributions to this release! - Removed C code. Tantivy is now pure Rust. (@fulmicoton) - BM25 (@fulmicoton) - Approximate field norms encoded over 1 byte. (@fulmicoton) - Compiles on stable rust (@fulmicoton) - Add &[u8] fastfield for associating arbitrary bytes to each document (@jason-wolfe) (#270) - Completely uncompressed - Internally: One u64 fast field for indexes, one fast field for the bytes themselves. - Add NGram token support (@drusellers) - Add Stopword Filter support (@drusellers) - Add a FuzzyTermQuery (@drusellers) - Add a RegexQuery (@drusellers) - Various performance improvements (@fulmicoton)_ Tantivy 0.5.2 =========================== - bugfix #274 - bugfix #280 - bugfix #289 Tantivy 0.5.1 ========================== - bugfix #254 : tantivy failed if no documents in a segment contained a specific field. Tantivy 0.5 ========================== - Faceting - RangeQuery - Configurable tokenization pipeline - Bugfix in PhraseQuery - Various query optimisation - Allowing very large indexes - 64 bits file address - Smarter encoding of the `TermInfo` objects Tantivy 0.4.3 ========================== - Bugfix race condition when deleting files. (#198) Tantivy 0.4.2 ========================== - Prevent usage of AVX2 instructions (#201) Tantivy 0.4.1 ========================== - Bugfix for non-indexed fields. (#199) Tantivy 0.4.0 ========================== - Raise the limit of number of fields (previously 256 fields) (@fulmicoton) - Removed u32 fields. They are replaced by u64 and i64 fields (#65) (@fulmicoton) - Optimized skip in SegmentPostings (#130) (@lnicola) - Replacing rustc_serialize by serde. Kudos to benchmark@KodrAus and @lnicola - Using error-chain (@KodrAus) - QueryParser: (@fulmicoton) - Explicit error returned when searched for a term that is not indexed - Searching for a int term via the query parser was broken `(age:1)` - Searching for a non-indexed field returns an explicit Error - Phrase query for non-tokenized field are not tokenized by the query parser. - Faster/Better indexing (@fulmicoton) - using murmurhash2 - faster merging - more memory efficient fast field writer (@lnicola ) - better handling of collisions - lesser memory usage - Added API, most notably to iterate over ranges of terms (@fulmicoton) - Bugfix that was preventing to unmap segment files, on index drop (@fulmicoton) - Made the doc! macro public (@fulmicoton) - Added an alternative implementation of the streaming dictionary (@fulmicoton) Tantivy 0.3.1 ========================== - Expose a method to trigger files garbage collection Tantivy 0.3 ========================== Special thanks to @Kodraus @lnicola @Ameobea @manuel-woelker @celaus for their contribution to this release. Thanks also to everyone in tantivy gitter chat for their advise and company :) Warning: Tantivy 0.3 is NOT backward compatible with tantivy 0.2 code and index format. You should not expect backward compatibility before tantivy 1.0. New Features ------------ - Delete. You can now delete documents from an index. - Support for windows (Thanks to @lnicola) Various Bugfixes & small improvements ---------------------------------------- - Added CI for Windows () Thanks to @KodrAus ! (#108) - Various dependy version update (Thanks to @Ameobea) #76 - Fixed several race conditions in `Index.wait_merge_threads` - Fixed #72. Mmap were never released. - Fixed #80. Fast field used to take an amplitude of 32 bits after a merge. (Ouch!) - Fixed #92. u32 are now encoded using big endian in the fst in order to make there enumeration consistent with the natural ordering. - Building binary targets for tantivy-cli (Thanks to @KodrAus) - Misc invisible bug fixes, and code cleanup. - Use ================================================ FILE: CITATION.cff ================================================ cff-version: 1.2.0 message: "If you use this software, please cite it as below." authors: - alias: Quickwit Inc. website: "https://quickwit.io" title: "tantivy" version: 0.22.0 doi: 10.5281/zenodo.13942948 date-released: 2024-10-17 url: "https://github.com/quickwit-oss/tantivy" ================================================ FILE: Cargo.toml ================================================ [package] name = "tantivy" version = "0.26.0" authors = ["Paul Masurel "] license = "MIT" categories = ["database-implementations", "data-structures"] description = """Search engine library""" documentation = "https://docs.rs/tantivy/" homepage = "https://github.com/quickwit-oss/tantivy" repository = "https://github.com/quickwit-oss/tantivy" readme = "README.md" keywords = ["search", "information", "retrieval"] edition = "2021" rust-version = "1.86" exclude = ["benches/*.json", "benches/*.txt"] [dependencies] oneshot = "0.1.13" base64 = "0.22.0" byteorder = "1.4.3" crc32fast = "1.3.2" once_cell = "1.10.0" regex = { version = "1.5.5", default-features = false, features = [ "std", "unicode", ] } aho-corasick = "1.0" tantivy-fst = "0.5" memmap2 = { version = "0.9.0", optional = true } lz4_flex = { version = "0.12", default-features = false, optional = true } zstd = { version = "0.13", optional = true, default-features = false } tempfile = { version = "3.12.0", optional = true } log = "0.4.16" serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" fs4 = { version = "0.13.1", optional = true } levenshtein_automata = "0.2.1" uuid = { version = "1.0.0", features = ["v4", "serde"] } crossbeam-channel = "0.5.4" rust-stemmers = { version = "1.2.0", optional = true } downcast-rs = "2.0.1" bitpacking = { version = "0.9.3", default-features = false, features = [ "bitpacker4x", ] } census = "0.4.2" rustc-hash = "2.0.0" thiserror = "2.0.1" htmlescape = "0.3.1" fail = { version = "0.5.0", optional = true } time = { version = "0.3.47", features = ["serde-well-known"] } smallvec = "1.8.0" rayon = "1.5.2" lru = "0.16.3" fastdivide = "0.4.0" itertools = "0.14.0" measure_time = "0.9.0" arc-swap = "1.5.0" bon = "3.3.1" columnar = { version = "0.6", path = "./columnar", package = "tantivy-columnar" } sstable = { version = "0.6", path = "./sstable", package = "tantivy-sstable", optional = true } stacker = { version = "0.6", path = "./stacker", package = "tantivy-stacker" } query-grammar = { version = "0.25.0", path = "./query-grammar", package = "tantivy-query-grammar" } tantivy-bitpacker = { version = "0.9", path = "./bitpacker" } common = { version = "0.10", path = "./common/", package = "tantivy-common" } tokenizer-api = { version = "0.6", path = "./tokenizer-api", package = "tantivy-tokenizer-api" } sketches-ddsketch = { git = "https://github.com/quickwit-oss/rust-sketches-ddsketch.git", rev = "555caf1", features = ["use_serde"] } datasketches = "0.2.0" futures-util = { version = "0.3.28", optional = true } futures-channel = { version = "0.3.28", optional = true } fnv = "1.0.7" typetag = "0.2.21" [target.'cfg(windows)'.dependencies] winapi = "0.3.9" [dev-dependencies] binggan = "0.14.2" rand = "0.9" maplit = "1.0.2" matches = "0.1.9" pretty_assertions = "1.2.1" proptest = "1.7.0" test-log = "0.2.10" futures = "0.3.21" paste = "1.0.11" more-asserts = "0.3.1" rand_distr = "0.5" time = { version = "0.3.47", features = ["serde-well-known", "macros"] } postcard = { version = "1.0.4", features = [ "use-std", ], default-features = false } [target.'cfg(not(windows))'.dev-dependencies] criterion = { version = "0.5", default-features = false } [dev-dependencies.fail] version = "0.5.0" features = ["failpoints"] [profile.release] opt-level = 3 debug = false debug-assertions = false [profile.bench] opt-level = 3 debug = true debug-assertions = false [profile.test] debug-assertions = true overflow-checks = true [features] default = ["mmap", "stopwords", "lz4-compression", "columnar-zstd-compression", "stemmer"] stemmer = ["rust-stemmers"] mmap = ["fs4", "tempfile", "memmap2"] stopwords = [] lz4-compression = ["lz4_flex"] zstd-compression = ["zstd"] # enable zstd-compression in columnar (and sstable) columnar-zstd-compression = ["columnar/zstd-compression"] failpoints = ["fail", "fail/failpoints"] unstable = [] # useful for benches. quickwit = ["sstable", "futures-util", "futures-channel"] # Compares only the hash of a string when indexing data. # Increases indexing speed, but may lead to extremely rare missing terms, when there's a hash collision. # Uses 64bit ahash. compare_hash_only = ["stacker/compare_hash_only"] [workspace] members = [ "query-grammar", "bitpacker", "common", "ownedbytes", "stacker", "sstable", "tokenizer-api", "columnar", ] # Following the "fail" crate best practises, we isolate # tests that define specific behavior in fail check points # in a different binary. # # We do that because, fail rely on a global definition of # failpoints behavior and hence, it is incompatible with # multithreading. [[test]] name = "failpoints" path = "tests/failpoints/mod.rs" required-features = ["failpoints"] [[bench]] name = "analyzer" harness = false [[bench]] name = "index-bench" harness = false [[bench]] name = "agg_bench" harness = false [[bench]] name = "exists_json" harness = false [[bench]] name = "range_query" harness = false [[bench]] name = "and_or_queries" harness = false [[bench]] name = "range_queries" harness = false [[bench]] name = "bool_queries_with_range" harness = false [[bench]] name = "str_search_and_get" harness = false [[bench]] name = "merge_segments" harness = false [[bench]] name = "regex_all_terms" harness = false ================================================ FILE: LICENSE ================================================ Copyright (c) 2018 by the project authors, as listed in the AUTHORS file. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ test: @echo "Run test only... No examples." cargo test --tests --lib fmt: cargo +nightly fmt --all ================================================ FILE: README.md ================================================ [![Docs](https://docs.rs/tantivy/badge.svg)](https://docs.rs/crate/tantivy/) [![Build Status](https://github.com/quickwit-oss/tantivy/actions/workflows/test.yml/badge.svg)](https://github.com/quickwit-oss/tantivy/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/quickwit-oss/tantivy/branch/main/graph/badge.svg)](https://codecov.io/gh/quickwit-oss/tantivy) [![Join the chat at https://discord.gg/MT27AG5EVE](https://shields.io/discord/908281611840282624?label=chat%20on%20discord)](https://discord.gg/MT27AG5EVE) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Crates.io](https://img.shields.io/crates/v/tantivy.svg)](https://crates.io/crates/tantivy) Tantivy, the fastest full-text search engine library written in Rust ## Fast full-text search engine library written in Rust **If you are looking for an alternative to Elasticsearch or Apache Solr, check out [Quickwit](https://github.com/quickwit-oss/quickwit), our distributed search engine built on top of Tantivy.** Tantivy is closer to [Apache Lucene](https://lucene.apache.org/) than to [Elasticsearch](https://www.elastic.co/products/elasticsearch) or [Apache Solr](https://lucene.apache.org/solr/) in the sense it is not an off-the-shelf search engine server, but rather a crate that can be used to build such a search engine. Tantivy is, in fact, strongly inspired by Lucene's design. ## Benchmark The following [benchmark](https://tantivy-search.github.io/bench/) breaks down the performance for different types of queries/collections. Your mileage WILL vary depending on the nature of queries and their load. Details about the benchmark can be found at this [repository](https://github.com/quickwit-oss/search-benchmark-game). ## Features - Full-text search - Configurable tokenizer (stemming available for 17 Latin languages) with third party support for Chinese ([tantivy-jieba](https://crates.io/crates/tantivy-jieba) and [cang-jie](https://crates.io/crates/cang-jie)), Japanese ([lindera](https://github.com/lindera-morphology/lindera-tantivy), [Vaporetto](https://crates.io/crates/vaporetto_tantivy), and [tantivy-tokenizer-tiny-segmenter](https://crates.io/crates/tantivy-tokenizer-tiny-segmenter)) and Korean ([lindera](https://github.com/lindera-morphology/lindera-tantivy) + [lindera-ko-dic-builder](https://github.com/lindera-morphology/lindera-ko-dic-builder)) - Fast (check out the :racehorse: :sparkles: [benchmark](https://tantivy-search.github.io/bench/) :sparkles: :racehorse:) - Tiny startup time (<10ms), perfect for command-line tools - BM25 scoring (the same as Lucene) - Natural query language (e.g. `(michael AND jackson) OR "king of pop"`) - Phrase queries search (e.g. `"michael jackson"`) - Incremental indexing - Multithreaded indexing (indexing English Wikipedia takes < 3 minutes on my desktop) - Mmap directory - SIMD integer compression when the platform/CPU includes the SSE2 instruction set - Single valued and multivalued u64, i64, and f64 fast fields (equivalent of doc values in Lucene) - `&[u8]` fast fields - Text, i64, u64, f64, dates, ip, bool, and hierarchical facet fields - Compressed document store (LZ4, Zstd, None) - Range queries - Faceted search - Configurable indexing (optional term frequency and position indexing) - JSON Field - Aggregation Collector: histogram, range buckets, average, and stats metrics - LogMergePolicy with deletes - Searcher Warmer API - Cheesy logo with a horse ### Non-features Distributed search is out of the scope of Tantivy, but if you are looking for this feature, check out [Quickwit](https://github.com/quickwit-oss/quickwit/). ## Getting started Tantivy works on stable Rust and supports Linux, macOS, and Windows. - [Tantivy's simple search example](https://tantivy-search.github.io/examples/basic_search.html) - [tantivy-cli and its tutorial](https://github.com/quickwit-oss/tantivy-cli) - `tantivy-cli` is an actual command-line interface that makes it easy for you to create a search engine, index documents, and search via the CLI or a small server with a REST API. It walks you through getting a Wikipedia search engine up and running in a few minutes. - [Reference doc for the last released version](https://docs.rs/tantivy/) ## How can I support this project? There are many ways to support this project. - Use Tantivy and tell us about your experience on [Discord](https://discord.gg/MT27AG5EVE) or by email (paul.masurel@gmail.com) - Report bugs - Write a blog post - Help with documentation by asking questions or submitting PRs - Contribute code (you can join [our Discord server](https://discord.gg/MT27AG5EVE)) - Talk about Tantivy around you ## Contributing code We use the GitHub Pull Request workflow: reference a GitHub ticket and/or include a comprehensive commit message when opening a PR. Feel free to update CHANGELOG.md with your contribution. ### Tokenizer When implementing a tokenizer for tantivy depend on the `tantivy-tokenizer-api` crate. ### Clone and build locally Tantivy compiles on stable Rust. To check out and run tests, you can simply run: ```bash git clone https://github.com/quickwit-oss/tantivy.git cd tantivy cargo test ``` ## Companies Using Tantivy

Etsy   ParadeDB   Nuclia   Humanfirst.ai Element.io Nuclia   Humanfirst.ai    Element.io

## FAQ ### Can I use Tantivy in other languages? - Python → [tantivy-py](https://github.com/quickwit-oss/tantivy-py) - Ruby → [tantiny](https://github.com/baygeldin/tantiny) You can also find other bindings on [GitHub](https://github.com/search?q=tantivy) but they may be less maintained. ### What are some examples of Tantivy use? - [seshat](https://github.com/matrix-org/seshat/): A matrix message database/indexer - [tantiny](https://github.com/baygeldin/tantiny): Tiny full-text search for Ruby - [lnx](https://github.com/lnx-search/lnx): adaptable, typo tolerant search engine with a REST API - [Bichon](https://github.com/rustmailer/bichon): A lightweight, high-performance Rust email archiver with WebUI - and [more](https://github.com/search?q=tantivy)! ### On average, how much faster is Tantivy compared to Lucene? - According to our [search latency benchmark](https://tantivy-search.github.io/bench/), Tantivy is approximately 2x faster than Lucene. ### Does tantivy support incremental indexing? - Yes. ### How can I edit documents? - Data in tantivy is immutable. To edit a document, the document needs to be deleted and reindexed. ### When will my documents be searchable during indexing? - Documents will be searchable after a `commit` is called on an `IndexWriter`. Existing `IndexReader`s will also need to be reloaded in order to reflect the changes. Finally, changes are only visible to newly acquired `Searcher`. ================================================ FILE: RELEASE.md ================================================ # Releasing a new Tantivy Version ## Steps 1. Identify new packages in workspace since last release 2. Identify changed packages in workspace since last release 3. Bump version in `Cargo.toml` and their dependents for all changed packages 4. Update version of root `Cargo.toml` 5. Publish version starting with leaf nodes 6. Set git tag with new version [`cargo-release`](https://github.com/crate-ci/cargo-release) will help us with steps 1-5: Replace prev-tag-name ```bash cargo release --workspace --no-publish -v --prev-tag-name 0.24 --push-remote origin minor --no-tag ``` `no-tag` or it will create tags for all the subpackages cargo release will _not_ ignore unchanged packages, but it will print warnings for them. e.g. "warning: updating ownedbytes to 0.10.0 despite no changes made since tag 0.24" We need to manually ignore these unchanged packages ```bash cargo release --workspace --no-publish -v --prev-tag-name 0.24 --push-remote origin minor --no-tag --exclude tokenizer-api ``` Add `--execute` to actually publish the packages, otherwise it will only print the commands that would be run. ### Tag Version ```bash git tag 0.25.0 git push upstream tag 0.25.0 ``` ================================================ FILE: TODO.txt ================================================ Make schema_builder API fluent. fix doc serialization and prevent compression problems u64 , etc. should return Result