View Source Vectorex (vectorex v0.1.0)

This module is a container for controls for a full text search for postgres.

It provides a fluent api to build full text search queries which can be transformed to a string that can be passed for execution using &to_sql/1

The module contains four functions that can be used to build the query

  1. ts_and
  2. ts_or
  3. ts_not
  4. ts_followed_by

Same functions exist in Vectorex.Subquery

Depending on the function you pass to new/2, the behaviour changes. If the control is supported by the function, we append it to the query. If not, the parameter is ignored.

Check the official documentation to verify which controls are supported by the function

Only to_tsquery supports all 4 controls.

You can create a new instance of Vectorex using new/2 by passing the postgres function you want to use and the parameter

Available Postgres functions are: :to_tsquery, :phraseto_tsquery, :plainto_tsquery, :websearch_to_tsquery

After that, you can start building the query.

Building queries

You can do that by using pipes

# and 
Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_and("ocaml")

# or
Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_or("ocaml")

# not
Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_not("ocaml")

# followed_by
Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_followed_by("ocaml")

Obviously, you can pipe multiple times

Vectorex.new(:to_tsquery, "elixir") 
|> Vectorex.ts_and("ocaml")
|> Vectorex.ts_and("scala")

Or you can use a list

Vectorex.new(:to_tsquery, "elixir") 
|> Vectorex.ts_and(["ocaml", "scala"])

Building subqueries

You can also group operators together using Vectorex.Subquery.new/1. You can do this if you want parentheses around your terms

inner =
  Vectorex.Subquery.new("ocaml")
  |> Vectorex.Subquery.ts_and("scala")

result =
  Vectorex.new(:to_tsquery, "elixir")
  |> Vectorex.ts_and(inner)

Subqueries also support the list option

inner =
  Vectorex.Subquery.new("ocaml")
  |> Vectorex.Subquery.ts_or(["scala", "haskell"])

result =
  Vectorex.new(:to_tsquery, "elixir")
  |> Vectorex.ts_and(inner)

We can also pass a list of subqueries

inner =
  Vectorex.Subquery.new("ocaml")
  |> Vectorex.Subquery.ts_or(["scala", "haskell"])

inner2 =
  Vectorex.Subquery.new("java")
  |> Vectorex.Subquery.ts_or("c#")

result =
  Vectorex.new(:to_tsquery, "elixir")
  |> Vectorex.ts_and([inner, inner2])

Converting to sql

After we build the query we want, we need to convert it to a string. We can do that using to_sql/1

We can use that string in an Ecto fragment for execution

vectorex = Vectorex.new(:to_tsquery, "elixir")

from e in Event,
    where: fragment("textsearchable_index_col @@ to_tsquery(?)", ^Vectorex.to_sql(vectorex))

Summary

Functions

Creates a new Vectorex instance which can be used to build a full text search query

Transforms a Vectorex instance to a sql string

Adds a AND clause.

Adds a FOLLOWED BY clause.

Adds a NOT clause.

Adds a OR clause.

Types

@type t() :: %Vectorex{
  function:
    :to_tsquery | :phraseto_tsquery | :plainto_tsquery | :websearch_to_tsquery,
  params:
    [{atom(), String.t()}] | [{atom(), Vectorex.Subquery.t()}] | [String.t()]
}

Functions

Creates a new Vectorex instance which can be used to build a full text search query

Examples

iex> Vectorex.new(:to_tsquery, "elixir")    
%Vectorex{params: ["elixir"], function: :to_tsquery}

iex> Vectorex.new(:phraseto_tsquery, "elixir")    
%Vectorex{params: ["elixir"], function: :phraseto_tsquery}

iex> Vectorex.new(:plainto_tsquery, "elixir")    
%Vectorex{params: ["elixir"], function: :plainto_tsquery}

iex> Vectorex.new(:websearch_to_tsquery, "elixir")    
%Vectorex{params: ["elixir"], function: :websearch_to_tsquery}
@spec to_sql(vectorex :: t()) :: String.t()

Transforms a Vectorex instance to a sql string

Examples

iex> Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_and("ocaml") |> Vectorex.ts_and("haskell") |>  Vectorex.to_sql()
"elixir & ocaml & haskell"

iex> Vectorex.new(:to_tsquery, "elixir") |> Vectorex.ts_and(Vectorex.Subquery.new("ocaml") |> Vectorex.Subquery.ts_or("scala")) |> Vectorex.to_sql()
"elixir & (ocaml | scala)"
@spec ts_and(
  vector :: t(),
  params ::
    [String.t()] | String.t() | Vectorex.Subquery.t() | [Vectorex.Subquery.t()]
) :: t()

Adds a AND clause.

If the operator is supported by the text search control, the parameter is applied to the builder. If not the parameter is ignored.

Link to this function

ts_followed_by(vector, params)

View Source
@spec ts_followed_by(
  vector :: t(),
  params ::
    [String.t()] | String.t() | Vectorex.Subquery.t() | [Vectorex.Subquery.t()]
) :: t()

Adds a FOLLOWED BY clause.

If the operator is supported by the text search control, the parameter is applied to the builder. If not the parameter is ignored.

@spec ts_not(
  vector :: t(),
  params ::
    [String.t()] | String.t() | Vectorex.Subquery.t() | [Vectorex.Subquery.t()]
) :: t()

Adds a NOT clause.

If the operator is supported by the text search control, the parameter is applied to the builder. If not the parameter is ignored.

@spec ts_or(
  vector :: t(),
  params ::
    [String.t()] | String.t() | Vectorex.Subquery.t() | [Vectorex.Subquery.t()]
) :: t()

Adds a OR clause.

If the operator is supported by the text search control, the parameter is applied to the builder. If not the parameter is ignored.