MoonSearch

A MoonBit-native embedded full-text search kernel

search
full-text-search
inverted-index
moon add Lucius646/MoonSearch@0.1.0
Download zip
Author
Version
0.1.0
License
Apache-2.0
Last updated
18 days ago
Downloads
3

Dependencies

README

#MoonSearch

MoonSearch is a MoonBit-native embedded full-text search kernel inspired by the component boundaries of Tantivy and the inverted-index semantics of Lucene.

#Installation

moon add Lucius646/MoonSearch@0.1.0

#Package architecture

MoonSearch is organized as an acyclic set of responsibility-focused MoonBit packages:

core ──→ schema ──→ analysis ──→ index ──→ query ──→ store │ │ │ │ │ │ │ │ │ │ │ └─ Directory, │ │ │ │ │ IndexReader/Writer │ │ │ │ └─ Query, Weight, Scorer, │ │ │ │ Searcher, Collector │ │ │ └─ Segment, postings, codec, Merge │ │ └─ Tokenizer, TokenStream, filters, registry │ └─ field definitions and SchemaBuilder └─ identifiers, documents, terms, shared errors internal/codec ──→ shared binary container primitives used by index and store analysis/chinese ──→ optional dictionary-backed Chinese analysis over analysis tests/integration ──→ public cross-package behavior through the root facade

The arrows describe allowed dependency direction, not a requirement that every package depends directly on its immediate neighbor. The root Lucius646/MoonSearch package is a compatibility facade that re-exports the public API, so existing @MoonSearch.* applications do not need to adopt the internal package names. Advanced users may import focused packages directly. Public integration tests live in their own tests/integration package and use only the root facade. White-box codec and manifest tests remain beside index and store, where MoonBit permits them to inspect package-private invariants.

#M5b-1

M5b-1 aligns M5a's field-aware analysis framework with Tantivy's streaming composition model without treating N-grams as Chinese word segmentation:

Schema tokenizer name ──→ TokenizerManager │ raw text ──→ Tokenizer ──→ TokenStream ──→ TokenFilter[] ──→ analyzed Tokens │ ┌──────────────┴──────────────┐ ▼ ▼ SegmentWriter indexing QueryParser analysis │ existing Query hierarchy

The current milestone includes:

  • documents containing text fields;
  • open Tokenizer, stateful TokenStream, and lazy TokenFilter boundaries;
  • third-party Tokenizers that can return their own eager or lazy TokenStream implementations;
  • composable TextAnalyzer pipelines that implement Tokenizer themselves;
  • name-based TokenizerManager registration and replacement;
  • built-in raw, Unicode-whitespace, punctuation-aware default, lowercase, and maximum-token-length components;
  • configurable character NgramTokenizer with all-gram and prefix-only modes;
  • Tantivy-compatible N-gram positions: every gram from one field value has position zero while UTF-8 byte offsets preserve its source span;
  • token positions, position lengths, and UTF-8 byte offsets;
  • schema-bound tokenizer names with legacy TextOptions::new retaining whitespace behavior;
  • schema-aware indexing that resolves each field through TokenizerManager and consumes the resulting TokenStream directly;
  • field-aware query-time analysis for Term, Boolean, and Phrase semantics;
  • disjunction-by-default and optional conjunction query construction;
  • phrase position-gap preservation after filtering;
  • Segment format v2 persistence of tokenizer names and compatibility with complete M3/M4 Segment v1 files;
  • field-qualified terms;
  • posting lists containing document ID, term frequency, and positions;
  • completed, read-only immutable segments;
  • immutable snapshots of stored text fields;
  • per-document field lengths and per-field collection statistics;
  • stable field allocation through SchemaBuilder;
  • independent indexed and stored text options;
  • exact field-qualified term queries;
  • BM25 ranking with k1=1.2 and b=0.75;
  • Boolean Must, Should, and MustNot clauses;
  • exact zero-slop phrase queries using positions;
  • score multiplication through BoostQuery;
  • multi-field weighting by composing Boolean and Boost queries;
  • position gaps between repeated values of the same field;
  • deterministic Top-K results;
  • DocAddress values ready for later multi-segment search;
  • stored-document lookup from a stable single-segment Searcher.
  • a byte-oriented open Directory boundary;
  • copy-isolated MemoryDirectory storage;
  • filesystem-backed FsDirectory storage;
  • incremental IndexWriter commits using numbered Segment files;
  • a deterministic, versioned and checksummed manifest;
  • stable IndexReader generations and Searcher snapshots;
  • snapshot-wide document frequency, field document count, and average field length;
  • one query Weight producing comparable Scorers for every Segment;
  • global Top-K selection with stable Segment ordinal and DocId tie-breaking;
  • IndexReader segment-count and generation inspection;
  • exact field-qualified IndexWriter.delete_term(Term) operations;
  • explicit commit_deletes() publication through a new manifest generation;
  • tombstones stored per Segment in deterministic manifest v2 data;
  • backward-compatible loading of M4a manifest v1;
  • live-document filtering for query hits and stored-document lookup;
  • live-only document frequency, field document count, average field length, and BM25 scoring;
  • replacement semantics: pending deletes affect existing Segments while a Segment appended by the same commit remains live;
  • native Segment Merge that copies postings, term frequencies, positions, stored documents, and field lengths without re-analysis;
  • consecutive DocId remapping across merged live documents;
  • preservation of indexed-only fields during Merge;
  • stable old Reader snapshots across both deletion commits and Merge;
  • a deterministic, versioned single-file Segment format;
  • persistence of Schema, terms, postings, term frequencies, positions, stored documents, field lengths, field statistics, and document count;
  • explicit rejection of unknown versions, truncation, checksum failures, and structurally inconsistent payloads.

