ArcadeDB full-text search — tenant-blind FULL_TEXT (Lucene) index DDL and
SEARCH_INDEX/SEARCH_FIELDS query builders, parallel to Arcadic.Vector.
The query text binds as the :q param (SQL); the index reference "Type[property]" and any
analyzer class name are interpolated behind Arcadic.Identifier / a dotted-class-name allowlist
(the only injection surfaces, closed by construction). A FULL_TEXT index retro-indexes rows
that already exist when it is created (unlike LSM_SPARSE_VECTOR, which does not) — so there is
no create-before-load ordering requirement. Full-text is HTTP-only SQL (Bolt is Cypher-only).
search/5's property_or_properties must match an existing FULL_TEXT index by NAME: a
single-property index is Type[prop], a composite create_index(conn, T, [a, b]) is Type[a,b]
(search it with the same list). SEARCH_INDEX on a ref with no matching index is a server
SchemaException. search_fields/5 names the fields directly and needs no exact index-name match.
Summary
Functions
Creates a FULL_TEXT index on type over one property or a list of properties (idempotent —
IF NOT EXISTS unless if_not_exists: false). opts: :if_not_exists (bool, default true),
:analyzer (a friendly atom — :standard/:english/:keyword/:whitespace/:simple — or a
Lucene FQCN string). Retro-indexes existing rows. Value-free on a bad identifier / analyzer / opt.
Creates a FULL_TEXT index, raising on error.
Drops a FULL_TEXT index (idempotent — IF EXISTS).
Drops a FULL_TEXT index, raising on error.
Builds the FULL_TEXT index reference "Type[p1,p2]", validating every identifier.
Full-text search via SEARCH_INDEX('Type[property]', :q). query binds as :q. opts:
:limit (pos_integer → LIMIT :k), :with_score (project the BM25 $score and use the
relevance-ranked {metadata:true} form). Returns whole records (+ "score" when :with_score).
Full-text search, returning rows or raising.
Full-text search via SEARCH_FIELDS(['p1','p2'…], :q) over a property list (all must be
FULL_TEXT-indexed). Same opts/return shape as search/5 — but note SEARCH_FIELDS
computes no relevance score: with :with_score it projects a constant score: 0.0 on every
row (a shape-only column, not a ranking). Use search/5 (SEARCH_INDEX) for the BM25 $score.
Full-text search_fields, returning rows or raising.
Functions
@spec create_index(Arcadic.Conn.t(), String.t(), String.t() | [String.t()], keyword()) :: :ok | {:error, atom() | Exception.t()}
Creates a FULL_TEXT index on type over one property or a list of properties (idempotent —
IF NOT EXISTS unless if_not_exists: false). opts: :if_not_exists (bool, default true),
:analyzer (a friendly atom — :standard/:english/:keyword/:whitespace/:simple — or a
Lucene FQCN string). Retro-indexes existing rows. Value-free on a bad identifier / analyzer / opt.
@spec create_index!( Arcadic.Conn.t(), String.t(), String.t() | [String.t()], keyword() ) :: :ok
Creates a FULL_TEXT index, raising on error.
@spec drop_index(Arcadic.Conn.t(), String.t(), String.t() | [String.t()]) :: :ok | {:error, atom() | Exception.t()}
Drops a FULL_TEXT index (idempotent — IF EXISTS).
@spec drop_index!(Arcadic.Conn.t(), String.t(), String.t() | [String.t()]) :: :ok
Drops a FULL_TEXT index, raising on error.
@spec index_ref(String.t(), String.t() | [String.t()]) :: {:ok, String.t()} | {:error, :invalid_identifier}
Builds the FULL_TEXT index reference "Type[p1,p2]", validating every identifier.
@spec search( Arcadic.Conn.t(), String.t(), String.t() | [String.t()], String.t(), keyword() ) :: {:ok, [map()]} | {:error, atom() | Exception.t()}
Full-text search via SEARCH_INDEX('Type[property]', :q). query binds as :q. opts:
:limit (pos_integer → LIMIT :k), :with_score (project the BM25 $score and use the
relevance-ranked {metadata:true} form). Returns whole records (+ "score" when :with_score).
@spec search!( Arcadic.Conn.t(), String.t(), String.t() | [String.t()], String.t(), keyword() ) :: [map()]
Full-text search, returning rows or raising.
@spec search_fields(Arcadic.Conn.t(), String.t(), [String.t()], String.t(), keyword()) :: {:ok, [map()]} | {:error, atom() | Exception.t()}
Full-text search via SEARCH_FIELDS(['p1','p2'…], :q) over a property list (all must be
FULL_TEXT-indexed). Same opts/return shape as search/5 — but note SEARCH_FIELDS
computes no relevance score: with :with_score it projects a constant score: 0.0 on every
row (a shape-only column, not a ranking). Use search/5 (SEARCH_INDEX) for the BM25 $score.
@spec search_fields!( Arcadic.Conn.t(), String.t(), [String.t()], String.t(), keyword() ) :: [map()]
Full-text search_fields, returning rows or raising.