| Title: | Fast Full-Text Search for R with 'Tantivy' |
|---|---|
| Description: | Index data frames and document collections and run fast full-text search entirely on your machine. 'tantivyr' wraps the 'Tantivy' 'Rust' search engine (a 'Lucene'-inspired library) to provide 'BM25' ranking, structured filters, snippet highlighting and incremental updates over an on-disk or in-memory index. First-class support is provided for stemming and stop words in Portuguese and English, making it well suited to public documents, news clippings, extracted 'PDF' text, transcripts and legal acts. |
| Authors: | André Leite [aut, cre] (ORCID: <https://orcid.org/0000-0002-4718-9766>), Marcos Wasiliew [aut] (ORCID: <https://orcid.org/0009-0004-4694-3159>), Hugo Vasconcelos [aut] (ORCID: <https://orcid.org/0000-0001-6249-0920>), Carlos Amorim [aut] (ORCID: <https://orcid.org/0000-0001-6315-8305>), Diogo Bezerra [aut] (ORCID: <https://orcid.org/0000-0002-1216-8674>), Júlia Nascimento Barreto [aut] (ORCID: <https://orcid.org/0009-0004-2851-7770>) |
| Maintainer: | André Leite <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.1 |
| Built: | 2026-09-29 16:14:51 UTC |
| Source: | https://github.com/strategicprojects/tantivyr |
A small collection of short news stories written in Brazilian Portuguese, meant for trying out indexing, stemming, stop words, filters and highlights. The stories are fictional and were written for this package, so they can be used freely in examples and teaching material.
pt_newspt_news
A tibble with 36 rows and 5 columns:
Integer identifier, in date order.
News section: "economia", "saúde", "educação",
"tecnologia", "meio ambiente" or "esporte" (six stories each).
Publication date (Date), from January 2024 to April 2025.
Headline.
Two-sentence body text.
Written for 'tantivyr'; see data-raw/pt_news.R in the package
sources.
idx <- tnt_index_df( pt_news, text = c(title, body), filters = c(section, date), stemmer = "portuguese", stopwords = TRUE ) tnt_search(idx, "vacinas", limit = 3)[, c("score", "section", "title")]idx <- tnt_index_df( pt_news, text = c(title, body), filters = c(section, date), stemmer = "portuguese", stopwords = TRUE ) tnt_search(idx, "vacinas", limit = 3)[, c("score", "section", "title")]
Report the version string of the 'Tantivy' 'Rust' search engine that this package was built against.
tantivy_version()tantivy_version()
A length-one character vector giving the version of the bundled
'Tantivy' 'Rust' search engine (for example "tantivy v0.26.2, index_format v7").
Adds the rows of data as documents. Only columns whose names match a schema
field are used; other columns are ignored. Additions become searchable after
tnt_commit().
tnt_add(idx, data)tnt_add(idx, data)
idx |
A |
data |
A data frame whose columns map to schema fields by name. |
The tnt_index, invisibly (so calls can be piped).
sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) df <- data.frame(id = 1:2, body = c("the quick fox", "lazy dogs sleep")) idx |> tnt_add(df) |> tnt_commit() tnt_num_docs(idx)sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) df <- data.frame(id = 1:2, body = c("the quick fox", "lazy dogs sleep")) idx |> tnt_add(df) |> tnt_commit() tnt_num_docs(idx)
Flushes buffered additions and deletions to the index and refreshes the
reader so they become visible to tnt_search().
tnt_commit(idx)tnt_commit(idx)
idx |
A |
The tnt_index, invisibly.
sch <- tnt_schema(body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(body = "hello")) |> tnt_commit()sch <- tnt_schema(body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(body = "hello")) |> tnt_commit()
Returns the total number of documents matching a query and optional filter, ignoring any result limit.
tnt_count(idx, query = "", fields = NULL, filter = NULL)tnt_count(idx, query = "", fields = NULL, filter = NULL)
idx |
A |
query |
A query string in tantivy's
query syntax.
The empty string |
fields |
< |
filter |
Either a tantivy query string, or a comparison expression such
as |
A single numeric count.
idx <- tnt_index_df( data.frame(t = c("apple pie", "apple tart", "banana bread")), text = t, stemmer = "english" ) tnt_count(idx, "apple")idx <- tnt_index_df( data.frame(t = c("apple pie", "apple tart", "banana bread")), text = t, stemmer = "english" ) tnt_count(idx, "apple")
Marks for deletion every document whose field equals the given value(s),
using a field == value expression. Deletions take effect after
tnt_commit(). For reliable deletion the field should be an exact field: a
numeric/date field, or a text field created with stemmer = "raw".
tnt_delete(idx, condition)tnt_delete(idx, condition)
idx |
A |
condition |
An expression of the form |
The tnt_index, invisibly.
sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(id = 1:3, body = c("a", "b", "c"))) |> tnt_commit() tnt_delete(idx, id == 2) |> tnt_commit() tnt_num_docs(idx)sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(id = 1:3, body = c("a", "b", "c"))) |> tnt_commit() tnt_delete(idx, id == 2) |> tnt_commit() tnt_num_docs(idx)
These constructors describe a single field in a tnt_schema(). Each returns
a lightweight tnt_field object.
tnt_text( stored = TRUE, indexed = TRUE, fast = FALSE, stemmer = "none", stopwords = FALSE, fold_accents = FALSE ) tnt_i64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_u64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_f64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_bool(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_date(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_json(stored = TRUE, indexed = TRUE)tnt_text( stored = TRUE, indexed = TRUE, fast = FALSE, stemmer = "none", stopwords = FALSE, fold_accents = FALSE ) tnt_i64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_u64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_f64(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_bool(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_date(stored = TRUE, indexed = TRUE, fast = FALSE) tnt_json(stored = TRUE, indexed = TRUE)
stored |
Logical. Keep the original value so it is returned by
|
indexed |
Logical. Index the field so it can be searched or filtered.
Defaults to |
fast |
Logical. Build a columnar "fast field" enabling fast filtering
and ordering (required by |
stemmer |
Stemming/tokenization for a text field. One of |
stopwords |
Logical. Remove stop words for the chosen language. Bundled
for Portuguese and English. Defaults to |
fold_accents |
Logical. Remove diacritics from indexed words and from
queries, so that |
A tnt_field object.
tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "portuguese", stopwords = TRUE), body = tnt_text(stemmer = "portuguese"), date = tnt_date() )tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "portuguese", stopwords = TRUE), body = tnt_text(stemmer = "portuguese"), date = tnt_date() )
Opens an existing on-disk index, or creates a new one from a tnt_schema().
With path = NULL an in-memory index is created (useful for tests and
transient work).
tnt_index(path = NULL, schema = NULL, overwrite = FALSE, heap_mb = 128)tnt_index(path = NULL, schema = NULL, overwrite = FALSE, heap_mb = 128)
path |
Directory for an on-disk index, or |
schema |
A |
overwrite |
Logical. If |
heap_mb |
Indexing memory budget in MB (minimum 15). Defaults to 128. |
A tnt_index object.
tnt_index_df(), tnt_add(), tnt_search()
sch <- tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "english"), body = tnt_text(stemmer = "english") ) idx <- tnt_index(schema = sch) # in-memory idxsch <- tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "english"), body = tnt_text(stemmer = "english") ) idx <- tnt_index(schema = sch) # in-memory idx
A convenience wrapper that infers a schema from data, creates an index,
adds every row and commits. Text columns are made searchable; filter columns
are indexed for filtering and ordering; all other columns are stored so they
are returned by tnt_search().
tnt_index_df( data, text, filters = NULL, stemmer = "none", stopwords = FALSE, stored = TRUE, path = NULL, overwrite = FALSE, heap_mb = 128, fold_accents = FALSE )tnt_index_df( data, text, filters = NULL, stemmer = "none", stopwords = FALSE, stored = TRUE, path = NULL, overwrite = FALSE, heap_mb = 128, fold_accents = FALSE )
data |
A data frame. |
text |
< |
filters |
< |
stemmer, stopwords, fold_accents
|
Stemming, stop-word and accent-folding
options applied to all |
stored |
Logical. Store text columns so they are returned by searches. |
path, overwrite, heap_mb
|
Passed to |
A committed tnt_index object.
df <- data.frame( id = 1:2, title = c("Orçamento público aprovado", "Reforma tributária avança"), year = c(2023L, 2024L) ) idx <- tnt_index_df(df, text = title, filters = year, stemmer = "portuguese") tnt_search(idx, "orcamento")df <- data.frame( id = 1:2, title = c("Orçamento público aprovado", "Reforma tributária avança"), year = c(2023L, 2024L) ) idx <- tnt_index_df(df, text = title, filters = year, stemmer = "portuguese") tnt_search(idx, "orcamento")
Index schema as a tibble
tnt_index_info(idx)tnt_index_info(idx)
idx |
A |
A tibble with one row per field: name, kind, stored,
indexed, tokenizer.
idx <- tnt_index_df(data.frame(t = "hi"), text = t) tnt_index_info(idx)idx <- tnt_index_df(data.frame(t = "hi"), text = t) tnt_index_info(idx)
Number of searchable documents
tnt_num_docs(idx)tnt_num_docs(idx)
idx |
A |
A single numeric value (committed document count).
idx <- tnt_index_df(data.frame(t = "hello world"), text = t) tnt_num_docs(idx)idx <- tnt_index_df(data.frame(t = "hello world"), text = t) tnt_num_docs(idx)
Combine named tnt_field definitions into a schema that can be passed to
tnt_index().
tnt_schema(...)tnt_schema(...)
... |
Named field definitions, e.g. |
A tnt_schema object (a named list of tnt_fields).
tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "english"), body = tnt_text(stemmer = "english") )tnt_schema( id = tnt_i64(), title = tnt_text(stemmer = "english"), body = tnt_text(stemmer = "english") )
Runs a BM25 full-text search and returns the top matches as a tibble. Supports structured filters, result ordering and snippet highlighting.
tnt_search( idx, query = "", limit = 10L, fields = NULL, filter = NULL, highlight = NULL, snippet_chars = 150L, order_by = NULL, desc = TRUE )tnt_search( idx, query = "", limit = 10L, fields = NULL, filter = NULL, highlight = NULL, snippet_chars = 150L, order_by = NULL, desc = TRUE )
idx |
A |
query |
A query string in tantivy's
query syntax.
The empty string |
limit |
Maximum number of results. Defaults to 10. |
fields |
< |
filter |
Either a tantivy query string, or a comparison expression such
as |
highlight |
< |
snippet_chars |
Maximum snippet length in characters. Defaults to 150. |
order_by |
< |
desc |
Logical. Order descending (the default) when |
A tibble with a score column, every stored field, and any requested
*_snippet columns.
df <- data.frame( id = 1:3, title = c("Quick brown fox", "Lazy dog", "Brown bear"), year = c(2019L, 2021L, 2023L) ) idx <- tnt_index_df(df, text = title, filters = year, stemmer = "english") tnt_search(idx, "brown") tnt_search(idx, "brown", filter = year >= 2021) tnt_search(idx, "fox", highlight = title)df <- data.frame( id = 1:3, title = c("Quick brown fox", "Lazy dog", "Brown bear"), year = c(2019L, 2021L, 2023L) ) idx <- tnt_index_df(df, text = title, filters = year, stemmer = "english") tnt_search(idx, "brown") tnt_search(idx, "brown", filter = year >= 2021) tnt_search(idx, "fox", highlight = title)
List supported stemmer languages
tnt_stemmers()tnt_stemmers()
A character vector of language names accepted by the stemmer
argument of tnt_text().
tnt_stemmers()tnt_stemmers()
Replaces documents by deleting any existing document that shares a key value
(the by field) with a row of data, then adding the rows of data. The
by field must be an exact field (numeric/date, or text with
stemmer = "raw"). Call tnt_commit() afterwards.
tnt_update(idx, data, by)tnt_update(idx, data, by)
idx |
A |
data |
A data frame of replacement documents. |
by |
< |
The tnt_index, invisibly.
sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(id = 1:2, body = c("old one", "old two"))) |> tnt_commit() tnt_update(idx, data.frame(id = 1L, body = "new one"), by = id) |> tnt_commit()sch <- tnt_schema(id = tnt_i64(), body = tnt_text(stemmer = "english")) idx <- tnt_index(schema = sch) tnt_add(idx, data.frame(id = 1:2, body = c("old one", "old two"))) |> tnt_commit() tnt_update(idx, data.frame(id = 1L, body = "new one"), by = id) |> tnt_commit()