M5b-2 adds the first language-specific built-in analyzer:

en_stem = SimpleTokenizer -> RemoveLongFilter(40) -> LowerCaseFilter -> EnglishStemmerFilter

The Porter2 stemmer follows the behavior expected by Tantivy's en_stem pipeline, leaves non-ASCII or mixed-script tokens unchanged, and preserves each token's original position, position length, and UTF-8 byte offsets. The StopWordFilter is a separate lazy, exact-match component: applications can place it after lowercasing when they want stop-word removal, while the built-in en_stem preset intentionally does not enable a stop-word list. Both indexing and QueryParser resolve en_stem through the same TokenizerManager, so inflected forms are normalized consistently without changing the Segment or Query abstractions.

M5b-3 hardens that implementation with a compact, permanently retained compatibility suite. Its curated word groups exercise the Porter2 prelude, steps 1 through 5, exceptional forms, the 40-byte token boundary, position and offset preservation, and immutable stop-word configuration. Expected stems were checked against the exact rust-stemmers 1.2.0 version used by Tantivy 0.26.1. This is deterministic conformance and regression testing, not a performance benchmark; it adds no Rust dependency or large corpus to the MoonSearch repository.

#M5b-4a

M5b-4a adds an optional Chinese analysis package without making N-grams pretend to be linguistic segmentation or embedding a large dictionary in the core:

application word list ──→ ChineseLexicon (immutable Trie) │ ▼ mixed input ──→ ChineseTokenizer ──→ RemoveLongFilter(40) ──→ LowerCaseFilter │ ┌─────────┴─────────┐ ▼ ▼ longest Han match contiguous non-Han text │ one-character fallback

ChineseDictionary is an open injection boundary. ChineseLexicon is the built-in immutable implementation: it snapshots Han-only words into a Trie and returns every candidate beginning at each input position. The M5b-4a tokenizer selects the longest candidate; keeping that policy outside the dictionary preserves the candidate set and frequency field needed by M5b-4b DAG routing. Unknown Han characters are emitted individually and deterministically. Consecutive non-Han, non-punctuation text remains one token, so the surrounding analyzer can lowercase identifiers such as MoonBit2026. Positions are sequential and offsets remain UTF-8 byte offsets, including for supplementary Han characters.

Chinese analysis is not registered by TokenizerManager::with_defaults() because a dictionary is an application resource. Applications explicitly bind one analyzer name and use that name in Schema:

let lexicon = @MoonSearch.ChineseLexicon::new([
"中文", "搜索引擎",
]) catch {
error => abort(error.to_string())
}
let manager = @MoonSearch.TokenizerManager::with_defaults()
manager.register("zh_dict", @MoonSearch.chinese_analyzer(lexicon)) catch {
error => abort(error.to_string())
}
let builder = @MoonSearch.SchemaBuilder::new()
let body = builder.add_text_field(
"body",
@MoonSearch.TextOptions::new(true, true).with_tokenizer("zh_dict"),
)

