High-level search API for Redis, inspired by Meilisearch.
Wraps the RediSearch FT.* commands with an Elixir-friendly interface:
keyword-based schemas, map-based documents, Elixir filter expressions
instead of raw query strings, and parsed result structs.
For raw command access, see Redis.Commands.Search.
Quick Start
# Create an index
Redis.Search.create_index(conn, "movies",
prefix: "movie:",
fields: [
title: :text,
year: {:numeric, sortable: true},
genres: :tag
]
)
# Add documents as maps
Redis.Search.add(conn, "movies", "movie:1", %{
title: "The Dark Knight",
year: 2008,
genres: "action,thriller"
})
# Search with Elixir filters
Redis.Search.find(conn, "movies", "dark knight",
where: [year: {:gt, 2000}, genres: "action"],
sort: {:year, :desc},
limit: 10
)
#=> {:ok, %Redis.Search.Result{total: 1, results: [%{id: "movie:1", ...}]}}Filter Syntax
The :where option accepts a keyword list compiled to RediSearch query syntax:
field: "value"-- text match (@field:value)field: {:match, "hello world"}-- phrase match (@field:(hello world))field: {:gt, n}-- greater than (@field:[(n +inf])field: {:gte, n}-- greater than or equal (@field:[n +inf])field: {:lt, n}-- less than (@field:[-inf (n])field: {:lte, n}-- less than or equal (@field:[-inf n])field: {:between, min, max}-- range (@field:[min max])field: {:tag, "val"}-- exact tag (@field:{val})field: {:any, ["a", "b"]}-- tag OR (@field:{a|b})
Options
:where-- filter keyword list (see above):sort--{field, :asc | :desc}:limit-- max results (integer) or{offset, count}:return-- list of fields to return:nocontent-- return only IDs (boolean):dialect-- RediSearch query dialect version:coerce-- auto-coerce numeric strings (default: true)
Summary
Functions
Adds a document to an index.
Adds multiple documents via pipeline.
Runs an aggregation query.
Creates a search index.
Drops a search index. Pass dd: true to also delete indexed documents.
Searches an index with Elixir-friendly filters.
Returns index info as a map.
Functions
Adds a document to an index.
Auto-detects hash vs JSON based on the index type. Pass :on to
override if the index hasn't been inspected yet.
Redis.Search.add(conn, "movies", "movie:1", %{
title: "Inception",
year: 2010,
genres: "sci-fi,thriller"
})
Adds multiple documents via pipeline.
Redis.Search.add_many(conn, "movies", [
{"movie:1", %{title: "Inception", year: 2010}},
{"movie:2", %{title: "Interstellar", year: 2014}}
])
Runs an aggregation query.
Redis.Search.aggregate(conn, "movies",
group_by: :genres,
reduce: [count: "total"],
sort: {:total, :desc},
limit: 10
)
# Multiple reducers
Redis.Search.aggregate(conn, "movies",
group_by: [:city],
reduce: [
count: "total",
avg: {:score, "avg_score"}
]
)Reducers
count: "alias"-- COUNTsum: {:field, "alias"}-- SUMavg: {:field, "alias"}-- AVGmin: {:field, "alias"}-- MINmax: {:field, "alias"}-- MAX
Creates a search index.
Fields are specified as a keyword list:
Redis.Search.create_index(conn, "idx", fields: [name: :text, age: :numeric])
Redis.Search.create_index(conn, "idx",
on: :json,
prefix: "doc:",
fields: [
title: :text,
score: {:numeric, sortable: true},
tags: :tag
]
)Options
:fields(required) -- keyword list of{name, type}or{name, {type, opts...}}:on--:hash(default) or:json:prefix-- key prefix string or list:stopwords-- list of stopwords or0for none:language-- default language
Drops a search index. Pass dd: true to also delete indexed documents.
Searches an index with Elixir-friendly filters.
# Simple full-text search
Redis.Search.find(conn, "movies", "dark knight")
# With filters
Redis.Search.find(conn, "movies", "batman",
where: [year: {:gt, 2000}, genres: {:tag, "action"}],
sort: {:year, :desc},
limit: 10,
return: [:title, :year]
)See module docs for the full filter syntax.
Returns index info as a map.