Metadata-Version: 2.4
Name: larzsearch
Version: 0.1.0
Summary: Full-text search with BM25 relevance ranking and fuzzy matching, in pure Python. No Elasticsearch, zero dependencies.
Author: larz-scripter
License: MIT
Project-URL: Homepage, https://github.com/larz-scripter/larzsearch
Project-URL: Repository, https://github.com/larz-scripter/larzsearch
Project-URL: Issues, https://github.com/larz-scripter/larzsearch/issues
Keywords: search,full-text-search,bm25,inverted-index,ranking,fuzzy,relevance,information-retrieval,elasticsearch-alternative,zero-dependency
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# larzsearch

**Full-text search with real relevance (BM25). Pure Python, zero dependencies.**

Index documents, then search them ranked by **BM25** — the relevance model behind
Lucene and Elasticsearch — not just "contains the word". Rarer query terms count
for more, term frequency has diminishing returns, and long documents don't win by
length. Optional fuzzy matching tolerates typos.

```python
from larzsearch import SearchIndex

idx = SearchIndex()
idx.add("a", "the quick brown fox jumps")
idx.add("b", "the lazy brown dog sleeps")

idx.search("brown fox")            # [{'id': 'a', 'score': .., 'doc': ..}, ...]
idx.search("quik fox", fuzzy=True) # matches despite the typo
```

## Why

- **Actual ranking, not filtering.** BM25 with IDF weighting and length
  normalization gives you results ordered by relevance — the thing naive
  substring search can't do.
- **Typo-tolerant.** `fuzzy=True` matches query terms within one edit, so "pythou"
  finds "python".
- **Documents your way.** Index plain strings or dicts (all values are indexed);
  the original doc comes back with each result.
- **Zero dependencies.** No Elasticsearch, no Whoosh, no C extensions — great for
  in-app search, docs sites, CLIs, and pairing with
  [larzdb](https://github.com/larz-scripter/larzdb).

## Install

```bash
pip install larzsearch
```

## Usage

```python
idx = SearchIndex(k1=1.5, b=0.75)         # tune BM25 if you like
idx.add("doc1", "text ...")
idx.add("doc2", {"title": "...", "body": "..."})
idx.add_many([{"id": 1, "text": "..."}, ...])
idx.remove("doc1"); idx.get("doc2"); len(idx)

results = idx.search("query terms", limit=10, fuzzy=False)
# [{"id": ..., "score": float, "doc": original}, ...]  (best first)
```

## Tests

```bash
python -m unittest discover -s tests -v   # 15 tests incl. ranking + fuzzy
```

## The Larz stack

One of 30+ pure-Python, zero-dependency libraries at
[github.com/larz-scripter](https://github.com/larz-scripter).

## License

MIT © larz-scripter