M5b-4a deliberately leaves frequency routing, HMM recognition, dictionary resources, and search expansion to later milestones.

#M5b-4b

M5b-4b adds strict weighted lexicons and an explicit dictionary-only frequency DAG analyzer:

weighted immutable Trie ──→ candidates at every Han position │ ▼ validated frequency DAG │ reverse dynamic programming │ ▼ globally highest-probability route

For an edge ending at next, the route score is ln(word_frequency) - ln(total_frequency) + score[next]. A one-character edge with frequency 1 is inserted when the dictionary has no valid candidate. Malformed third-party candidates are ignored, duplicate lengths retain their highest frequency, and exact score ties prefer the longer current edge. These rules make output independent of dictionary iteration order.

The M5b-4a APIs remain stable. ChineseTokenizer::new and chinese_analyzer still use greedy longest matching. ChineseTokenizer::with_frequency_dag and chinese_dag_analyzer opt into M5b-4b. ChineseDictionary::total_frequency has a default value for existing unweighted providers; weighted providers override it. ChineseLexicon::new continues to snapshot and deduplicate unweighted words, while ChineseLexicon::from_entries rejects empty or non-Han words, non-positive frequencies, duplicate words, and total-frequency overflow.

let lexicon = @MoonSearch.ChineseLexicon::from_entries([
@MoonSearch.ChineseLexiconEntry::new("研究", 1000),
@MoonSearch.ChineseLexiconEntry::new("研究生", 1),
@MoonSearch.ChineseLexiconEntry::new("生命", 1000),
]) catch {
error => abort(error.to_string())
}
let manager = @MoonSearch.TokenizerManager::with_defaults()
manager.register("zh_dag", @MoonSearch.chinese_dag_analyzer(lexicon)) catch {
error => abort(error.to_string())
}

Query syntax parsing, phrase slop, concurrent writers, automatic merge policy, obsolete Segment file reclamation, field types beyond text, HMM unknown-word recognition, a bundled Chinese dictionary and loader/cache pipeline, dynamic dictionary mutation, and Chinese search-mode Token Graph expansion are intentionally outside M5b-4b.

#M5b-4c-1

M5b-4c-1 adds a portable dictionary text resource boundary without coupling the analysis package to native file APIs:

application / Directory / embedded asset │ UTF-8 String │ ▼ ChineseLexicon::from_dictionary_text │ incremental Trie builder │ ▼ immutable ChineseLexicon

The accepted format is word frequency [tag], with one entry per line. The parser accepts an initial UTF-8 BOM, LF or CRLF input, blank lines, full-line # comments, Unicode whitespace separators, and an optional tag that is currently ignored. It reports one-based line numbers for invalid field counts, non-decimal or overflowing frequencies, non-Han words, duplicates, and aggregate-frequency overflow.

///|
let dictionary_text = "研究 1000 v\n研究生 1 n\n生命 1000 n\n命 1 n\n起源 1000 n\n"

///|
let lexicon = @MoonSearch.ChineseLexicon::from_dictionary_text(dictionary_text) catch {
error => abort(error.to_string())
}

///|
let analyzer = @MoonSearch.chinese_dag_analyzer(lexicon)

The parser feeds entries directly into a package-internal Trie builder instead of retaining a parsed entry array plus a duplicate set. The caller remains responsible for obtaining and decoding the String, which keeps identical behavior across native, JavaScript, WASM, custom Directory implementations, and embedded resources.

HMM unknown-word recognition, a bundled dictionary, native path loading, resource caching, dynamic dictionary mutation, and Chinese search-mode Token Graph expansion are intentionally outside M5b-4c-1.

#M5b-4c-2

M5b-4c-2 adds optional HMM recognition without changing the longest-match or dictionary-only DAG APIs:

weighted dictionary DAG │ ▼ consecutive one-character route buffer │ ├─ buffer is an exact dictionary word ─→ preserve DAG singletons │ └─ otherwise │ ▼ constrained B/M/E/S Viterbi │ ▼ recognized unknown-word tokens

ChineseHmmModel is an open log-score provider for start, transition, and emission values. TableChineseHmmModel is the built-in immutable facade: it snapshots two legal start scores, all eight legal transitions, sparse character emissions, and one unknown-emission fallback. Duplicate, missing, or illegal state-table entries are rejected during construction.

