Go to file
Phill Mell-Davies 164adc87e1
Tantivy 0.19.2 (#67)
* Adding __init__.py file to the tantivy folder to make maturin happy

Add Cargo.lock to the repo

Set the git-fetch-with-cli cargo flag so that we can override fetch settings

Renaming .cargo/config to .cargo/config.toml

Adding github-quiq-sh cargo registry

Point dependencies at our github-quiq-sh registry

Trying to resolve this build issue, pointing pyo3-build-config at our github-quiq-sh registry

SER-21487: Enable support for all standard Tantivy languages plus Chinese + Japanese in tantivy-py

SER-21487: Use uname rather than UNAME in the Makefile

SER-21487: Fix document date handling

SER-23013: Upgrade Tantivy and other dependencies

* Upgrade to Tantivy 0.19.1

* Apply rustfmt and fix bug when fast option = None

* Upgrade to tantivy-0.19.2

* Standardize around using 'cargo fmt' rather than 'rustfmt'

* Reverting to old style dependencies

* Linting with clippy

* Switching out hashmap for defining tokenizers for an array, and adding test for Spanish indexing

* Use cargo fmt instead of rustfmt on the Lint ci step
2023-02-14 13:20:59 +00:00
.cargo Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
.github/workflows Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
ci ci: Don't use the master branch of the maturin docker image. 2020-10-11 14:21:45 +02:00
src Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
tantivy Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
tests Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
.gitignore Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
.travis.yml Fixed links 2021-10-18 13:31:07 +00:00
Cargo.lock Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
Cargo.toml Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
LICENSE Initial python bindings implementation. 2019-06-04 11:09:58 +02:00
MANIFEST.in Initial python bindings implementation. 2019-06-04 11:09:58 +02:00
Makefile Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
README.md edit for the main readme (#60) 2022-11-28 23:24:54 +09:00
build.rs Update to pyo3 0.15 (#40) 2022-01-17 10:16:08 +09:00
noxfile.py Include Python 3.11 in nox tests and Github actions matrix (#56) 2023-01-13 16:29:38 +00:00
pyproject.toml Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00
requirements-dev.txt Switch from pipenv to nox 2022-01-17 21:26:11 +08:00
rustfmt.toml Tantivy 0.19.2 (#67) 2023-02-14 13:20:59 +00:00

README.md

Build Status License: MIT

tantivy-py

Python bindings for Tantivy the full-text search engine library written in Rust.

Installation

The bindings can be installed using from pypi using pip:

pip install tantivy

If no binary wheel is present for your operating system the bindings will be build from source, this means that Rust needs to be installed before building can succeed.

Note that the bindings are using PyO3, which only supports python3.

Development

Setting up a development environment can be done in a virtual environment using nox or using local packages using the provided Makefile.

For the nox setup install the virtual environment and build the bindings using:

python3 -m pip install nox
nox

For the Makefile based setup run:

make

Running the tests is done using:

make test

Usage

The Python bindings have a similar API to Tantivy. To create a index first a schema needs to be built. After that documents can be added to the index and a reader can be created to search the index.

Building an index and populating it

import tantivy

# Declaring our schema.
schema_builder = tantivy.SchemaBuilder()
schema_builder.add_text_field("title", stored=True)
schema_builder.add_text_field("body", stored=True)
schema_builder.add_integer_field("doc_id",stored=True)
schema = schema_builder.build()

# Creating our index (in memory)
index = tantivy.Index(schema)

To have a persistent index, use the path parameter to store the index on the disk, e.g:

index = tantivy.Index(schema, path=os.getcwd() + '/index')

By default, tantivy offers the following tokenizers which can be used in tantivy-py:

  • default default is the tokenizer that will be used if you do not assign a specific tokenizer to your text field. It will chop your text on punctuation and whitespaces, removes tokens that are longer than 40 chars, and lowercase your text.

  • raw Does not actual tokenizer your text. It keeps it entirely unprocessed. It can be useful to index uuids, or urls for instance.

  • en_stem

In addition to what default does, the en_stem tokenizer also apply stemming to your tokens. Stemming consists in trimming words to remove their inflection. This tokenizer is slower than the default one, but is recommended to improve recall.

to use the above tokenizers, simply provide them as a parameter to add_text_field. e.g.

schema_builder.add_text_field("body",  stored=True,  tokenizer_name='en_stem')

Adding one document.

writer = index.writer()
writer.add_document(tantivy.Document(
	doc_id=1,
    title=["The Old Man and the Sea"],
    body=["""He was an old man who fished alone in a skiff in the Gulf Stream and he had gone eighty-four days now without taking a fish."""],
))
# ... and committing
writer.commit()

Building and Executing Queries

First you need to get a searcher for the index

# Reload the index to ensure it points to the last commit.
index.reload()
searcher = index.searcher()

Then you need to get a valid query object by parsing your query on the index.

query = index.parse_query("fish days", ["title", "body"])
(best_score, best_doc_address) = searcher.search(query, 3).hits[0]
best_doc = searcher.doc(best_doc_address)
assert best_doc["title"] == ["The Old Man and the Sea"]
print(best_doc)

Valid Query Formats

tantivy-py supports the query language used in tantivy. Some basic query Formats.

  • AND and OR conjunctions.
query = index.parse_query('(Old AND Man) OR Stream', ["title", "body"])
(best_score, best_doc_address) = searcher.search(query, 3).hits[0]
best_doc = searcher.doc(best_doc_address)
  • +(includes) and -(excludes) operators.
query = index.parse_query('+Old +Man chef -fished', ["title", "body"])
(best_score, best_doc_address) = searcher.search(query, 3).hits[0]
best_doc = searcher.doc(best_doc_address)

Note: in a query like above, a word with no +/- acts like an OR.

  • phrase search.
query = index.parse_query('"eighty-four days"', ["title", "body"])
(best_score, best_doc_address) = searcher.search(query, 3).hits[0]
best_doc = searcher.doc(best_doc_address)
  • integer search
query = index.parse_query('"eighty-four days"', ["doc_id"])
(best_score, best_doc_address) = searcher.search(query, 3).hits[0]
best_doc = searcher.doc(best_doc_address)

Note: for integer search, the integer field should be indexed.

For more possible query formats and possible query options, see Tantivy Query Parser Docs.