Public API

The Raijin database listens on TCP port 2500 for incoming HTTP requests. A GET request will retrieve the built-in web UI.

API query structure

A POST request sent with the following structure will execute a query:

{
  "query": "QUERY_STRING"
}

The QUERY_STRING may contain any number or combination of supported SQL queries (SELECT, INSERT, etc.), each terminated with a semicolon (;), with the entire set of queries enclosed in double quotes (" ").

Direct JSON ingestion API

A POST request to RAIJIN_SRV:RAIJIN_PORT/DB_NAME/TABLE_NAME with a series, or an array, of single-object JSON documents will insert data into the specified table. Both the database identified by DB_NAME and the table identified by TABLE_NAME must already exist.

The response indicates the number of records successfully ingested.

{"copy":4}

Malformed POST data will return an HTTP 400 status code. See Error handling for further details.

NDJSON

JSON objects are often saved to file or streamed over the network as NDJSON (newline-delimited JSON). NDJSON data can be POSTed to Rajin as is for ingestion as seen here.

Example 1. Inserting multiple flat JSON objects in NDJSON format
$ curl -sS raijin.example.com:2500/logs/demo -d '{"field1":-3.2,"field2":false}
{"field1":5.671,"field2":true}
{"hostname":"g01c335n2027","os":"Windows","active":1}
{"hostname":"g01c335n2028","os":"Linux","active":0}
'

Array of flat JSON objects

Some applications natively use and output data as JavaScript arrays of JSON objects. Such applications can POST their data directly to Raijin without additional formatting.

Example 2. Inserting an array of flat JSON objects
$ curl -sS raijin.example.com:2500/logs/demo -d '[{"field1":-3.2,"field2":false},{"field1":5.671,"field2":true},{"hostname":"g01c335n2027","os":"Windows","active":1},{"hostname":"g01c335n2028","os":"Linux","active":0}]'

Querying Raijin

The following examples use the API query structure for querying Raijin.

Database administration

Like most SQL-capable database engines, Raijin accepts standard SQL queries for administering databases and tables.

Example 3. Create a new table

In this example, a new, schemaless table called demo is created.

curl -sS raijin.example.com:2500 -d '{"query":"USE logs; CREATE TABLE demo();"}'
Example 4. Verify table creation
$ curl -sS raijin.example.com:2500 -d '{"query":"USE logs; SHOW TABLES;"}'
Result
{"table":"demo","record_count":"14","encrypted":"no","partitioning_type":"none","size":"71 bytes"}

Querying for data

Data queries must reference existing tables and the database they belong to. If DB_NAME is not specified in the FROM clause as FROM DB_NAME.TABLE_NAME, then the SQL query needs to be prefixed with USE DB_NAME;.

Example 5. USE DB_NAME
curl -sS raijin.example.com:2500 -d '{"query":"USE logs; SELECT * FROM demo;"}'
Result
{"_id":4311,"field1":-3.2,"field2":false}
{"_id":4312,"field1":5.671,"field2":true}
{"_id":4313,"hostname":"g01c335n2027","os":"Windows","active":1}
{"_id":4314,"hostname":"g01c335n2028","os":"Linux","active":0}
Example 6. FROM DB_NAME.TABLE_NAME
curl -sS raijin.example.com:2500 -d '{"query":"SELECT * FROM logs.demo;"}'
Result
{"_id":4311,"field1":-3.2,"field2":false}
{"_id":4312,"field1":5.671,"field2":true}
{"_id":4313,"hostname":"g01c335n2027","os":"Windows","active":1}
{"_id":4314,"hostname":"g01c335n2028","os":"Linux","active":0}
Example 7. Table-independent queries

For queries that involve only constants or functions, i.e., queries tha do not require a FROM clause, there is no need to reference a DB_NAME or TABLE_NAME.

$ curl -sS raijin.example.com:2500 -d '{"query":"SELECT pi(),ln(2.718281828)"}'
Result
{"pi":3.141593,"ln":1}
curl -sS raijin.example.com:2500 -d '{"query":"SELECT QUARTER(NOW()),YEAR(NOW())"}'
Result
{"quarter":2,"year":2022}

Error handling

Example 8. Invalid SQL statements

Raijin will return a HTTP 400 status code and a JSON-formatted response for invalid SQL statements.

$ curl -sv raijin.example.com:2500 -d '{"query":"selert 1 as one;"}' | jq
*   Trying 192.168.1.60:2500...
* Connected to raijin.example.com (192.168.1.60) port 2500 (#0)
> POST / HTTP/1.1
> Host: raijin.example.com:2500
> User-Agent: curl/7.77.0
> Accept: */*
> Content-Length: 28
> Content-Type: application/x-www-form-urlencoded
>
} [28 bytes data]
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request (1)
< Content-Length: 157
< Content-Type: text/html
<
{ [157 bytes data]
* Connection #0 to host raijin.example.com left intact
{
  "raijin-exception": {
    "parser-location": "http:1:1: ",
    "tag_reason": "syntax error at or near \"selert\"", (2)
    "where": "scan.cc:9246",
    "error_code": "16801924"
  }
}
1 HTTP 400 status code
2 tag_reason indicates that SELECT was misspelled as selert.
Example 9. Data ingestion with malformed JSON objects

The response indicates the number of records successfully ingested. In case of ingestion errors, the API will respond with HTTP 200 and the number of successfully ingested records.

 $ curl -sv raijin.example.com:2500/logs/demo -d '{"field1":-3.2,"field2":false}
> {"field1":5.671,"field2":true}
> {"hostname":"g01c335n2027","os":"Windows",active:1} (1)
> {"hostname":"g01c335n2028","os":"Linux","active":0} (2)
> '
*   Trying 192.168.1.60:2500...
* Connected to raijin.example.com (192.168.1.60) port 2500 (#0)
> POST /logs/demo HTTP/1.1
> Host: raijin.example.com:2500
> User-Agent: curl/7.77.0
> Accept: */*
> Content-Length: 166
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK (3)
< Transfer-Encoding: chunked
< Content-Type: text/json
<
{"copy":3} (4)
* Connection #0 to host raijin.example.com left intact
1 This object violates JSON syntax by not enclosing the active key in double quotes (" ") and was not ingested.
2 This object has valid JSON syntax and was ingested.
3 HTTP 200 OK
4 This shows that 3 of the 4 records were ingested.
Result
{"_id":1,"field1":-3.2,"field2":false}
{"_id":2,"field1":5.671,"field2":true}
{"_id":3,"hostname":"g01c335n2028","os":"Linux","active":0}