Viterbi enforces B/S starts, E/S final states, and only these transitions: B→M/E, M→M/E, E→B/S, and S→B/S. Reachability is tracked separately from numeric scores, so even an application-supplied score below the internal impossible-score sentinel cannot make an illegal path win. Final score ties prefer S, conservatively avoiding invented multi-character words.

///|
let model : &@MoonSearch.ChineseHmmModel = application_hmm_model

///|
let analyzer = @MoonSearch.chinese_dag_hmm_analyzer(lexicon, model)

The HMM model is injected like the dictionary and the resulting analyzer is registered under an application-chosen tokenizer name. Indexing and querying must register the same dictionary and model snapshots under that name.

A bundled HMM probability model, HMM resource-file parsing and caching, dynamic model mutation, and Chinese search-mode Token Graph expansion are intentionally outside M5b-4c-2. Search-mode graph expansion is the next M5c boundary.

#M5c-1

M5c-1 establishes the language-neutral Token Graph boundary before Chinese search-mode expansion:

Token(position, position_length) │ ▼ validated DAG edges │ ▼ bounded finite-string expansion ┌─────┴─────┐ ▼ ▼ Boolean path Phrase path alternatives alternatives

TokenGraph snapshots a non-decreasing analyzed token stream and treats every token as an edge from position to position + position_length. Invalid positions, zero-length edges, invalid offsets, and integer overflow are rejected. Finite-string expansion is capped at 256 paths by default so an application tokenizer cannot accidentally create an exponentially expensive query.

Graph edges are normalized when converted to a finite string. For example, a two-position dns edge beside the path domain → name, followed by server, becomes the alternatives dns server and domain name server. Real gaps left by filters remain positional gaps.

Phrase parsing now creates one exact PhraseQuery per finite graph path and combines alternatives as a Boolean disjunction. Conjunctive term parsing also requires one complete graph path instead of requiring every overlapping alternative. Segment postings continue to store term positions rather than position_length, matching Lucene and Tantivy's postings model; repeated positions survive persistence, while position_length is consumed during query graph construction and when advancing across repeated field values.

Chinese dictionary-backed two-gram and three-gram search-mode expansion remains outside M5c-1 and is the M5c-2 boundary.

#M5c-2

M5c-2 implements Chinese search mode as a separate analysis filter. Precise segmentation remains responsible for the primary path; ChineseSearchModeFilter then expands each Han word using the same injected dictionary:

  • words longer than two characters may emit dictionary-backed two-character subwords;
  • words longer than three characters may also emit dictionary-backed three-character subwords;
  • the original word is always retained;
  • arbitrary N-grams and subwords absent from the dictionary are not emitted.

Positions use character graph nodes and offsets remain UTF-8 byte offsets. For 中国科学院, a suitable dictionary produces the original edge plus 中国, 科学, 科学院, and 学院. Complete finite paths include 中国科学院 and 中国 → 科学院; the incomplete 中国 → 科学 branch is discarded.

Three analyzer constructors keep segmentation policy explicit:

///|
let longest = @MoonSearch.chinese_search_analyzer(dictionary)

///|
let dag = @MoonSearch.chinese_dag_search_analyzer(dictionary)

///|
let dag_hmm = @MoonSearch.chinese_dag_hmm_search_analyzer(dictionary, model)

Search mode is primarily an indexing recall pipeline. Applications may give a schema tokenizer name different manager snapshots: register the search analyzer for SegmentWriter, and register the corresponding precise DAG or DAG/HMM analyzer under the same name for QueryParser. Both sides should use the same dictionary and HMM snapshots. This mirrors the mature index-analyzer versus search-analyzer split without storing analysis implementations in the segment.

A bundled dictionary/model, dynamic lexicon mutation, generic synonym graphs, lossless persistence of position_length, index-time graph flattening, and exact phrase semantics across expanded multiword graphs remain outside M5c-2. The latter two form the next M5c-3 position-policy boundary; M5c-2 guarantees analyzer correctness and term-query recall.

#M5c-3

