--- title: "Getting started with tantivyr" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Getting started with tantivyr} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") ``` ```{r setup} library(tantivyr) ``` `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. ## The convenience layer: `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. ```{r} 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 ``` ### Searching `tnt_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*. ```{r} tnt_search(idx, "orçamento") ``` ### Filtering Filters can be written as ordinary R comparisons. They are combined with the text query. ```{r} tnt_search(idx, "", filter = year >= 2024) tnt_search(idx, "congresso", filter = source == "A") tnt_search(idx, "", filter = year %in% c(2022, 2024), limit = 10) ``` You can also pass a raw [Tantivy query string](https://docs.rs/tantivy/latest/tantivy/query/struct.QueryParser.html) for anything the helpers do not cover: ```{r} tnt_search(idx, "", filter = "year:[2023 TO *] AND source:B") ``` ### Highlighting and ordering ```{r} tnt_search(idx, "congresso", highlight = title)$title_snippet tnt_search(idx, "", order_by = year, desc = TRUE)[, c("title", "year")] ``` ### Counting `tnt_count()` returns the total number of matches, ignoring any limit. ```{r} tnt_count(idx, "congresso") tnt_count(idx, "", filter = year == 2024) ``` ## The explicit layer: schemas and persistence For 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. ```{r} 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. ```{r} 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) ``` ### Incremental updates and deletes `tnt_update()` replaces documents by a key column; `tnt_delete()` removes them. Both need a commit to take effect. ```{r} 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")] idx |> tnt_delete(slug == "edital-002") |> tnt_commit() tnt_num_docs(idx) ``` ### Reopening an index On-disk indexes survive across sessions. Call `tnt_index()` with just the path to reopen — the schema is restored automatically. ```{r} reopened <- tnt_index(path) tnt_num_docs(reopened) ``` ## Where to go next - `?tnt_search` documents every search option. - `?tnt_field` lists the field types and their stemming/stop-word options. - `tnt_stemmers()` returns the supported languages. ```{r, include = FALSE} unlink(path, recursive = TRUE) ```