Add initial documentation
This commit is contained in:
parent
d74af9681e
commit
6f1f39226f
4 changed files with 398 additions and 0 deletions
110
docs/ENDPOINTS.md
Normal file
110
docs/ENDPOINTS.md
Normal file
|
@ -0,0 +1,110 @@
|
|||
# Endpoints
|
||||
|
||||
This document describes RESTful http endpoints which can be used to query and manipulate the database.
|
||||
|
||||
---
|
||||
|
||||
### SQL
|
||||
|
||||
*Endpoints*
|
||||
- `POST` `https://api.surreal.io/sql` Execute SQL contained in HTTP body
|
||||
|
||||
---
|
||||
|
||||
### Tables
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}`
|
||||
|
||||
*Retrieve*
|
||||
- `SCAN` `/surreal/{id}/{db}/{table}/` `/surreal/{id}/{db}/{table}/~`
|
||||
|
||||
*Endpoints*
|
||||
- `GET` `https://api.surreal.io/{table}` SELECT * FROM {table}
|
||||
- `POST` `https://api.surreal.io/{table}` INSERT INTO {table}
|
||||
- `DEL` `https://api.surreal.io/{table}` DELETE FROM {table}
|
||||
|
||||
---
|
||||
|
||||
### Records
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}/{key}`
|
||||
|
||||
*Retrieve*
|
||||
- `GET` `/surreal/{id}/{db}/{table}/{key}`
|
||||
|
||||
*Endpoints*
|
||||
- `GET` `https://api.surreal.io/{table}/{key}` SELECT * FROM @{table}:{id}
|
||||
- `PUT` `https://api.surreal.io/{table}/{key}` UPDATE @{table}:{id} CONTENT {}
|
||||
- `POST` `https://api.surreal.io/{table}/{key}` CREATE @{table}:{id} CONTENT {}
|
||||
- `PATCH` `https://api.surreal.io/{table}/{key}` MODIFY @{table}:{id} CONTENT {}
|
||||
- `TRACE` `https://api.surreal.io/{table}/{key}` SELECT HISTORY FROM @{table}:{id}
|
||||
- `DEL` `https://api.surreal.io/{table}/{key}` DELETE @{table}:{id}
|
||||
|
||||
---
|
||||
|
||||
### History
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}/•/{key}/{time}`
|
||||
|
||||
*Retrieve*
|
||||
- `SCAN` `/surreal/{id}/{db}/{table}/•/{key}/` `/surreal/{id}/{db}/{table}/•/{key}/~`
|
||||
|
||||
*Endpoints*
|
||||
- `GET` `https://api.surreal.io/{table}/{key}?time={time}` SELECT record as it looked at {time}
|
||||
|
||||
---
|
||||
|
||||
### Joins
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}/†/{key}/{type}/{foreignkey}`
|
||||
|
||||
*Retrieve*
|
||||
- `SCAN` `/surreal/{id}/{db}/{table}/†/{key}/{type}/` `/surreal/{id}/{db}/{table}/†/{key}/{type}/~`
|
||||
|
||||
*Endpoints*
|
||||
- `PUT` `https://api.surreal.io/{table}/{key}/join/{type}` CREATE (in|out) join of {type}
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/join/{type}` SELECT (in|out|inout) joins of {type}
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/join/{type}/{joinkey}` SELECT (in|out) join of {type} with id {joinkey}
|
||||
- `DEL` `https://api.surreal.io/{table}/{key}/join/{type}/{joinkey}` DELETE (in|out) join of {type} with id {joinkey}
|
||||
|
||||
---
|
||||
|
||||
### Relations
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}/(«|»)/{key}/{type}/{foreignkey}`
|
||||
|
||||
*Retrieve*
|
||||
- `SCAN` `/surreal/{id}/{db}/{table}/(«|»)/{key}/{type}/` `/surreal/{id}/{db}/{table}/(«|»)/{key}/{type}/~`
|
||||
|
||||
*Endpoints*
|
||||
- `POST` `https://api.surreal.io/{table}/{key}/(in|out)/{type}/{vertexkey}` CREATE (in|out) relationship of {type} to {vertexkey}
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/(in|out|inout)/{type}` SELECT (in|out|inout) relationships of {type}
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/(in|out)/{type}/{edgekey}` SELECT (in|out) relationship of {type} with id {edgekey}
|
||||
- `DEL` `https://api.surreal.io/{table}/{key}/(in|out)/{type}/{edgekey}` DELETE (in|out) relationship of {type} with id {edgekey}
|
||||
|
||||
---
|
||||
|
||||
### Events
|
||||
|
||||
*Storage*
|
||||
- `/surreal/{id}/{db}/{table}/‡/{key}/{type}/{time}`
|
||||
|
||||
*Retrieve*
|
||||
- `SCAN` `/surreal/{id}/{db}/{table}/‡/{key}/{type}/` `/surreal/{id}/{db}/{table}/‡/{key}/{type}/~`
|
||||
|
||||
*Endpoints*
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/events/{type}` SELECT events('login') ON @{table}:{id}
|
||||
- `POST` `https://api.surreal.io/{table}/{key}/events/{type}` CREATE EVENT login ON @{table}:{id} WITH CONTENT {}
|
||||
- `GET` `https://api.surreal.io/{table}/{key}/events/{type}/{time}` SELECT events('login') ON @{table}:{id} WHERE time={time}
|
||||
- `POST` `https://api.surreal.io/{table}/{key}/events/{type}/{time}` CREATE EVENT login ON @{table}:{id} WITH CONTENT {} AT TIME {time}
|
||||
- `DEL` `https://api.surreal.io/{table}/{key}/events/{type}/{time}` DELETE events('login') ON @{table}:{id} WHERE time={time}
|
||||
|
||||
---
|
||||
|
||||
### Search
|
||||
- `GET` `https://api.surreal.io/search` Select all records in table
|
144
docs/QUERIES.md
Normal file
144
docs/QUERIES.md
Normal file
|
@ -0,0 +1,144 @@
|
|||
# Queries
|
||||
|
||||
This document describes example SQL queries which can be used to query the database.
|
||||
|
||||
### CREATE
|
||||
|
||||
```sql
|
||||
CREATE person SET age=28, name='Tobie'
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE @person:id /* Ensures record is blank */
|
||||
CREATE @person:id SET age = 28, name = 'Tobie' /* ... and sets name+age */
|
||||
CREATE @person:id SET age = 28, name = 'Tobie', tags = [] /* ... and sets `tags` to an empty set */
|
||||
CREATE @person:id SET age = 28, name = 'Tobie', tags = ['old'] /* ... and sets `tags` to a set with 1 element */
|
||||
```
|
||||
|
||||
### UPDATE
|
||||
|
||||
```sql
|
||||
UPDATE person SET age=EMPTY
|
||||
UPDATE person SET age=EMPTY WHERE age < 18
|
||||
```
|
||||
|
||||
```sql
|
||||
UPDATE @person:id /* Ensures record exists */
|
||||
UPDATE @person:id SET age = 28, name = 'Tobie' /* ... and sets name+age */
|
||||
UPDATE @person:id SET age = 28, name = 'Tobie', tags = NULL /* ... and sets `tags` to NULL */
|
||||
UPDATE @person:id SET age = 28, name = 'Tobie', tags = [] /* ... and sets `tags` to an empty set */
|
||||
UPDATE @person:id SET age = 28, name = 'Tobie', tags = ['old'] /* ... and sets `tags` to a set with 1 element */
|
||||
UPDATE @person:id SET age = 28, name = 'Tobie', tags += ['new'], tags -= ['old'] /* ... and adds 'new' to `tags` and removes 'old' from `tags */
|
||||
```
|
||||
|
||||
### MODIFY
|
||||
|
||||
```sql
|
||||
MODIFY @person:id WITH {JSON}
|
||||
```
|
||||
|
||||
### RELATE
|
||||
|
||||
```sql
|
||||
RELATE friend FROM @person:one TO @person:two
|
||||
```
|
||||
|
||||
### DELETE
|
||||
|
||||
```sql
|
||||
DELETE person WHERE age < 18
|
||||
```
|
||||
|
||||
```sql
|
||||
DELETE @person:one, @person:two
|
||||
```
|
||||
|
||||
### SELECT
|
||||
|
||||
```sql
|
||||
SELECT FROM VIEW adults ON PERSON
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT * FROM person
|
||||
SELECT *, both() FROM person
|
||||
SELECT *, in(), out() FROM person
|
||||
SELECT * FROM person WHERE account = 'abcum' ORDER BY (account, firstname, lastname)
|
||||
SELECT mean(value) FROM cpu
|
||||
SELECT mean(value)
|
||||
SELECT mean(value) from cpu WHERE host = 'serverA' AND time > now() - 4h GROUP BY time(5m)
|
||||
|
||||
SELECT ALL FROM person WHERE tags ∋ "tag"
|
||||
SELECT ALL FROM person WHERE tags.? = "tag"
|
||||
SELECT ALL FROM person WHERE "tag" IN tags
|
||||
SELECT ALL FROM person WHERE tags CONTAINS "tag"
|
||||
SELECT ALL FROM person WHERE tags.? IN ["tag1", "tag2"]
|
||||
SELECT ALL FROM person WHERE emails.?.value ~ "gmail.com" /* Any email address value matches 'gmail.com' */
|
||||
SELECT ALL FROM person WHERE emails.*.value ~ "gmail.com" /* Every email address value matches 'gmail.com' */
|
||||
|
||||
SELECT ALL FROM person WHERE tags ∌ "tag"
|
||||
SELECT ALL FROM person WHERE tags.* != "tag"
|
||||
SELECT ALL FROM person WHERE "tag" NOT IN tags
|
||||
SELECT ALL FROM person WHERE tags NOT CONTAINS "tag"
|
||||
SELECT ALL FROM person WHERE tags.* NOT IN ["tag1", "tag2"]
|
||||
|
||||
SELECT ALL FROM person WHERE tags IN ["tag1", "tag2", "tag3"]
|
||||
SELECT ALL FROM person WHERE "tag1" IN tags
|
||||
|
||||
SELECT *, :(friend|follow)/:person[age>=18,social=true] AS acquaintances FROM person WHERE acquaintances IN [@person:123]
|
||||
SELECT *, :(friend|follow)/:person[age>=18,social=true] AS acquaintances FROM person WHERE acquaintances.firstname IN ['Tobie']
|
||||
|
||||
```
|
||||
|
||||
### VIEWS
|
||||
|
||||
```sql
|
||||
DEFINE VIEW adults
|
||||
MAP
|
||||
`
|
||||
if (meta.table == 'person') {
|
||||
if (doc.firstname && doc.lastname) {
|
||||
emit([doc.lastname, doc.firstname, meta.id], null)
|
||||
}
|
||||
if (doc:friend(person):name == 'Tobie') {
|
||||
emit()
|
||||
}
|
||||
}
|
||||
`
|
||||
REDUCE
|
||||
`
|
||||
`
|
||||
```
|
||||
|
||||
```sql
|
||||
RESYNC VIEW adults
|
||||
```
|
||||
|
||||
```sql
|
||||
REMOVE VIEW adults
|
||||
```
|
||||
|
||||
### INDEX
|
||||
|
||||
```sql
|
||||
DEFINE INDEX name ON person COLUMNS lastname, firstname
|
||||
DEFINE INDEX name ON person COLUMNS lastname, firstname, emails.0.value
|
||||
DEFINE INDEX name ON person COLUMNS accounts, lastname, firstname, emails.0.value
|
||||
```
|
||||
|
||||
```sql
|
||||
RESYNC INDEX name ON person
|
||||
```
|
||||
|
||||
```sql
|
||||
REMOVE INDEX name ON person
|
||||
```
|
||||
|
||||
### FIELD
|
||||
|
||||
```sql
|
||||
DEFINE FIELD fullname ON person CODE `
|
||||
let email = doc.emails ? _(doc.emails).pluck('value').first() : null;
|
||||
return [doc.firstname, doc.middlename, doc.lastname, doc.username, email].filter(i => { return i }).join(' ');
|
||||
`
|
||||
```
|
22
docs/SECURITY.md
Normal file
22
docs/SECURITY.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Surreal
|
||||
|
||||
Surreal is a NoSQL Document and Graph database
|
||||
|
||||
---
|
||||
|
||||
### Authentication
|
||||
|
||||
- Accept connection on HTTP (RESTful)
|
||||
- Check JWT token
|
||||
- Get id from token *(account id)*
|
||||
- Get db from token *(database name)*
|
||||
- Check token against database `/surreal/{id}/{db}/!/tokens/{token}`
|
||||
- `HTTP 403` if token does not exist
|
||||
|
||||
|
||||
- Accept connection on HTTP (Websocket)
|
||||
- Check JWT token
|
||||
- Get id from token *(account id)*
|
||||
- Get db from token *(database name)*
|
||||
- Check token against database `/surreal/{id}/{db}/!/tokens/{token}`
|
||||
- `HTTP 403` if token does not exist
|
122
docs/STORAGE.md
Normal file
122
docs/STORAGE.md
Normal file
|
@ -0,0 +1,122 @@
|
|||
# Storage
|
||||
|
||||
Surreal can be used with any key-value storage which enables range scans. This document describes how the data is stored in the storage layer, so that it can be queried and manipulated quickly and efficiently.
|
||||
|
||||
**Base keys**
|
||||
|
||||
```bash
|
||||
{$base} = "surreal" # This is the base key
|
||||
```
|
||||
|
||||
The base key is used to separate the data used in SurrealDB from data used by other databases using the same key:value store.
|
||||
|
||||
```bash
|
||||
{$auth} = "abcum" # This is the name of the auth account
|
||||
```
|
||||
|
||||
The auth key is used to enable multi-tenancy of databases on SurrealDB. Each authenticated user is able to access databases underneath their own auth key only.
|
||||
|
||||
```bash
|
||||
{$db} = "database" # This is the name of the database
|
||||
```
|
||||
|
||||
The database key is used to separate data into multiple different databases under each multi-tenant installation.
|
||||
|
||||
**Unique ids**
|
||||
|
||||
Each view, table, and index is assigned a unique id, which is used instead of the name in each key:value pair. This allows for views, indexes, and tables to be deleted asynchronously, while at the same time a new one is created in its place with the same name.
|
||||
|
||||
**Data types**
|
||||
|
||||
Each data type is stored using a different symbol in the key:value pair.
|
||||
|
||||
```bash
|
||||
¤ # Used to store view and index data
|
||||
« # Used to store in edges
|
||||
» # Used to store out edges
|
||||
• # Used to store diffs to each record
|
||||
‡ # Used to store time-series data
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Table
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/!/tables/{$table} "{$tableid}"
|
||||
# e.g.
|
||||
/{$base}/{$auth}/{$db}/!/tables/people "1bd7ajq8"
|
||||
```
|
||||
|
||||
### Field
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/!/field/{$field} "{CODE}"
|
||||
# e.g.
|
||||
/{$base}/{$auth}/{$db}/1bd7ajq8/!/field/fullname "return doc.fname + doc.lname"
|
||||
```
|
||||
|
||||
### Items
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/{$id} ""
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/UUID `{"name":"Tobie","age":18}`
|
||||
```
|
||||
|
||||
*TRAIL*
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/•/{$id}/{$time} ""
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/•/UUID/2016-01-29T22:42:56.478173947Z ""
|
||||
```
|
||||
|
||||
*EVENT*
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/‡/{$id}/{$type}/{$time} ""
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/‡/UUID/login/2016-01-29T22:42:56.478173947Z ""
|
||||
```
|
||||
|
||||
*EDGES*
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/»/{$id}/{$type}/{$edgeid} ""
|
||||
/{$base}/{$auth}/{$db}/{$typeid}/{$id} ""
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/«/{$id}/{$type}/{$edgeid} ""
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/»/1537/follow/9563 ""
|
||||
/{$base}/{$auth}/{$db}/{$typeid}/9563 `{"in":"1537","out":"5295"}`
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/«/5295/follow/9563 ""
|
||||
```
|
||||
|
||||
### Views
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/!/views/{$view} "{$viewid}"
|
||||
# e.g.
|
||||
/{$base}/{$auth}/{$db}/!/views/test "9jh1ebj4"
|
||||
/{$base}/{$auth}/{$db}/!/views/test/map "emit()"
|
||||
/{$base}/{$auth}/{$db}/!/views/test/red "return count()"
|
||||
```
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/¤/{$viewid}/COLUMNS "{$id}"
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/¤/{$viewid}/[lastname,firstname] "@person:1342"
|
||||
```
|
||||
|
||||
### Index
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/!/index/{$index} "{$indexid}"
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/!/index/{$index}/col "COLUMNS"
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/!/index/names "5gbq3hm5"
|
||||
/{$base}/{$auth}/{$db}/1bd7ajq8/!/index/names/col "lastname|firstname|emails.0.value"
|
||||
```
|
||||
|
||||
```bash
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/¤/{$indexid}/COLUMNS "{$id}"
|
||||
# e.g
|
||||
/{$base}/{$auth}/{$db}/{$tableid}/¤/{$indexid}/[lastname,firstname] "@person:1342"
|
||||
```
|
Loading…
Reference in a new issue