M5c-3 closes M5 with an explicit index-time position policy. Search-mode expansion now has two intentionally different forms:

  • ChineseSearchModeFilter::new preserves the character-offset Token Graph for analyzer inspection and graph-aware query construction;
  • ChineseSearchModeFilter::for_index stacks the original word and all of its dictionary subwords at one ordinal position, with position_length == 1.

The index-flat form is deliberately lossy because Segment postings store term positions rather than graph edge lengths. It nevertheless preserves the properties required by the current engine:

  • adjacent primary words remain adjacent;
  • every emitted dictionary subword remains term-searchable;
  • ordered subword phrases spanning different primary words remain exact;
  • the Segment v2 format remains unchanged.

For a search-mode field, register an index analyzer such as chinese_dag_search_index_analyzer for SegmentWriter, and register the corresponding precise analyzer such as chinese_dag_analyzer under the same schema tokenizer name for QueryParser. Longest-match and DAG/HMM pairs are available through the matching *_search_index_analyzer constructors.

Two subwords derived from the same primary word are intentionally stacked, not treated as a phrase sequence. Supporting that interpretation would require lossless graph metadata in postings or a more general query-time rewrite and is outside M5.

The component boundaries follow Tantivy and Lucene semantics without copying their implementation details. TokenStream is an open stateful interface; TokenFilter wraps an input stream and transforms tokens as they are consumed. Built-in Tokenizers may use internal array-backed streams, while applications can provide genuinely lazy streams. MoonBit does not model Tantivy's Rust associated stream type directly, so Tokenizer.token_stream returns a &TokenStream trait object. TextAnalyzer is a composed Tokenizer rather than a separate eager Analyzer abstraction, and TokenizerManager stores all registered pipelines uniformly as Tokenizers. Schema stores a registry name rather than a concrete implementation. Indexing and QueryParser resolve the same name, while Segment files persist the name rather than executable Tokenizer code or resources. An application reopening an index must therefore register a compatible implementation under that name. Writers and QueryParsers capture registry snapshots when they are created.

Multi-field weighting is expressed by composition:

BooleanQuery( Should(BoostQuery(TermQuery(title, "moonbit"), 3.0)), Should(BoostQuery(TermQuery(body, "moonbit"), 1.0)), )

#Run the example

Make sure the MoonBit toolchain is on PATH, then run:

moon run cmd/main

The example registers the built-ins, binds title and body fields to en_stem, and indexes through the schema-aware writer. It still demonstrates M4b deletion and Merge snapshots, then uses QueryParser to normalize uppercase and inflected user input into the same terms used at index time.

#Test

moon test

The tests cover all M0-M4b invariants plus built-in/custom Tokenizers, custom TokenStream and TokenFilter implementations, lazy filter composition, Unicode N-gram offsets and Tantivy-compatible positions, Porter2 English stemming, rust-stemmers 1.2.0 regression cases, stop-word position gaps and configuration snapshots, the en_stem length boundary and index/query contract, registry lookup, Chinese Trie snapshots and longest matching, mixed-script segmentation, supplementary Han offsets, third-party Chinese dictionaries, Chinese frequency-DAG ambiguity resolution, malformed-candidate sanitization, weighted lexicon validation, dictionary BOM/CRLF/tag parsing, line-diagnosed resource errors, strict HMM table validation, constrained Viterbi unknown-word recognition, HMM index/query consistency, Chinese index/query consistency, schema binding, query-time Boolean and Phrase analysis, repeated-position Segment round trips, Segment v2 tokenizer persistence, and complete Segment v1 compatibility. Cross-package behavior is exercised by the independent tests/integration package; implementation-level white-box tests remain in their owning packages.

#License

Apache-2.0

#
AnalysisError

Stable root-package facade for text analysis.

#
Bm25Scorer

Stable root-package facade for query construction, scoring, and search.

#
BooleanClause

Stable root-package facade for query construction, scoring, and search.

#
BooleanQuery

Stable root-package facade for query construction, scoring, and search.

#
BoostQuery

Stable root-package facade for query construction, scoring, and search.

#
ChineseDictionary

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseDictionaryResourceError

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseHmmModel

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseHmmModelError

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseHmmState

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseLexicon

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseLexiconEntry

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseLexiconError

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseSearchModeFilter

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseTokenizer

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
ChineseWordMatch

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
Directory

Stable root-package facade for directory-backed index lifecycle APIs.

#
DocAddress

