View Source ArangoXEcto.View (ArangoX Ecto v1.3.1)

ArangoSearch view module

Defines a schema for a view to help create and manage Arango Search views.

creation

Creation

Like for collections, the same static vs dynamic system is in place. If in dynamic mode and a collection that a view links to doesn't exist when querying, it will be created automatically. If in static mode an error will be raised if the the appropriate migration has not been made. Check out the ArangoXEcto.Migration module for more info.

Like for collections, there is no check if a view exists when use the ArangoXEcto.aql_query/4 function and will error, so make sure the view exists first.

example

Example

defmodule Something.UserSearch do

use ArangoXEcto.View

alias ArangoXEcto.View.Link

view "user_search" do
  primary_sort :created_at, :desc
  primary_sort :name

  store_value [:email], :lz4
  store_value [:first_name, :last_name], :none

  link MyApp.Users, %Link{
    includeAllFields: true,
    fields: %{
      name: %Link{
        analyzers: [:text_en]
      }
    }
  }

  options  [
    primarySortCompression: :lz4
  ]
end

end

defining-the-analyzer-module

Defining the analyzer module

When in dynamic mode only the analyzer module needs to be passed to the view so that the analyzers will be automatically created. This option will be ignored in static mode. You can pass the analyzer module by passing the module to the :analyzer_module option on the use statement.

use ArangoXEcto.View, analyzer_module: Something.Analyzers

querying

Querying

Views essentially operate as virtual wrappers of Ecto Schemas. You can use them just like other schemas to query on and all the fields available are a culmination of the fields on the link schemas. This is how it works in the ArangoDB so to keep it true to function, it functions the same here.

Querying is done exactly the same as a normal schema except the result will not be a struct. This is explained further below.

iex> Repo.all(MyApp.UsersView)
[%{first_name: "John", last_name: "Smith"}, _]

Since the Arango Search function heavily relies on the AQL SEARCH operation it only makes sense for this to also work in Ecto Queries. You can find more info about this under ArangoXEcto.Query.search/3 and ArangoXEcto.Query.or_search/3.

The search operation functions the same as the Ecto.Query.where/3 clause so that can be used for more reference. You can also use fragments to use special analyzers, an example is given below.

Note

You must import the ArangoXEcto.Query function to use the search query macro.

iex> MyApp.UsersView |> search(gender: :male) |> Repo.all()
[%{gender: :male}, ...]

iex> from(MyApp.UsersView) |> search([uv], uv.gender == :female) |> Repo.all()
[%{gender: :female}, ...]

iex> UsersView |> search([uv], fragment("ANALYZER(? == ?, "identity")", uv.first_name, "John")) |> Repo.all()
[%{first_name: "John"}]

Unfortunately this won't work as an argument to the Ecto Query from macro (e.g. below) and will only work as above.

# DO NOT USE THIS, IT WILL NOT WORK
iex> from(uv in MyApp.UsersView, search: uv.first_name == "John")
ArgumentError

Of course you can also use AQL queries. Noting that you need to ensure the view is created already because it will not be checked.

iex> ArangoXEcto.aqlquery(Repo, ...> "FOR uv IN @@view SEARCH ANALYZER(uv.firstname == @first_name, "identity") RETURN uv", ...> "@view": UsersView.__view(:name), ...> first_name: "John" ...> ) {:ok, [%{"first_name" => "John"}]}

Sorting

Since views work with ecto queries as per usual, you can use functions such as sort in Ecto queries. If you want to sort based on the BM25 score for example, you can use fragments like below.

iex> UsersView
...> |> search(gender: :male)
...> |> order_by([uv], fragment("BM25(?)", uv))
...> |> select([uv], {uv.first_name, fragment("BM25(?)", uv)})
[{"John", 1.8}, {"Bob", 1.8}]

loading-results

Loading results

Due to how views function and the possibility of multiple types of returns, the result of a query cannot be automatically loaded to a struct with Ecto so you will have to use the ArangoXEcto.load/2 function. It does still load the values using the field loaders to the correct type, so if you don't need to load it into a struct you can skip this.

iex> Repo.all(MyApp.UsersView) |> ArangoXEcto.load(MyApp.User)
[%User{first_name: "John", last_name: "Smith"}, _]

Since you can have multiple different schemas linked, the ArangoXEcto.load/2 function supports passing multiple module options that will match against the arango _id to load the correct module.

iex> Repo.all(MyApp.UsersView) |> ArangoXEcto.load([MyApp.User, MyApp.Post])
[%User{first_name: "John", last_name: "Smith"}, %Post{name: "abc"}]

Link to this section Summary

Functions

Generates the view definition

Defines a link field on the view.

Defines options for view creation.

Defines a primary sort field on the view.

Defines a stored value on the view.

Defines a view with a view name and defenitions.

Link to this section Types

@type compression() :: :lz4 | :none
@type name() :: String.t()

Link to this section Functions

@spec definition(Module.t()) :: map()

Generates the view definition

This takes the macros that define the view and converts it into a definition for use on creation.

Link to this macro

link(schema, link)

View Source (macro)

Defines a link field on the view.

This can be supplied more than once in a view block to enable multiple link definitions. Each link can be of different documents or edges, this is sorted on querying as mentioned at the top of this module.

Links are defined by the ArangoXEcto.View.Link module.

parameters

Parameters

* `:schema` - the module of the document or edge the link should be created on
* `:link` - the link definition, see `ArangoXEcto.View.Link`
Link to this macro

options(attrs)

View Source (macro)

Defines options for view creation.

options

Options

The available options are directly from the ArangoDB View definition.

* `:consolidationIntervalMsec` - wait at least this many milliseconds between applying consolidationPolicy
  to consolidate View data store and possibly release space on the filesystem.
* `:consolidationPolicy` - the consolidation policy to apply for selecting data store segment merge candidates.
* `:commitIntervalMsec` - wait at least this many milliseconds between committing View data store changes
   and making documents visible to queries.
* `:writebufferSizeMax` - maximum memory byte size per writer (segment) before a writer (segment) flush is triggered.
* `:writebufferIdle` - maximum number of writers (segments) cached in the pool.
* `:writebufferActive` - maximum number of concurrent active writers (segments) that perform a transaction.
  Other writers (segments) wait till current active writers (segments) finish.
* `:cleanupIntervalStep` - waits at least this many commits between removing unused files in its data directory .
* `:primarySortCompression` - defines how to compress the primary sort data (introduced in ArangoDB v3.7.0).
  See `t:ArangoXEcto.View.compression/0`.

  `:lz4` (default) - use LZ4 fast compression
  `:none` - disable compression to trade space for speed
Link to this macro

primary_sort(field, direction \\ :asc)

View Source (macro)

Defines a primary sort field on the view.

Only a field name is required but a direction can also be supplied. By default the direction will be ascending (:asc).

This can be supplied more than once in a view block to enable multiple primary sorts.

parameters

Parameters

* `:field` - atom name of the field to be used as a primary sort
* `:direction` - either `:asc` or `:desc` for sort direction
Link to this macro

store_value(fields, compression \\ :lz4)

View Source (macro)

Defines a stored value on the view.

Only the fields used is required but the compression method can also be supplied. By default the compression will be :lz4.

This can be supplied more than once in a view block to enable multiple stored value definitions.

parameters

Parameters

* `:fields` - a list of atoms for fields for the stored value
* `:compression` - either `:none` or `:lz4` for compression, see `t:ArangoXEcto.View.compression/0`
Link to this macro

view(name, list)

View Source (macro)

Defines a view with a view name and defenitions.

Can only be defined once per view module.