• Stars
    star
    498
  • Rank 88,471 (Top 2 %)
  • Language
    Elixir
  • License
    MIT License
  • Created over 9 years ago
  • Updated almost 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Rethinkdb client in pure elixir (JSON protocol)

RethinkDB Build Status

UPDATE: I am not actively developing this.

Multiplexed RethinkDB client in pure Elixir.

If you are coming here from elixir-rethinkdb, welcome! If you were expecting Exrethinkdb you are in the right place. We decided to change the name to just RethinkDB and the repo to rethinkdb-elixir. Sorry if it has caused confusion. Better now in the early stages than later!

I just set up a channel on the Elixir slack, so if you are on there join #rethinkdb.

Recent changes

0.4.0

  • Extract Changefeed out into separate package
  • Accept keyword options with queries

Getting Started

See API documentation for more details.

Connection

Connections are managed by a process. Start the process by calling start_link/1. See documentation for Connection.start_link/1 for supported options.

Basic Remote Connection

{:ok, conn} = RethinkDB.Connection.start_link([host: "10.0.0.17", port: 28015])

Named Connection

{:ok, conn} = RethinkDB.Connection.start_link([name: :foo])

Supervised Connection

Start the supervisor with:

worker(RethinkDB.Connection, [[name: :foo]])
worker(RethinkDB.Connection, [[name: :bar, host: 'localhost', port: 28015]])

Default Connection

An RethinkDB.Connection does parallel queries via pipelining. It can and should be shared among multiple processes. Because of this, it is common to have one connection shared in your application. To create a default connection, we create a new module and use RethinkDB.Connection.

defmodule FooDatabase do
  use RethinkDB.Connection
end

This connection can be supervised without a name (it will assume the module as the name).

worker(FooDatabase, [])

Queries can be run without providing a connection (it will use the name connection).

import RethinkDB.Query
table("people") |> FooDatabase.run

Connection Pooling

To use a connection pool, add Poolboy to your dependencies:

{:poolboy, "~> 1.5"}

Then, in your supervision tree, add:

