A MoonBit-native embedded full-text search kernel
Dependencies
moon add Lucius646/MoonSearch@0.1.0core ──→ 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 facadeSchema tokenizer name ──→ TokenizerManager
│
raw text ──→ Tokenizer ──→ TokenStream ──→ TokenFilter[] ──→ analyzed Tokens
│
┌──────────────┴──────────────┐
▼ ▼
SegmentWriter indexing QueryParser analysis
│
existing Query hierarchyen_stem = SimpleTokenizer
-> RemoveLongFilter(40)
-> LowerCaseFilter
-> EnglishStemmerFilterapplication word list ──→ ChineseLexicon (immutable Trie)
│
▼
mixed input ──→ ChineseTokenizer ──→ RemoveLongFilter(40) ──→ LowerCaseFilter
│
┌─────────┴─────────┐
▼ ▼
longest Han match contiguous non-Han text
│
one-character fallbacklet 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"),
)weighted immutable Trie ──→ candidates at every Han position
│
▼
validated frequency DAG
│
reverse dynamic programming
│
▼
globally highest-probability routelet 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())
}application / Directory / embedded asset
│
UTF-8 String
│
▼
ChineseLexicon::from_dictionary_text
│
incremental Trie builder
│
▼
immutable ChineseLexicon///|
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)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///|
let model : &@MoonSearch.ChineseHmmModel = application_hmm_model
///|
let analyzer = @MoonSearch.chinese_dag_hmm_analyzer(lexicon, model)Token(position, position_length)
│
▼
validated DAG edges
│
▼
bounded finite-string expansion
┌─────┴─────┐
▼ ▼
Boolean path Phrase path
alternatives alternatives///|
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)BooleanQuery(
Should(BoostQuery(TermQuery(title, "moonbit"), 3.0)),
Should(BoostQuery(TermQuery(body, "moonbit"), 1.0)),
)moon run cmd/mainmoon testfn chinese_dag_hmm_analyzer(dictionary : &ChineseDictionary, model : &ChineseHmmModel) -> TextAnalyzerfn chinese_dag_hmm_search_analyzer(dictionary : &ChineseDictionary, model : &ChineseHmmModel) -> TextAnalyzerfn chinese_dag_hmm_search_index_analyzer(dictionary : &ChineseDictionary, model : &ChineseHmmModel) -> TextAnalyzerA MoonBit-native embedded full-text search kernel
Dependencies