Merge pull request #71 from kortschak/compress
Add transparent input decompression
This commit is contained in:
commit
984ab6fd25
8 changed files with 181 additions and 72 deletions
19
README.md
19
README.md
|
|
@ -1,7 +1,7 @@
|
|||
<p align="center">
|
||||
<img src="static/branding/cayley_side.png?raw=true" alt="Cayley" />
|
||||
</p>
|
||||
Cayley is an open-source graph inspired by the graph database behind [Freebase](http://freebase.com) and Google's [Knowledge Graph](http://www.google.com/insidesearch/features/search/knowledge.html).
|
||||
Cayley is an open-source graph inspired by the graph database behind [Freebase](http://freebase.com) and Google's [Knowledge Graph](http://www.google.com/insidesearch/features/search/knowledge.html).
|
||||
|
||||
Its goal is to be a part of the developer's toolbox where [Linked Data](http://linkeddata.org/) and graph-shaped data (semantic webs, social networks, etc) in general are concerned.
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ If you prefer to build from source, see the documentation on the wiki at [How to
|
|||
|
||||
`cd` to the directory and give it a quick test with:
|
||||
```
|
||||
./cayley repl --dbpath=testdata.nt
|
||||
./cayley repl --dbpath=testdata.nt
|
||||
```
|
||||
|
||||
You should see a `cayley>` REPL prompt. Go ahead and give it a try:
|
||||
|
|
@ -69,17 +69,16 @@ cayley> graph.Vertex("dani").Out("follows").All()
|
|||
|
||||
**Sample Data**
|
||||
|
||||
For somewhat more interesting data, a sample of 30k movies from Freebase comes in the checkout.
|
||||
For somewhat more interesting data, a sample of 30k movies from Freebase comes in the checkout.
|
||||
|
||||
```
|
||||
gzip -cd 30kmoviedata.nt.gz > 30kmovies.nt
|
||||
./cayley repl --dbpath=30kmovies.nt
|
||||
./cayley repl --dbpath=30kmoviedata.nt.gz
|
||||
```
|
||||
|
||||
To run the web frontend, replace the "repl" command with "http"
|
||||
To run the web frontend, replace the "repl" command with "http"
|
||||
|
||||
```
|
||||
./cayley http --dbpath=30kmovies.nt
|
||||
./cayley http --dbpath=30kmoviedata.nt.gz
|
||||
```
|
||||
|
||||
And visit port 64210 on your machine, commonly [http://localhost:64210](http://localhost:64210)
|
||||
|
|
@ -89,7 +88,7 @@ And visit port 64210 on your machine, commonly [http://localhost:64210](http://l
|
|||
|
||||
The default environment is based on [Gremlin](http://gremlindocs.com/) and is simply a JavaScript environment. If you can write jQuery, you can query a graph.
|
||||
|
||||
You'll notice we have a special object, `graph` or `g`, which is how you can interact with the graph.
|
||||
You'll notice we have a special object, `graph` or `g`, which is how you can interact with the graph.
|
||||
|
||||
The simplest query is merely to return a single vertex. Using the 30kmovies.nt dataset from above, let's walk through some simple queries:
|
||||
|
||||
|
|
@ -107,7 +106,7 @@ g.V("Humphrey Bogart").All()
|
|||
// Follow links that are pointing In to our "Humphrey Bogart" node with the predicate "name".
|
||||
g.V("Humphrey Bogart").In("name").All()
|
||||
|
||||
// Notice that "name" is a generic predicate in our dataset.
|
||||
// Notice that "name" is a generic predicate in our dataset.
|
||||
// Starting with a movie gives a similar effect.
|
||||
g.V("Casablanca").In("name").All()
|
||||
|
||||
|
|
@ -129,7 +128,7 @@ And these pipelines continue...
|
|||
g.V().Has("name","Casablanca")
|
||||
.Out("/film/film/starring").Out("/film/performance/actor")
|
||||
.Out("name").All()
|
||||
|
||||
|
||||
// But this is starting to get long. Let's use a morphism -- a pre-defined path stored in a variable -- as our linkage
|
||||
|
||||
var filmToActor = g.Morphism().Out("/film/film/starring").Out("/film/performance/actor")
|
||||
|
|
|
|||
37
db/load.go
37
db/load.go
|
|
@ -15,6 +15,10 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/bzip2"
|
||||
"compress/gzip"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/barakmich/glog"
|
||||
|
|
@ -54,7 +58,38 @@ func ReadTriplesFromFile(c chan *graph.Triple, tripleFile string) {
|
|||
}
|
||||
}()
|
||||
|
||||
nquads.ReadNQuadsFromReader(c, f)
|
||||
r, err := decompressor(f)
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
|
||||
nquads.ReadNQuadsFromReader(c, r)
|
||||
}
|
||||
|
||||
const (
|
||||
gzipMagic = "\x1f\x8b"
|
||||
b2zipMagic = "BZh"
|
||||
)
|
||||
|
||||
type readAtReader interface {
|
||||
io.Reader
|
||||
io.ReaderAt
|
||||
}
|
||||
|
||||
func decompressor(r readAtReader) (io.Reader, error) {
|
||||
var buf [3]byte
|
||||
_, err := r.ReadAt(buf[:], 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case bytes.Compare(buf[:2], []byte(gzipMagic)) == 0:
|
||||
return gzip.NewReader(r)
|
||||
case bytes.Compare(buf[:3], []byte(b2zipMagic)) == 0:
|
||||
return bzip2.NewReader(r), nil
|
||||
default:
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
|
||||
func LoadTriplesInto(tChan chan *graph.Triple, ts graph.TripleStore, loadSize int) {
|
||||
|
|
|
|||
81
db/load_test.go
Normal file
81
db/load_test.go
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/bzip2"
|
||||
"compress/gzip"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testDecompressor = []struct {
|
||||
message string
|
||||
input []byte
|
||||
expect []byte
|
||||
err error
|
||||
readErr error
|
||||
}{
|
||||
{
|
||||
message: "text input",
|
||||
input: []byte("cayley data\n"),
|
||||
err: nil,
|
||||
expect: []byte("cayley data\n"),
|
||||
readErr: nil,
|
||||
},
|
||||
{
|
||||
message: "gzip input",
|
||||
input: []byte{
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x5c, 0xbc, 0xcd, 0x53, 0x00, 0x03, 0x4b, 0x4e, 0xac, 0xcc, 0x49, 0xad,
|
||||
0x54, 0x48, 0x49, 0x2c, 0x49, 0xe4, 0x02, 0x00, 0x03, 0xe1, 0xfc, 0xc3, 0x0c, 0x00, 0x00, 0x00,
|
||||
},
|
||||
err: nil,
|
||||
expect: []byte("cayley data\n"),
|
||||
readErr: nil,
|
||||
},
|
||||
{
|
||||
message: "bzip2 input",
|
||||
input: []byte{
|
||||
0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59, 0xb5, 0x4b, 0xe3, 0xc4, 0x00, 0x00,
|
||||
0x02, 0xd1, 0x80, 0x00, 0x10, 0x40, 0x00, 0x2e, 0x04, 0x04, 0x20, 0x20, 0x00, 0x31, 0x06, 0x4c,
|
||||
0x41, 0x4c, 0x1e, 0xa7, 0xa9, 0x2a, 0x18, 0x26, 0xb1, 0xc2, 0xee, 0x48, 0xa7, 0x0a, 0x12, 0x16,
|
||||
0xa9, 0x7c, 0x78, 0x80,
|
||||
},
|
||||
err: nil,
|
||||
expect: []byte("cayley data\n"),
|
||||
readErr: nil,
|
||||
},
|
||||
{
|
||||
message: "bad gzip input",
|
||||
input: []byte{0x1f, 0x8b, 'c', 'a', 'y', 'l', 'e', 'y', ' ', 'd', 'a', 't', 'a', '\n'},
|
||||
err: gzip.ErrHeader,
|
||||
expect: nil,
|
||||
readErr: nil,
|
||||
},
|
||||
{
|
||||
message: "bad bzip2 input",
|
||||
input: []byte{0x42, 0x5a, 0x68, 'c', 'a', 'y', 'l', 'e', 'y', ' ', 'd', 'a', 't', 'a', '\n'},
|
||||
err: nil,
|
||||
expect: nil,
|
||||
readErr: bzip2.StructuralError("invalid compression level"),
|
||||
},
|
||||
}
|
||||
|
||||
func TestDecompressor(t *testing.T) {
|
||||
for _, test := range testDecompressor {
|
||||
buf := bytes.NewReader(test.input)
|
||||
r, err := decompressor(buf)
|
||||
if err != test.err {
|
||||
t.Fatalf("Unexpected error for %s, got:%v expect:%v", test.message, err, test.err)
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
p := make([]byte, len(test.expect)*2)
|
||||
n, err := r.Read(p)
|
||||
if err != test.readErr {
|
||||
t.Fatalf("Unexpected error for reading %s, got:%v expect:%v", test.message, err, test.err)
|
||||
}
|
||||
if bytes.Compare(p[:n], test.expect) != 0 {
|
||||
t.Errorf("Unexpected read result for %s, got:%q expect:%q", test.message, p[:n], test.expect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
## Overview
|
||||
|
||||
Cayley expects, in the usual case, to be run with a configuration file, though it can also be run purely through configuration flags. The configuration file contains a JSON object with any of the documented parameters.
|
||||
Cayley expects, in the usual case, to be run with a configuration file, though it can also be run purely through configuration flags. The configuration file contains a JSON object with any of the documented parameters.
|
||||
|
||||
Cayley looks in the following locations for the configuration file
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ All command line flags take precedence over the configuration file.
|
|||
* Type: String
|
||||
* Default: "64210"
|
||||
|
||||
The port for Cayley's HTTP server to listen on.
|
||||
The port for Cayley's HTTP server to listen on.
|
||||
|
||||
#### **`read_only`**
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ All command line flags take precedence over the configuration file.
|
|||
* Type: Integer
|
||||
* Default: 10000
|
||||
|
||||
The number of triples to buffer from a loaded file before writing a block of triples to the database. Larger numbers are good for larger loads.
|
||||
The number of triples to buffer from a loaded file before writing a block of triples to the database. Larger numbers are good for larger loads.
|
||||
|
||||
#### **`db_options`**
|
||||
|
||||
|
|
@ -77,7 +77,7 @@ All command line flags take precedence over the configuration file.
|
|||
* Type: Integer
|
||||
* Default: 30
|
||||
|
||||
The value in seconds of the maximum length of time the Javascript runtime should run until cancelling the query and returning a 408 Timeout. A negative value means no limit.
|
||||
The value in seconds of the maximum length of time the Javascript runtime should run until cancelling the query and returning a 408 Timeout. A negative value means no limit.
|
||||
|
||||
## Per-Database Options
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ The size in MiB of the LevelDB write cache. Increasing this number allows for mo
|
|||
#### **`cache_size_mb`**
|
||||
|
||||
* Type: Integer
|
||||
* Default: 2
|
||||
* Default: 2
|
||||
|
||||
The size in MiB of the LevelDB block cache. Increasing this number uses more memory to maintain a bigger cache of triple blocks for better performance.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
# Javascript/Gremlin API documentation
|
||||
|
||||
## The `graph` object
|
||||
## The `graph` object
|
||||
|
||||
Alias: `g`
|
||||
|
||||
This is the only special object in the environment, generates the query objects. Under the hood, they're simple objects that get compiled to a Go iterator tree when executed.
|
||||
This is the only special object in the environment, generates the query objects. Under the hood, they're simple objects that get compiled to a Go iterator tree when executed.
|
||||
|
||||
#### **`graph.Vertex([nodeId],[nodeId]...)`**
|
||||
#### **`graph.Vertex([nodeId],[nodeId]...)`**
|
||||
|
||||
Alias: `graph.V`
|
||||
|
||||
Arguments:
|
||||
|
||||
* `nodeId` (Optional): A string or list of strings representing the starting vertices.
|
||||
|
||||
|
||||
Returns: Query object
|
||||
|
||||
Starts a query path at the given vertex/verticies. No ids means "all vertices".
|
||||
|
||||
####**`graph.Morphism()`**
|
||||
####**`graph.Morphism()`**
|
||||
|
||||
Alias: `graph.M`
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ For these examples, suppose we have the following graph:
|
|||
+---+
|
||||
```
|
||||
|
||||
Where every link is a "follows" relationship, and the nodes with an extra `#` in the name have an extra `status` link. As in,
|
||||
Where every link is a "follows" relationship, and the nodes with an extra `#` in the name have an extra `status` link. As in,
|
||||
|
||||
```
|
||||
D -- status --> cool_person
|
||||
|
|
@ -75,7 +75,7 @@ Perhaps these are the influencers in our community.
|
|||
|
||||
Arguments:
|
||||
|
||||
* `predicatePath` (Optional): One of:
|
||||
* `predicatePath` (Optional): One of:
|
||||
* null or undefined: All predicates pointing out from this node
|
||||
* a string: The predicate name to follow out from this node
|
||||
* a list of strings: The predicates to follow out from this node
|
||||
|
|
@ -87,7 +87,7 @@ Arguments:
|
|||
|
||||
Out is the work-a-day way to get between nodes, in the forward direction. Starting with the nodes in `path` on the subject, follow the triples with predicates defined by `predicatePath` to their objects.
|
||||
|
||||
Example:
|
||||
Example:
|
||||
```javascript
|
||||
// The working set of this is B and D
|
||||
g.V("C").Out("follows")
|
||||
|
|
@ -95,10 +95,10 @@ g.V("C").Out("follows")
|
|||
g.V("A").Out("follows").Out("follows")
|
||||
// Finds all things D points at. Result is B G and cool_person
|
||||
g.V("D").Out()
|
||||
// Finds all things D points at on the status linkage.
|
||||
// Finds all things D points at on the status linkage.
|
||||
// Result is B G and cool_person
|
||||
g.V("D").Out(["follows", "status"])
|
||||
// Finds all things D points at on the status linkage, given from a seperate query path.
|
||||
// Finds all things D points at on the status linkage, given from a seperate query path.
|
||||
// Result is {"id": cool_person, "pred": "status"}
|
||||
g.V("D").Out(g.V("status"), "pred")
|
||||
```
|
||||
|
|
@ -107,7 +107,7 @@ g.V("D").Out(g.V("status"), "pred")
|
|||
|
||||
Arguments:
|
||||
|
||||
* `predicatePath` (Optional): One of:
|
||||
* `predicatePath` (Optional): One of:
|
||||
* null or undefined: All predicates pointing into this node
|
||||
* a string: The predicate name to follow into this node
|
||||
* a list of strings: The predicates to follow into this node
|
||||
|
|
@ -133,7 +133,7 @@ g.V("E").Out("follows").In("follows")
|
|||
|
||||
Arguments:
|
||||
|
||||
* `predicatePath` (Optional): One of:
|
||||
* `predicatePath` (Optional): One of:
|
||||
* null or undefined: All predicates pointing both into and out from this node
|
||||
* a string: The predicate name to follow both into and out from this node
|
||||
* a list of strings: The predicates to follow both into and out from this node
|
||||
|
|
@ -142,13 +142,13 @@ Arguments:
|
|||
* null or undefined: No tags
|
||||
* a string: A single tag to add the predicate used to the output set.
|
||||
* a list of strings: Multiple tags to use as keys to save the predicate used to the output set.
|
||||
Follow the predicate in either direction. Same as
|
||||
Follow the predicate in either direction. Same as
|
||||
|
||||
Note: Less efficient, for the moment, as it's implemented with an Or, but useful where necessary.
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
// Find all followers/followees of F. Returns B E and G
|
||||
// Find all followers/followees of F. Returns B E and G
|
||||
g.V("F").Both("follows")
|
||||
```
|
||||
|
||||
|
|
@ -159,11 +159,11 @@ Arguments:
|
|||
|
||||
* `node`: A string for a node. Can be repeated or a list of strings.
|
||||
|
||||
Filter all paths to ones which, at this point, are on the given `node`.
|
||||
Filter all paths to ones which, at this point, are on the given `node`.
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
// Starting from all nodes in the graph, find the paths that follow B.
|
||||
// Starting from all nodes in the graph, find the paths that follow B.
|
||||
// Results in three paths for B (from A C and D)
|
||||
g.V().Out("follows").Is("B")
|
||||
```
|
||||
|
|
@ -189,7 +189,7 @@ g.V("C").Out("follows").Has("follows", "F")
|
|||
|
||||
### Tagging
|
||||
|
||||
####**`path.Tag(tag)`**
|
||||
####**`path.Tag(tag)`**
|
||||
|
||||
Alias: `path.As`
|
||||
|
||||
|
|
@ -212,19 +212,19 @@ g.V().Tag("start").Out("status")
|
|||
|
||||
Arguments:
|
||||
|
||||
* `tag`: A previous tag in the query to jump back to.
|
||||
|
||||
* `tag`: A previous tag in the query to jump back to.
|
||||
|
||||
If still valid, a path will now consider their vertex to be the same one as the previously tagged one, with the added constraint that it was valid all the way here. Useful for traversing back in queries and taking another route for things that have matched so far.
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
// Start from all nodes, save them into start, follow any status links, jump back to the starting node, and find who follows them. Return the result.
|
||||
// Results are:
|
||||
// {"id": "A", "start": "B"},
|
||||
// {"id": "C", "start": "B"},
|
||||
// {"id": "D", "start": "B"},
|
||||
// Results are:
|
||||
// {"id": "A", "start": "B"},
|
||||
// {"id": "C", "start": "B"},
|
||||
// {"id": "D", "start": "B"},
|
||||
// {"id": "C", "start": "D"},
|
||||
// {"id": "D", "start": "G"}
|
||||
// {"id": "D", "start": "G"}
|
||||
g.V().Tag("start").Out("status").Back("start").In("follows")
|
||||
```
|
||||
|
||||
|
|
@ -249,7 +249,7 @@ g.V("D", "B").Save("follows", "target")
|
|||
|
||||
### Joining
|
||||
|
||||
####**`path.Intersect(query)`**
|
||||
####**`path.Intersect(query)`**
|
||||
|
||||
Alias: `path.And`
|
||||
|
||||
|
|
@ -269,7 +269,7 @@ cFollows.Intersect(dFollows)
|
|||
// Equivalently, g.V("C").Out("follows").And(g.V("D").Out("follows"))
|
||||
```
|
||||
|
||||
####**`path.Union(query)`**
|
||||
####**`path.Union(query)`**
|
||||
|
||||
Alias: `path.Or`
|
||||
|
||||
|
|
@ -298,10 +298,10 @@ Arguments:
|
|||
|
||||
* `morphism`: A morphism path to follow
|
||||
|
||||
With `graph.Morphism` we can prepare a path for later reuse. `Follow` is the way that's accomplished.
|
||||
With `graph.Morphism` we can prepare a path for later reuse. `Follow` is the way that's accomplished.
|
||||
Applies the path chain on the morphism object to the current path.
|
||||
|
||||
Starts as if at the g.M() and follows through the morphism path.
|
||||
Starts as if at the g.M() and follows through the morphism path.
|
||||
|
||||
Example:
|
||||
```javascript:
|
||||
|
|
@ -318,7 +318,7 @@ Arguments:
|
|||
|
||||
* `morphism`: A morphism path to follow
|
||||
|
||||
Same as `Follow` but follows the chain in the reverse direction. Flips "In" and "Out" where appropriate,
|
||||
Same as `Follow` but follows the chain in the reverse direction. Flips "In" and "Out" where appropriate,
|
||||
the net result being a virtual predicate followed in the reverse direction.
|
||||
|
||||
Starts at the end of the morphism and follows it backwards (with appropriate flipped directions) to the g.M() location.
|
||||
|
|
@ -346,10 +346,10 @@ Executes the query and adds the results, with all tags, as a string-to-string (t
|
|||
|
||||
####**`query.GetLimit(size)`**
|
||||
|
||||
Arguments:
|
||||
Arguments:
|
||||
|
||||
* `size`: An integer value on the first `size` paths to return.
|
||||
|
||||
|
||||
Returns: undefined
|
||||
|
||||
Same as all, but limited to the first `size` unique nodes at the end of the path, and each of their possible traversals.
|
||||
|
|
@ -360,7 +360,7 @@ Arguments: None
|
|||
|
||||
Returns: Array
|
||||
|
||||
Executes a query and returns the results at the end of the query path.
|
||||
Executes a query and returns the results at the end of the query path.
|
||||
Example:
|
||||
``javascript
|
||||
// fooNames contains an Array of names for foo.
|
||||
|
|
@ -399,15 +399,15 @@ Returns: A single string-to-string object
|
|||
As `.TagArray` above, but limited to one result node -- a string. Like `.Limit(1)` for the above case. Returns a tag-to-string map.
|
||||
|
||||
|
||||
####**`query.ForEach(callback), query.ForEach(limit, callback)`**
|
||||
####**`query.ForEach(callback), query.ForEach(limit, callback)`**
|
||||
|
||||
Alias: `query.Map`
|
||||
|
||||
Arguments:
|
||||
Arguments:
|
||||
|
||||
* `limit` (Optional): An integer value on the first `limit` paths to process.
|
||||
* `callback`: A javascript function of the form `function(data)`
|
||||
|
||||
|
||||
Returns: undefined
|
||||
|
||||
For each tag-to-string result retrieved, as in the `All` case, calls `callback(data)` where `data` is the tag-to-string map.
|
||||
|
|
|
|||
18
docs/HTTP.md
18
docs/HTTP.md
|
|
@ -8,17 +8,17 @@ Unless otherwise noted, all URIs take a POST command.
|
|||
|
||||
#### `/api/v1/query/gremlin`
|
||||
|
||||
POST Body: Javascript source code of the query
|
||||
POST Body: Javascript source code of the query
|
||||
|
||||
Response: JSON results, depending on the query.
|
||||
|
||||
#### `/api/v1/query/mql`
|
||||
|
||||
POST Body: JSON MQL query
|
||||
POST Body: JSON MQL query
|
||||
|
||||
Response: JSON results, with a query wrapper:
|
||||
```json
|
||||
{
|
||||
{
|
||||
"result": <JSON Result set>
|
||||
}
|
||||
```
|
||||
|
|
@ -39,15 +39,15 @@ Result form:
|
|||
```json
|
||||
{
|
||||
"nodes": [{
|
||||
"id" : integer,
|
||||
"tags": ["list of tags from the query"],
|
||||
"id" : integer,
|
||||
"tags": ["list of tags from the query"],
|
||||
"values": ["known values from the query"],
|
||||
"is_link_node": bool, // Does the node represent the link or the node (the oval shapes)
|
||||
"is_fixed": bool // Is the node a fixed starting point of the query
|
||||
}],
|
||||
}],
|
||||
|
||||
"links": [{
|
||||
"source": integer, // Node ID
|
||||
"source": integer, // Node ID
|
||||
"target": integer, // Node ID
|
||||
"link_node": integer // Node ID
|
||||
}]
|
||||
|
|
@ -56,13 +56,13 @@ Result form:
|
|||
|
||||
#### `/api/v1/shape/gremlin`
|
||||
|
||||
POST Body: Javascript source code of the query
|
||||
POST Body: Javascript source code of the query
|
||||
|
||||
Response: JSON description of the last query executed.
|
||||
|
||||
#### `/api/v1/shape/mql`
|
||||
|
||||
POST Body: JSON MQL query
|
||||
POST Body: JSON MQL query
|
||||
|
||||
Response: JSON description of the query.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ Every JSON Object can be thought of as a node in the graph, and wrapping an obje
|
|||
|
||||
Is equivalent to all nodes in the graph, where "id" is the special keyword for the value of the node.
|
||||
|
||||
Predicates are added to the object to specify constraints.
|
||||
Predicates are added to the object to specify constraints.
|
||||
|
||||
```json
|
||||
[{
|
||||
|
|
@ -66,7 +66,7 @@ JSON does not specify the behavior of objects with the same key. In order to hav
|
|||
|
||||
|
||||
```json
|
||||
[{
|
||||
[{
|
||||
"id": "A",
|
||||
"@x:some_predicate": "B",
|
||||
"@y:some_predicate": "C"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Overview
|
||||
|
||||
## Getting Started
|
||||
## Getting Started
|
||||
|
||||
This guide will take you through starting a persistent graph based on the provided data, with some hints for each backend.
|
||||
|
||||
|
|
@ -25,22 +25,16 @@ You can repeat the `--db` and `--dbpath` flags from here forward instead of the
|
|||
|
||||
### Load Data Into A Graph
|
||||
|
||||
Let's extract the sample data, a couple hundred thousand movie triples, that comes in the checkout:
|
||||
First we load the data.
|
||||
|
||||
```bash
|
||||
zcat 30kmoviedatauniq.n3.gz > 30k.n3
|
||||
```
|
||||
|
||||
Then, we can load the data.
|
||||
|
||||
```bash
|
||||
./cayley load --config=cayley.cfg.overview --triples=30k.n3
|
||||
./cayley load --config=cayley.cfg.overview --triples=30kmoviedata.nt.gz
|
||||
```
|
||||
|
||||
And wait. It will load. If you'd like to watch it load, you can run
|
||||
|
||||
```bash
|
||||
./cayley load --config=cayley.cfg.overview --triples=30k.n3 --alsologtostderr
|
||||
./cayley load --config=cayley.cfg.overview --triples=30kmoviedata.nt.gz --alsologtostderr
|
||||
```
|
||||
|
||||
And watch the log output go by.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue