This is work in progress and not functional as of now. If you want to help, please drop me a message. Any help is greatly appreciated!
ExDgraph is a gRPC based client for the Dgraph database. It uses the DBConnection behaviour to support transactions and connection pooling via Poolboy.
WORK IN PROGRESS.
Dgraph is an open source, horizontally scalable and distributed graph database, providing ACID transactions, consistent replication and linearizable reads. [...] Dgraph's goal is to provide Google production level scale and throughput, with low enough latency to be serving real time user queries, over terabytes of structured data. (Source)
If you want to learn more about Dgraph watch this talk.
This is under development and contributions are very welcome. Please add a comment under this issue to discuss how to help. Please also read the roadmap at the bottom of this Readme to see where I stand and what the next steps are.
A good start would be to improve test coverage. Run mix coveralls to see where work is needed.
- Performance and stability first
- Work as closely to GraphQL+ as possible
- Keep it simple and allow a maximum of flexibility for the user while providing enough syntactic sugar to make it simple to use. Also for people new to Dgraph
Add the package ex_dgraph to your list of dependencies in mix.exs:
def deps do
[
{:ex_dgraph, "~> 0.1.0", github: "ospaarmann/exdgraph", branch: "master"}
]
endAnd add the application to your list of applications in mix.exs:
def application do
[
applications: [
:ex_dgraph
]
]
endAgain, this is work in progress. I'll add more examples on how to use this on the go. So far you can connect to a server and run a simple query. I recommend installing and running Dgraph locally with Docker. You find information on how to do that here. To use this simple example you first have to import the example data. You can just open http://localhost:8000 in your browser when Dgraph is running to execute and visualize queries using Ratel.
At the moment simple queries, mutations and operations are supported via the DBConnection behaviour. Everything else is done directly via the Protobuf API. This will change. Check the tests for examples.
Example for a query
query = """
{
starwars(func: anyofterms(name, "VI"))
{
uid
name
release_date
starring
{
name
}
}
}
"""
conn = ExDgraph.conn()
{:ok, msg} = ExDgraph.query(conn, query)Examples for a mutation
starwars_schema = "id: string @index(exact).
name: string @index(exact, term) @count .
age: int @index(int) .
friend: uid @count .
dob: dateTime ."
starwars_creation_mutation = """
_:luke <name> "Luke Skywalker" .
_:leia <name> "Princess Leia" .
_:han <name> "Han Solo" .
_:lucas <name> "George Lucas" .
_:irvin <name> "Irvin Kernshner" .
_:richard <name> "Richard Marquand" .
_:sw1 <name> "Star Wars: Episode IV - A New Hope" .
_:sw1 <release_date> "1977-05-25" .
_:sw1 <revenue> "775000000" .
_:sw1 <running_time> "121" .
_:sw1 <starring> _:luke .
_:sw1 <starring> _:leia .
_:sw1 <starring> _:han .
_:sw1 <director> _:lucas .
_:sw2 <name> "Star Wars: Episode V - The Empire Strikes Back" .
_:sw2 <release_date> "1980-05-21" .
_:sw2 <revenue> "534000000" .
_:sw2 <running_time> "124" .
_:sw2 <starring> _:luke .
_:sw2 <starring> _:leia .
_:sw2 <starring> _:han .
_:sw2 <director> _:irvin .
_:sw3 <name> "Star Wars: Episode VI - Return of the Jedi" .
_:sw3 <release_date> "1983-05-25" .
_:sw3 <revenue> "572000000" .
_:sw3 <running_time> "131" .
_:sw3 <starring> _:luke .
_:sw3 <starring> _:leia .
_:sw3 <starring> _:han .
_:sw3 <director> _:richard .
_:st1 <name> "Star Trek: The Motion Picture" .
_:st1 <release_date> "1979-12-07" .
_:st1 <revenue> "139000000" .
_:st1 <running_time> "132" .
"""
conn = ExDgraph.conn()
{:ok, operation_msg} = ExDgraph.operation(conn, %{schema: starwars_schema})
{:ok, mutation_msg} = ExDgraph.mutation(conn, starwars_creation_mutation)Examples for an operation
# Connect
conn = ExDgraph.conn()
# Drop all entries from the database
ExDgraph.operation(conn, %{drop_all: true})
# Create schema
@testing_schema "id: string @index(exact).
name: string @index(exact, term) @count .
age: int @index(int) .
friend: uid @count .
dob: dateTime ."
# Run operation
ExDgraph.operation(conn, %{schema: @testing_schema})Example for a raw query
# Connect to Server
{:ok, channel} = GRPC.Stub.connect("#localhost:9080")
# Define query (for now just a string)
query = """
{
starwars(func: anyofterms(name, "VI"))
{
uid
name
release_date
starring
{
name
}
}
}
"""
# Build request
request = ExDgraph.Api.Request.new(query: query)
# Send request to server
{:ok, msg} = channel |> ExDgraph.Api.Dgraph.Stub.query(request)
# Parse result
json = Poison.decode!(msg.json)You need Dgraph running locally on port 9080. A quick way of running any version of Dgraph, is via Docker:
$ git clone git@github.com:ospaarmann/exdgraph.git
$ cd exdgraph
$ docker-compose up
$ mix test
More info on how to run Dgraph locally.
- Connect to Dgraph server via gRPC
- Implement DBConnection behaviour
- Improve test coverage
- Add documenation
- Improve error handling
- Implement TLS / authentication
- Improve request model via specific module
- Improve response model via specific module
- Query builder
- Query executer
- Mutations
- Operations
- More intelligent query builder for nested queries
- Read more on Dgraph here: https://docs.dgraph.io
- Read more on gRPC here: https://grpc.io/docs/
- Read more on Google Protobuf here: https://developers.google.com/protocol-buffers/
- Read more on DBConnection here: https://hexdocs.pm/db_connection/DBConnection.html
I am using tony612/grpc-elixir as Elixir gRPC implementation and tony612/protobuf-elixir as pure Elixir implementation of Google Protobuf.
Copyright © 2018 Ole Spaarmann os@ospaarmann.com
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.