Current section
Files
Jump to
Current section
Files
lib/rest/rest.ex
defmodule Astra.Rest do
alias Astra.Rest.Http
@moduledoc """
`Astra.Rest` provides functions to access the public methods of the REST interface for databases hosed on https://astra.datastax.com.
Astra's REST interface is implemented using the stargate project, https://stargate.io. Swagger docs for this interface are available here https://docs.astra.datastax.com/reference#keyspaces-2.
If required, raw access to the Astra REST api can be obtained through the `Astra.Rest.Http` module.
"""
@doc """
`get_row` retrieves one or more rows based on the `keyspace`, `table` and `primary_key`. Primary keys that span multiple fields
should be delimeted with a `\\` ex. "123\\tuesday".
## Examples
```
> Astra.Rest.get_row("test", "thing", "83b8d85d-bd33-4650-8b9d-b43354187114")
{:ok, [%{id: "83b8d85d-bd33-4650-8b9d-b43354187114", name: "test row"}]}
```
"""
@spec get_row(String, String, String) :: {Atom, list(Map)}
def get_row(keyspace, table, primary_key), do: Http.get("#{keyspace}/#{table}/#{primary_key}") |> Http.parse_response
@doc """
Add a row. All fields in the row are optional except for fields defined in the `PRIMARY KEY` of the table definition.
## Parameters
- keyspace: the keyspace containing the target table
- table: the table containing the entity we are retrieving
- entity: a Map of the attributes of the row we are adding
ex.
```
%{
id: "83b8d85d-bd33-4650-8b9d-b43354187114",
name: "test row"
}
```
## Examples
```
> new_row = %{id: "83b8d85d-bd33-4650-8b9d-b43354187114", name: "test row"}
> Astra.Rest.add_row("test", "thing", new_row)
{:ok, %{id: "83b8d85d-bd33-4650-8b9d-b43354187114"}}
```
"""
@spec add_row(String, String, Map) :: {Atom, Map}
def add_row(keyspace, table, entity), do: Http.post("#{keyspace}/#{table}", Http.json!(entity)) |> Http.parse_response
@doc """
Update part of a row, only fields provided in the entity will be updated.
## Parameters
- keyspace: the keyspace containing the target table
- table: the table containing the entity we are retrieving
- key: a primary key, if it contains multiple fields they should be seperated with `\\`
- entity: a Map of the attributes of the row we are adding
ex.
```
%{
id: "83b8d85d-bd33-4650-8b9d-b43354187114",
name: "test row"
}
```
## Examples
```
> new_row = %{id: "83b8d85d-bd33-4650-8b9d-b43354187114", name: "test row"}
> Astra.Rest.add_row("test", "thing", new_row)
{:ok, %{id: "83b8d85d-bd33-4650-8b9d-b43354187114"}}
```
"""
@spec update_partial_row(String, String, String, Map) :: {Atom, Map}
def update_partial_row(keyspace, table, key, changes), do: Http.patch("#{keyspace}/#{table}/#{key}", Http.json!(changes)) |> Http.parse_response
@doc """
Similar to `Astra.Rest.add_row/3`, the key needs to be provided explicity.
## Parameters
- keyspace: the keyspace containing the target table
- table: the table containing the entity we are retrieving
- key: a primary key, if it contains multiple fields they should be seperated with `\\`
- entity: a Map of the attributes of the row we are adding
ex.
```
%{
id: "83b8d85d-bd33-4650-8b9d-b43354187114",
name: "test row"
}
```
## Examples
```
> new_row = %{name: "test row"}
> Astra.Rest.replace_row("test", "thing", "83b8d85d-bd33-4650-8b9d-b43354187115", new_row)
{:ok, %{name: "test row"}}
> Astra.Rest.get_row("test", "thing", "83b8d85d-bd33-4650-8b9d-b43354187115")
{:ok, [%{id: "83b8d85d-bd33-4650-8b9d-b43354187115", name: "test row"}]}
```
"""
@spec replace_row(String, String, String, Map) :: {Atom, Map}
def replace_row(keyspace, table, key, entity), do: Http.put("#{keyspace}/#{table}/#{key}", Http.json!(entity)) |>Http.parse_response
@doc """
Remove a row.
## Parameters
- keyspace: the keyspace containing the target table
- table: the table containing the entity we are retrieving
- key: a primary key, if it contains multiple fields they should be seperated with `\\`
## Examples
```
> new_row = %{id: "83b8d85d-bd33-4650-8b9d-b43354187114", name: "test row"}
> Astra.Rest.delete_row("test", "thing", "83b8d85d-bd33-4650-8b9d-b43354187114")
{:ok, []]}
```
"""
# delete row
@spec delete_row(String, String, String) :: {Atom, []}
def delete_row(keyspace, table, key), do: Http.delete("#{keyspace}/#{table}/#{key}") |> Http.parse_response
# search a table
# CREATE CUSTOM INDEX things_name_idx ON thing (name) USING 'StorageAttachedIndex' WITH OPTIONS = {'normalize': 'true', 'case_sensitive': 'false'};
@doc """
Search for rows in a table. The following operators are available for the query: `$eq`, `$lt`, `$lte`, `$gt`, `$gte`, `$ne`, and `$exists`.
Please note that some restrictions exist for searches:
1. Search cannot be on a `PRIMARY KEY` field, unless a composite primary key is being used.
2. Search fields will require some form of secondary index. SAI is usually the best choice https://docs.astra.datastax.com/docs/using-storage-attached-indexing-sai
Example of creating an SAI index on a table:
```
CREATE TABLE thing (
id text PRIMARY KEY,
name text
)
CREATE CUSTOM INDEX things_name_idx
ON thing (name) USING 'StorageAttachedIndex'
WITH OPTIONS = {'normalize': 'true', 'case_sensitive': 'false'};
```
## Parameters
- keyspace: the keyspace containing the target table
- table: the table containing the entity we are retrieving
- query: the search query for the table. ex. `%{name: %{"$in": ["red", "blue"]}}`
## Examples
```
> Astra.Rest.search_table("test", "thing", %{name: %{"$eq": "test row"}})
```
"""
@spec search_table(String, String, Map) :: {Atom, []}
def search_table(keyspace, table, query), do: Http.get("#{keyspace}/#{table}",[], params: %{where: Http.json!(query)}) |> Http.parse_response
end