Skip to content

YgorCastor/ravix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ravix_logo

Elixir CI Coverage Status Hex

Ravix

Ravix is a in-development project to implement a client for the amazing RavenDB NoSQL Database.

Usage

Installing

Add Ravix to your mix.exs dependencies

{:ravix, "~> 0.10.0"}

Setting up your Repository

Create a Ravix Store Module for your repository

defmodule YourProject.YourStore do
  use Ravix.Documents.Store, otp_app: :your_app
end

You can configure your Store in your config.exs files

config :ravix, Ravix.Test.Store,
  urls: [System.get_env("RAVENDB_URL", "http://localhost:8080")],
  database: "test",
  retry_on_failure: true,
  retry_backoff: 100,
  retry_count: 3,
  force_create_database: true,
  document_conventions: %{
    max_number_of_requests_per_session: 30,
    max_ids_to_catch: 32,
    timeout: 30,
    use_optimistic_concurrency: false,
    max_length_of_query_using_get_url: 1024   512,
    identity_parts_separator: "/",
    disable_topology_update: false
  }

Note: All the calls to RavenDB are done via HTTP calls, to that we leverage the use of Finch, check there for adapter configurations.

Then you can start the processes in your main supervisor

defmodule Ravix.TestApplication do
  use Application

  def start(_opts, _) do
    children = [
      {Finch, name: Ravix.Finch}, # By default the store searches for a Finch instance called 'Ravix.Finch' 
      {Ravix.Test.Store, [%{}]} # you can create multiple stores
    ]

    Supervisor.init(
      children,
      strategy: :one_for_one
    )
  end
end

Querying the Database

All operations supported by the driver should be executed inside a session, to open a session you can just call the open_session/0 function from the store you defined. All the changes are only persisted when the function Ravix.Documents.Session.save_changes/1 is called!

iex(2)> Ravix.Test.Store.open_session()
{:ok, "985781c8-9154-494b-92d0-a66b49bb17ee"}

Inserting a new document

iex(2)> Ravix.Test.Store.open_session()
iex(2)> {:ok, session_id} = Ravix.Test.Store.open_session()
{:ok, "c4fb1f48-c969-4c76-9b12-5521926c7533"}
iex(3)> Ravix.Documents.Session.store(session_id, %{id: "cat/1", cat_name: "Adolfus"})
{:ok, %{cat_name: "Adolfus", id: "cat/1"}}
iex(4)> Ravix.Documents.Session.save_changes(session_id)
{:ok,
 %{
   "Results" => [
     %{
       "@change-vector" => "A:264-vzsRp yZT0GDkS5GJY/pAQ",
       "@collection" => "@empty",
       "@id" => "cat/1",
       "@last-modified" => "2022-03-28T15:01:45.6545514Z",
       "Type" => "PUT"
     }
   ]
 }}

Loading a document into the session

iex(3)> {:ok, session_id} = Ravix.Test.Store.open_session()
{:ok, "d17e2be8-8c1e-4a59-8626-46725387f769"}
iex(4)> Ravix.Documents.Session.load(session_id, ["cat/1"])
{:ok,
 %{
   "Includes" => %{},
   "Results" => [
     %{
       "@metadata" => %{
         "@change-vector" => "A:264-vzsRp yZT0GDkS5GJY/pAQ",
         "@id" => "cat/1",
         "@last-modified" => "2022-03-28T15:01:45.6545514Z"
       },
       "cat_name" => "Adolfus",
       "id" => "cat/1"
     }
   ],
   "already_loaded_ids" => []
 }}

Querying using RQL

RavenDB provides a query-language called RQL, and for that Ravix provides two ways to deal with queries, using builder functions and raw RQLs

RQL Builder

You can build RQLs using the builder provided by the Ravix.RQL.Query module

iex(11)> from("@all_docs") |> where(equal_to("cat_name", "Adolfus")) |> list_all(session_id)
{:ok,
 %{
   "DurationInMs" => 1,
   "IncludedPaths" => nil,
   "Includes" => %{},
   "IndexName" => "Auto/AllDocs/Bycat_nameAndid",
   "IndexTimestamp" => "2022-03-28T18:39:58.7637789",
   "IsStale" => false,
   "LastQueryTime" => "2022-03-28T18:49:05.9272430",
   "LongTotalResults" => 1,
   "NodeTag" => "A",
   "ResultEtag" => -4402181509807245325,
   "Results" => [
     %{
       "@metadata" => %{
         "@change-vector" => "A:264-vzsRp yZT0GDkS5GJY/pAQ",
         "@id" => "cat/1",
         "@index-score" => 5.330733299255371,
         "@last-modified" => "2022-03-28T15:01:45.6545514Z"
       },
       "cat_name" => "Adolfus",
       "id" => "cat/1"
     }
   ],
   "SkippedResults" => 0,
   "TotalResults" => 1
 }}

Raw Query

iex(13)> raw("from @all_docs where cat_name = \"Adolfus\"") |> list_all(session_id)
{:ok,
 %{
   "DurationInMs" => 1,
   "IncludedPaths" => nil,
   "Includes" => %{},
   "IndexName" => "Auto/AllDocs/Bycat_nameAndid",
   "IndexTimestamp" => "2022-03-28T18:39:58.7637789",
   "IsStale" => false,
   "LastQueryTime" => "2022-03-28T18:53:27.4689173",
   "LongTotalResults" => 1,
   "NodeTag" => "A",
   "ResultEtag" => -4402181509807245325,
   "Results" => [
     %{
       "@metadata" => %{
         "@change-vector" => "A:264-vzsRp yZT0GDkS5GJY/pAQ",
         "@id" => "cat/1",
         "@index-score" => 5.330733299255371,
         "@last-modified" => "2022-03-28T15:01:45.6545514Z"
       },
       "cat_name" => "Adolfus",
       "id" => "cat/1"
     }
   ],
   "SkippedResults" => 0,
   "TotalResults" => 1
 }}

Collections

RavenDB can organize the documents in collections, Ravix will automatically insert the document in a collection if you use the Ravix. Document macro. If you don't want to use the macro, your struct just need to have the :@metadata field.

defmodule Ravix.SampleModel.Cat do
  use Ravix.Document, fields: [:id, :name, :breed]
end

Secure Server

To connect to a secure server, you can just inform the SSL certificates based on the erlang ssl configs to Finch itself.

E.g:

{Finch, name: Ravix.Finch,
    pools: %{
      default: [
        conn_opts: [
          transport_opts: [
            cert: DER_CERT,
            key: DER_KEY
          ]
        ]
      ]
    }
},

Ecto

What about querying your RavenDB using Ecto? Ravix-Ecto

Current State

  • Configuration Reading
  • Session Management
  • Request Executors
  • Unsafe Server Connection
  • Authenticated Server Connection
  • Create Document
  • Delete Document
  • Load Document
  • Queries Engine
  • Clustering
  • Topology Updates
  • Counters
  • Timeseries
  • Asynchronous Subscriptions
  • Attachments

The driver is working for the basic operations, clustering and resiliency are also implemented.

About

Ravix is an Elixir Client for the amazing RavenDB

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

No packages published

Languages