tantivyr indexes text and searches it with BM25 ranking,
structured filters, highlighting and incremental updates — locally, with
no server. This vignette walks through the two ways of using it: the
one-call convenience wrapper and the explicit schema API.
tnt_index_df()Most of the time you have a data frame and want to search some of its
columns. tnt_index_df() infers a schema, indexes every row
and commits in one call.
news <- data.frame(
id = 1:5,
title = c(
"Orçamento público aprovado pelo congresso",
"Reforma tributária avança no senado",
"Nova lei de licitações entra em vigor",
"Congresso debate orçamentos municipais",
"Tribunal de contas analisa despesas"
),
source = c("A", "B", "A", "C", "B"),
year = c(2022L, 2023L, 2024L, 2024L, 2023L)
)
idx <- tnt_index_df(
news,
text = title, # full-text column(s)
filters = c(source, year), # columns to filter / order on
stemmer = "portuguese",
stopwords = TRUE
)
idx
#>
#> ── <tnt_index> (in-memory)
#> 5 documents · 4 fields
#> • id: i64
#> • title: text [tnt_pt_stop]
#> • source: text [raw]
#> • year: i64tnt_search() returns a tibble with a score
column followed by every stored field. Because we used the Portuguese
stemmer, a search for orçamento also matches
orçamentos.
Filters can be written as ordinary R comparisons. They are combined with the text query.
tnt_search(idx, "", filter = year >= 2024)
#> # A tibble: 2 × 5
#> score id title source year
#> <dbl> <dbl> <chr> <chr> <dbl>
#> 1 1 3 Nova lei de licitações entra em vigor A 2024
#> 2 1 4 Congresso debate orçamentos municipais C 2024
tnt_search(idx, "congresso", filter = source == "A")
#> # A tibble: 1 × 5
#> score id title source year
#> <dbl> <dbl> <chr> <chr> <dbl>
#> 1 1.77 1 Orçamento público aprovado pelo congresso A 2022
tnt_search(idx, "", filter = year %in% c(2022, 2024), limit = 10)
#> # A tibble: 3 × 5
#> score id title source year
#> <dbl> <dbl> <chr> <chr> <dbl>
#> 1 1.39 1 Orçamento público aprovado pelo congresso A 2022
#> 2 0.875 3 Nova lei de licitações entra em vigor A 2024
#> 3 0.875 4 Congresso debate orçamentos municipais C 2024You can also pass a raw Tantivy query string for anything the helpers do not cover:
tnt_search(idx, "congresso", highlight = title)$title_snippet
#> [1] "Orçamento público aprovado pelo <b>congresso</b>"
#> [2] "<b>Congresso</b> debate orçamentos municipais"
tnt_search(idx, "", order_by = year, desc = TRUE)[, c("title", "year")]
#> # A tibble: 5 × 2
#> title year
#> <chr> <dbl>
#> 1 Nova lei de licitações entra em vigor 2024
#> 2 Congresso debate orçamentos municipais 2024
#> 3 Tribunal de contas analisa despesas 2023
#> 4 Reforma tributária avança no senado 2023
#> 5 Orçamento público aprovado pelo congresso 2022For full control over how each field is stored, indexed and analysed,
build a schema with tnt_schema() and the
tnt_*() field constructors, then manage the index
yourself.
sch <- tnt_schema(
id = tnt_i64(),
slug = tnt_text(stemmer = "raw"), # exact key for updates
title = tnt_text(stemmer = "portuguese", stored = TRUE),
body = tnt_text(stemmer = "portuguese"),
date = tnt_date(fast = TRUE)
)
path <- tempfile()
idx <- tnt_index(path, schema = sch)Add documents and commit to make them searchable. Operations return the index invisibly, so they pipe.
docs <- data.frame(
id = 1:2,
slug = c("edital-001", "edital-002"),
title = c("Edital de licitação 001", "Edital de licitação 002"),
body = c("Aquisição de equipamentos de informática.",
"Contratação de serviços de limpeza."),
date = as.Date(c("2024-02-01", "2024-03-15"))
)
idx |> tnt_add(docs) |> tnt_commit()
tnt_num_docs(idx)
#> [1] 2tnt_update() replaces documents by a key column;
tnt_delete() removes them. Both need a commit to take
effect.
idx |>
tnt_update(
data.frame(id = 1L, slug = "edital-001",
title = "Edital de licitação 001 (retificado)",
body = "Aquisição de notebooks.",
date = as.Date("2024-02-10")),
by = slug
) |>
tnt_commit()
tnt_search(idx, "notebooks")[, c("id", "title")]
#> # A tibble: 1 × 2
#> id title
#> <dbl> <chr>
#> 1 1 Edital de licitação 001 (retificado)
idx |> tnt_delete(slug == "edital-002") |> tnt_commit()
tnt_num_docs(idx)
#> [1] 1?tnt_search documents every search option.?tnt_field lists the field types and their
stemming/stop-word options.tnt_stemmers() returns the supported languages.