Stable root-package facade for MoonSearch's foundational value types.

#
DocId

Stable root-package facade for MoonSearch's foundational value types.

#
Document

Stable root-package facade for MoonSearch's foundational value types.

#
EnglishStemmerFilter

Stable root-package facade for text analysis.

#
FieldId

Stable root-package facade for MoonSearch's foundational value types.

#
FsDirectory

Stable root-package facade for directory-backed index lifecycle APIs.

#
IndexReader

Stable root-package facade for directory-backed index lifecycle APIs.

#
IndexWriter

Stable root-package facade for directory-backed index lifecycle APIs.

#
LowerCaseFilter

Stable root-package facade for text analysis.

#
MemoryDirectory

Stable root-package facade for directory-backed index lifecycle APIs.

#
NgramTokenizer

Stable root-package facade for text analysis.

#
Occur

Stable root-package facade for query construction, scoring, and search.

#
PersistenceError

Stable root-package facade for MoonSearch's foundational value types.

#
PhraseQuery

Stable root-package facade for query construction, scoring, and search.

#
Posting

Stable root-package facade for immutable Segment construction and access.

#
Query

Stable root-package facade for query construction, scoring, and search.

#
QueryParser

Stable root-package facade for query construction, scoring, and search.

#
RawTokenizer

Stable root-package facade for text analysis.

#
RemoveLongFilter

Stable root-package facade for text analysis.

#
Schema

Stable root-package facade for schema construction and field options.

#
SchemaBuilder

Stable root-package facade for schema construction and field options.

#
Scorer

Stable root-package facade for query construction, scoring, and search.

#
SearchHit

Stable root-package facade for query construction, scoring, and search.

#
SearchStatistics

Stable root-package facade for query construction, scoring, and search.

#
Searcher

Stable root-package facade for query construction, scoring, and search.

#
Segment

Stable root-package facade for immutable Segment construction and access.

#
SegmentWriter

Stable root-package facade for immutable Segment construction and access.

#
SimpleTokenizer

Stable root-package facade for text analysis.

#
StopWordFilter

Stable root-package facade for text analysis.

#
StoredDocument

Stable root-package facade for MoonSearch's foundational value types.

#
TableChineseHmmModel

Stable root-package facade for optional dictionary-backed Chinese analysis.

#
Term

Stable root-package facade for MoonSearch's foundational value types.

#
TermQuery

Stable root-package facade for query construction, scoring, and search.

#
TextAnalyzer

Stable root-package facade for text analysis.

#
TextOptions

Stable root-package facade for schema construction and field options.

#
Token

Stable root-package facade for text analysis.

#
TokenFilter

Stable root-package facade for text analysis.

#
TokenGraph

Stable root-package facade for text analysis.

#
TokenGraphPath

Stable root-package facade for text analysis.

#
TokenStream

Stable root-package facade for text analysis.

#
Tokenizer

Stable root-package facade for text analysis.

#
TokenizerManager

Stable root-package facade for text analysis.

#
TopKCollector

Stable root-package facade for query construction, scoring, and search.

#
Weight

Stable root-package facade for query construction, scoring, and search.

#
WhitespaceAnalyzer

Stable root-package facade for text analysis.

#
WhitespaceTokenizer

Stable root-package facade for text analysis.

#
chinese_analyzer

Creates a lowercase Chinese analyzer around an injected dictionary.

#
chinese_dag_analyzer

Creates a lowercase Chinese analyzer using frequency-DAG routing.

#
chinese_dag_hmm_analyzer

Creates a lowercase Chinese DAG analyzer with injected HMM recognition.

#
chinese_dag_hmm_search_analyzer

Creates a Chinese DAG/HMM analyzer with search-mode subwords.

#
chinese_dag_hmm_search_index_analyzer

Creates a Chinese DAG/HMM search expansion for indexing.

#
chinese_dag_search_analyzer

Creates a Chinese DAG analyzer with search-mode subwords.

#
chinese_dag_search_index_analyzer

Creates a Chinese DAG search expansion for indexing.

#
chinese_search_analyzer

Creates a longest-match Chinese analyzer with search-mode subwords.

#
chinese_search_index_analyzer

Creates a longest-match Chinese search expansion for indexing.

#
english_stem_analyzer

Creates the English stemming pipeline exposed as the en_stem preset.

Source Files