worker(:poolboy, [[name: {:local, :rethinkdb_pool}, worker_module: RethinkDB.Connection, size: 10, max_overflow: 0], [])

NOTE: If you want to use changefeeds or any persistent queries, max_overflow: 0 is required.

Then use it in your code:

db = :poolboy.checkout(:rethinkdb_pool)
table("people") |> db
:poolboy.checkin(:rethinkdb_pool, db)

Query

RethinkDB.run/2 accepts a process as the second argument (to facilitate piping).

Insert

q = Query.table("people")
  |> Query.insert(%{first_name: "John", last_name: "Smith"})
  |> RethinkDB.run conn

Filter

q = Query.table("people")
  |> Query.filter(%{last_name: "Smith"})
  |> RethinkDB.run conn

Functions

RethinkDB supports RethinkDB functions in queries. There are two approaches you can take:

Use RethinkDB operators

import RethinkDB.Query

make_array([1,2,3]) |> map(fn (x) -> add(x, 1) end)

Use Elixir operators via the lambda macro

require RethinkDB.Lambda
import RethinkDB.Lambda

make_array([1,2,3]) |> map(lambda fn (x) -> x + 1 end)

Map

require RethinkDB.Lambda
import Query
import RethinkDB.Lambda

conn = RethinkDB.connect

table("people")
  |> has_fields(["first_name", "last_name"])
  |> map(lambda fn (person) ->
    person[:first_name] + " " + person[:last_name]
  end) |> RethinkDB.run conn

See query.ex for more basic queries. If you don't see something supported, please open an issue. We're moving fast and any guidance on desired features is helpful.

Indexes

# Simple indexes
# create
result = Query.table("people")
  |> Query.index_create("first_name", Lambda.lambda fn(row) -> row["first_name"] end)
  |> RethinkDB.run conn

# retrieve
result = Query.table("people")
  |> Query.get_all(["Will"], index: "first_name")
  |> RethinkDB.run conn


# Compound indexes
# create
result = Query.table("people")
  |> Query.index_create("full_name", Lambda.lambda fn(row) -> [row["first_name"], row["last_name"]] end)
  |> RethinkDB.run conn

# retrieve
result = Query.table("people")
  |> Query.get_all([["Will", "Smith"], ["James", "Bond"]], index: "full_name")
  |> RethinkDB.run conn

One limitation we have in Elixir is that we don't support varargs. So in JavaScript you would do getAll(key1, key2, {index: "uniqueness"}). In Elixir we have to do get_all([key1, key2], index: "uniqueness"). With a single key it becomes get_all([key1], index: "uniqueness") and when key1 is [partA, partB] you have to do get_all([[partA, partB]], index: "uniqueness")

Changes

Change feeds can be consumed either incrementally (by calling RethinkDB.next/1) or via the Enumerable Protocol.

results = Query.table("people")
  |> Query.filter(%{last_name: "Smith"})
  |> Query.changes
  |> RethinkDB.run conn
# get one result
first_change = RethinkDB.next results
# get stream, chunked in groups of 5, Inspect
results |> Stream.chunk(5) |> Enum.each &IO.inspect/1

Supervised Changefeeds

Supervised Changefeeds (an OTP behavior for running a changefeed as a process) have been moved to their own repo to enable independent release cycles. See https://github.com/hamiltop/rethinkdb_changefeed

Roadmap

Version 1.0.0 will be limited to individual connections and implement the entire documented ReQL (as of rethinkdb 2.0)

While not provided by this library, we will also include example code for:

  • Connection Pooling

The goal for 1.0.0 is to be stable. Issues have been filed for work that needs to be completed before 1.0.0 and tagged with the 1.0.0 milestone.

Example Apps

Checkout the wiki page for various example apps

Contributing

Contributions are welcome. Take a look at the Issues. Anything that is tagged Help Wanted or Feedback Wanted is a good candidate for contributions. Even if you don't know where to start, respond to an interesting issue and you will be pointed in the right direction.

Testing

Be intentional. Whether you are writing production code or tests, make sure there is value in the test being written.

More Repositories

1

MongoLiteDB

An embeddable file based Mongo compatible database. Think SQLite for NoSQL.
Ruby
90
star
2

rethinkdb_changefeed

Supervised Changefeeds for RethinkDB and Elixir
Elixir
30
star
3

rethinkdb_ecto

Shim library for using Ecto with RethinkDB. Not a full adapter.
Elixir
24
star
4

streamz

Elixir Streams and Utilities for Streaming.
Elixir
24
star
5

structurez

A playground for data structures in Elixir
Elixir
13
star
6

reduce_comprehensions

Reduce comprehensions for Elixir
Elixir
5
star
7

friends-demo

Demo of RethinkDB Elixir Change Feeds
Elixir
5
star
8

flaky_connection

A TCP proxy that allows you to drop connections at will. Useful for testing network libraries.
Elixir
4
star
9

personal_twitter_bot

A twitter bot with a web UI. Built on the REEP stack (RethinkDB Elixir Elm Phoenix).
Elixir
4
star
10

RaphaelBackboneDemo

A quick demo of RapahelBackbone
Ruby
3
star
11

Rails-Jquery-Sass-Haml-Drag-n-Drop-Demo

A demo of how to do drag and drop ajax calls with Rails/Sass/Haml
Ruby
3
star
12

systemex

System monitoring tool written in Elixir
Elixir
2
star
13

artos

A Real Time Operating System for Arduino
Java
2
star
14

RailsTutorial

Rails Tutorial
Ruby
1
star
15

draftex

Script for fantasy football draft
Elixir
1
star
16

Be-Kind

A javascript and rails solution to replaying mouse movements
Ruby
1
star
17

ashes

A Phoenix server for building and packaging Elixir applications
Elixir
1
star
18

Ourtoss

An RTOS written for the 8086. Not currently fit for hardware, but tested in an emulator.
C
1
star
19

MealTracker

A meal tracker that calculates the ingredient cost on a per meal basis
Python
1
star
20

sharpened_saw

A collection of elixir exercises for learning functional programming
Elixir
1
star
21

Contraction-Timer

A simple CLI timer for pregency contractions.
Python
1
star