View Source ArangoXEcto.Query (ArangoX Ecto v2.0.0)
ArangoDB specific Ecto.Query
functions.
The all/1
, delete_all/1
and update_all/1
functions in this module convert Ecto.Query
structs into AQL syntax.
The Arango specific functions are available to support ArangoSearch questions and perform graph queries.
ArangoSearch queries
ArangoSearch queries can be performed through the search/3
and or_search/3
macros. For
example, if you wanted to do a wildcard search for the title of your favorite movie you can do the
following.
from(MoviesView)
|> search([mv], fragment("LIKE(?, ?)", mv.title, "%War%"))
|> Repo.all()
You can see that a fragment is used to incluse custom AQL. If you wanted to use a specific analyzer, for example for case-insensitive searches, you could so using a fragment also like below.
from(MoviesView)
|> search([mv], fragment("ANALYZER(LIKE(?, ?), \"norm_en\")", mv.title, "%war%"))
|> Repo.all()
Graph searches
You can do graph queries inside Ecto queries. To do this you just use the graph/5
macro
provided. This will generate the required fragment to do graph queries.
For example, take the following AQL query.
FOR u IN 1..3 OUTBOUND "user/bob" friends
RETURN u
You can represent that using the following Ecto query. Note that a select is required since Ecto needs to know what fields to get when querying on a fragment.
from(
u in graph(1..3, :outbound, "user/bob", "friends"),
select: map(u, [:first_name, :last_name])
)
|> Repo.all()
Credit
This initial code for this module was used from
https://github.com/ArangoDB-Community/arangodb_ecto/blob/master/lib/arangodb_ecto/query.ex.
Credit for the initial code goes to mpoeter
. Updates were made since to enable additional
functionality and to work with the latest Ecto version.
Summary
Functions
Creates an AQL query to fetch all entries from the data store matching the given Ecto query.
Creates an AQL query to delete all entries from the data store matching the given Ecto query.
Query an ArangoDB graph
A OR search query expression.
An AND search query expression.
Creates an AQL query to update all entries from the data store matching the given Ecto query.
Functions
@spec all(Ecto.Query.t()) :: binary()
Creates an AQL query to fetch all entries from the data store matching the given Ecto query.
@spec delete_all(Ecto.Query.t()) :: binary()
Creates an AQL query to delete all entries from the data store matching the given Ecto query.
Query an ArangoDB graph
This is a helper around searching a graph. This essentially generates a fragment that is used in the from or join part of the Ecto query.
You MUST provide a select in the query, otherwise an error be raised since Ecto can't work out what fields to use when a fragment is used.
There is a limitiation that you can't use the Ecto.Query.API.struct/2
function since the query
is a fragment. If you need to load your results into a struct then you can use the
ArangoXEcto.load/2
function.
Example
For example, lets take the following query.
FOR u IN 1..3 OUTBOUND "user/bob" friends
RETURN u
You can represent that using the following Ecto query. Note that like you would in any other Ecto query, you need to pin any variables used.
from(
u in graph(1..3, :outbound, "user/bob", "friends"),
select: map(u, [:first_name, :last_name])
)
|> Repo.all()
Providing options
You can also provide a keyword list as options as the last parameter to the macro.
FOR u IN 1..3 OUTBOUND "user/bob" friends OPTIONS { vertexCollections: ["users"] }
RETURN u
This can be done using like the following.
from(u in graph(1..3, :outbound, "user/bob", "friends", vertexCollections: ["users"]))
|> select([u], map(u, [:first_name, :last_name]))
|> Repo.all()
Dynamically selecting fields
If you want to select all of the fields on a struct you can use the following code and pin the
select_fields
variable. Replace the User
schema with the schema in question.
select_fields = Enum.map(User.__schema__(:fields), &User.__schema__(:field_source, &1))
A OR search query expression.
Extention to the Ecto.Query
api for arango searches.
This function is the same as ArangoXEcto.Query.search/3
except implements as an or clause.
This also follows the same syntax as the Ecto.Query.or_where/3
function.
An AND search query expression.
Extention to the Ecto.Query
api for arango searches.
The expression syntax is exactly the same as the regular Ecto.Query.where/3
clause.
Refer to that for more info on syntax or for advanced AQL queries see the section below.
You will need to import this function like you do for Ecto.Query
.
Implementation
This will store the search in the Ecto query where
clause
with a custom search operation. This is to prevent having to create a seperate query
type. When converting the Ecto query to an AQL query, this is caught and changed
into an AQL SEARCH
expression.
Using Analyzers and advanced AQL
To save having to learn some new kind of query format for so many different possible search
scenarios, you can just use AQL directly in. This is powered by the Ecto.Query.API.fragment/1
function.
Below is an example of how you can implement using a custom analyzer:
from(UsersView)
|> search([uv], fragment("ANALYZER(? == ?, \"identity\")", uv.first_name, "John"))
|> Repo.all()
@spec update_all(Ecto.Query.t()) :: binary()
Creates an AQL query to update all entries from the data store matching the given Ecto query.