changed to new testdata file that is now used throughout the documentation

This commit is contained in:
Jonathan Fuerst 2015-04-22 17:05:38 +02:00
parent 5e3aafb47b
commit e851864576
11 changed files with 165 additions and 167 deletions

View file

@ -1,6 +1,6 @@
{
"Arch": "arm amd64 386",
"Os": "linux darwin windows",
"ResourcesInclude": "README.md,static,templates,LICENSE,AUTHORS,CONTRIBUTORS,docs,cayley.cfg.example,30kmoviedata.nq.gz,testdata.nq",
"ResourcesInclude": "README.md,static,templates,LICENSE,AUTHORS,CONTRIBUTORS,docs,cayley.cfg.example,data",
"ConfigVersion": "0.9"
}

View file

@ -38,7 +38,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.nq
./cayley repl --dbpath=data/testdata.nq
```
You should see a `cayley>` REPL prompt. Go ahead and give it a try:
@ -66,13 +66,13 @@ cayley> graph.Vertex("dani").Out("follows").All()
For somewhat more interesting data, a sample of 30k movies from Freebase comes in the checkout.
```
./cayley repl --dbpath=30kmoviedata.nq.gz
./cayley repl --dbpath=data/30kmoviedata.nq.gz
```
To run the web frontend, replace the "repl" command with "http"
```
./cayley http --dbpath=30kmoviedata.nq.gz
./cayley http --dbpath=data/30kmoviedata.nq.gz
```
And visit port 64210 on your machine, commonly [http://localhost:64210](http://localhost:64210)

View file

@ -1,11 +0,0 @@
<A> <follows> <B> .
<B> <follows> <F> .
<B> <status> "cool_person" .
<C> <follows> <B> .
<C> <follows> <D> .
<D> <follows> <B> .
<D> <follows> <G> .
<D> <status> "cool_person" .
<E> <follows> <F> .
<F> <follows> <G> .
<G> <status> "cool_person" .

View file

@ -415,7 +415,7 @@ func prepare(t testing.TB) {
cfg.DatabaseType = *backend
switch *backend {
case "memstore":
cfg.DatabasePath = "30kmoviedata.nq.gz"
cfg.DatabasePath = "data/30kmoviedata.nq.gz"
case "leveldb", "bolt":
cfg.DatabasePath = "/tmp/cayley_test_" + *backend
cfg.DatabaseOptions = map[string]interface{}{
@ -450,7 +450,7 @@ func prepare(t testing.TB) {
}
if needsLoad {
err = load(handle.QuadWriter, cfg, "30kmoviedata.nq.gz", "cquad")
err = load(handle.QuadWriter, cfg, "data/30kmoviedata.nq.gz", "cquad")
if err != nil {
t.Fatalf("Failed to load %q: %v", cfg.DatabasePath, err)
}

11
data/testdata.nq Normal file
View file

@ -0,0 +1,11 @@
<alice> <follows> <bob> .
<bob> <follows> <fred> .
<bob> <status> "cool_person" .
<charlie> <follows> <bob> .
<charlie> <follows> <dani> .
<dani> <follows> <bob> .
<dani> <follows> <greg> .
<dani> <status> "cool_person" .
<emily> <follows> <fred> .
<fred> <follows> <greg> .
<greg> <status> "cool_person" .

View file

@ -49,26 +49,32 @@ Both `.Morphism()` and `.Vertex()` create path objects, which provide the follow
For these examples, suppose we have the following graph:
```
+---+ +---+
| A |------- ->| F |<--
+---+ \------>+---+-/ +---+ \--+---+
------>|#B#| | | E |
+---+-------/ >+---+ | +---+
| C | / v
+---+ -/ +---+
---- +---+/ |#G#|
\-->|#D#|------------->+---+
+---+
+-------+ +------+
| alice |----- ->| fred |<--
+-------+ \---->+-------+-/ +------+ \-+-------+
----->| #bob# | | | emily |
+---------+--/ --->+-------+ | +-------+
| charlie | / v
+---------+ / +--------+
\--- +--------+ | #greg# |
\-->| #dani# |------------>+--------+
+--------+
```
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
dani -- status --> cool_person
```
Perhaps these are the influencers in our community.
To load above graph into cayley and reproduce the following examples:
`./cayley repl --dbpath=data/testdata.nq` for a REPL prompt, or
`./cayley http --dbpath=data/testdata.nq` for the web frontend.
### Basic Traversals
####**`path.Out([predicatePath], [tags])`**
@ -89,18 +95,18 @@ Out is the work-a-day way to get between nodes, in the forward direction. Starti
Example:
```javascript
// The working set of this is B and D
g.V("C").Out("follows")
// The working set of this is F, as A follows B and B follows F.
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.
// 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 separate query path.
// The working set of this is bob and dani
g.V("charlie").Out("follows")
// The working set of this is fred, as alice follows bob and bob follows fred.
g.V("alice").Out("follows").Out("follows")
// Finds all things dani points at. Result is bob, greg and cool_person
g.V("dani").Out()
// Finds all things dani points at on the status linkage.
// Result is bob, greg and cool_person
g.V("dani").Out(["follows", "status"])
// Finds all things dani points at on the status linkage, given from a separate query path.
// Result is {"id": cool_person, "pred": "status"}
g.V("D").Out(g.V("status"), "pred")
g.V("dani").Out(g.V("status"), "pred")
```
####**`path.In([predicatePath], [tags])`**
@ -121,12 +127,12 @@ Same as Out, but in the other direction. Starting with the nodes in `path` on t
Example:
```javascript
// Find the cool people, B G and D
// Find the cool people, bob, greg and dani
g.V("cool_person").In("status")
// Find who follows B, in this case, A, C, and D
g.V("B").In("follows")
// Find who follows the people E follows, namely, E and B
g.V("E").Out("follows").In("follows")
// Find who follows bob, in this case, alice, charlie, and dani
g.V("bob").In("follows")
// Find who follows the people emily follows, namely, emily and bob
g.V("emily").Out("follows").In("follows")
```
####**`path.Both([predicatePath], [tags])`**
@ -148,8 +154,8 @@ Note: Less efficient, for the moment, as it's implemented with an Or, but useful
Example:
```javascript
// Find all followers/followees of F. Returns B E and G
g.V("F").Both("follows")
// Find all followers/followees of fred. Returns bob, emily and greg
g.V("fred").Both("follows")
```
@ -163,9 +169,9 @@ 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.
// Results in three paths for B (from A C and D)
g.V().Out("follows").Is("B")
// Starting from all nodes in the graph, find the paths that follow bob.
// Results in three paths for bob (from alic, charlie and dani)
g.V().Out("follows").Is("bob")
```
####**`path.Has(predicate, object)`**
@ -181,10 +187,10 @@ Usually useful for starting with all nodes, or limiting to a subset depending on
Example:
```javascript
// Start from all nodes that follow B -- results in A C and D
g.V().Has("follows", "B")
// People C follows who then follow F. Results in B.
g.V("C").Out("follows").Has("follows", "F")
// Start from all nodes that follow bob -- results in alice, charlie and dani
g.V().Has("follows", "bob")
// People charlie follows who then follow fred. Results in bob.
g.V("charlie").Out("follows").Has("follows", "fred")
```
### Tagging
@ -203,7 +209,7 @@ In order to save your work or learn more about how a path got to the end, we hav
Example:
```javascript
// Start from all nodes, save them into start, follow any status links, and return the result.
// Results are: {"id": "cool_person", "start": "B"}, {"id": "cool_person", "start": "G"}, {"id": "cool_person", "start": "D"}
// Results are: {"id": "cool_person", "start": "bob"}, {"id": "cool_person", "start": "greg"}, {"id": "cool_person", "start": "dani"}
g.V().Tag("start").Out("status")
```
@ -220,11 +226,11 @@ 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"},
// {"id": "C", "start": "D"},
// {"id": "D", "start": "G"}
// {"id": "alice", "start": "bob"},
// {"id": "charlie", "start": "bob"},
// {"id": "dani", "start": "bob"},
// {"id": "charlie", "start": "dani"},
// {"id": "dani", "start": "greg"}
g.V().Tag("start").Out("status").Back("start").In("follows")
```
@ -239,12 +245,12 @@ From the current node as the subject, save the object of all quads with `predica
Example:
```javascript
// Start from D and B and save who they follow into "target"
// Start from dani and bob and save who they follow into "target"
// Returns:
// {"id" : "D", "target": "B" },
// {"id" : "D", "target": "G" },
// {"id" : "B", "target": "F" },
g.V("D", "B").Save("follows", "target")
// {"id" : "dani", "target": "bob" },
// {"id" : "dani", "target": "greg" },
// {"id" : "bob", "target": "fred" },
g.V("dani", "bob").Save("follows", "target")
```
### Joining
@ -262,11 +268,11 @@ Filters all paths by the result of another query path (efficiently computed).
This is essentially a join where, at the stage of each path, a node is shared.
Example:
```javascript
var cFollows = g.V("C").Out("follows")
var dFollows = g.V("D").Out("follows")
// People followed by both C (B and D) and D (B and G) -- returns B.
var cFollows = g.V("charlie").Out("follows")
var dFollows = g.V("dani").Out("follows")
// People followed by both charlie (bob and dani) and dani (bob and greg) -- returns bob.
cFollows.Intersect(dFollows)
// Equivalently, g.V("C").Out("follows").And(g.V("D").Out("follows"))
// Equivalently, g.V("charlie").Out("follows").And(g.V("dani").Out("follows"))
```
####**`path.Union(query)`**
@ -284,9 +290,9 @@ See also: `path.Tag()`
Example:
```javascript
var cFollows = g.V("C").Out("follows")
var dFollows = g.V("D").Out("follows")
// People followed by both C (B and D) and D (B and G) -- returns B (from C), B (from D), D and G.
var cFollows = g.V("charlie").Out("follows")
var dFollows = g.V("dani").Out("follows")
// People followed by both charlie (bob and dani) and dani (bob and greg) -- returns bob (from charlie), bob (from dani), dani and greg.
cFollows.Union(dFollows)
```
####**`path.Except(query)`**
@ -303,11 +309,11 @@ In a set-theoretic sense, this is (A - B). While `g.V().Except(path)` to achieve
Example:
```javascript
var cFollows = g.V("C").Out("follows")
var dFollows = g.V("D").Out("follows")
// People followed by both C (B and D) and D (B and G) -- returns B.
cFollows.Except(dFollows) // The set (D) -- what C follows that D does not also follow.
// Equivalently, g.V("C").Out("follows").Except(g.V("D").Out("follows"))
var cFollows = g.V("charlie").Out("follows")
var dFollows = g.V("dani").Out("follows")
// People followed by both charlie (bob and dani) and dani (bob and greg) -- returns bob.
cFollows.Except(dFollows) // The set (dani) -- what charlie follows that dani does not also follow.
// Equivalently, g.V("charlie").Out("follows").Except(g.V("dani").Out("follows"))
```
@ -327,10 +333,10 @@ Starts as if at the g.M() and follows through the morphism path.
Example:
```javascript:
friendOfFriend = g.Morphism().Out("follows").Out("follows")
// Returns the followed people of who C follows -- a simplistic "friend of my friend"
// Returns the followed people of who charlie follows -- a simplistic "friend of my friend"
// and whether or not they have a "cool" status. Potential for recommending followers abounds.
// Returns B and G
g.V("C").Follow(friendOfFriend).Has("status", "cool_person")
// Returns bob and greg
g.V("charlie").Follow(friendOfFriend).Has("status", "cool_person")
```
####**`path.FollowR(morphism)`**
@ -348,7 +354,7 @@ Example:
```javascript:
friendOfFriend = g.Morphism().Out("follows").Out("follows")
// Returns the third-tier of influencers -- people who follow people who follow the cool people.
// Returns E B C (from B) and C (from G)
// Returns emily, bob, charlie (from bob) and charlie (from greg)
g.V().Has("status", "cool_person").FollowR(friendOfFriend)
```
@ -384,8 +390,8 @@ Returns: Array
Executes a query and returns the results at the end of the query path.
Example:
```javascript
// fooNames contains an Array of names for foo.
var fooNames = g.V("foo").Out("name").ToArray()
// bobFollowers contains an Array of followers of bob (alice, charlie, dani).
var bobFollowers = g.V("bob").In("follows").ToArray()
```
####**`query.ToValue()`**
@ -394,7 +400,7 @@ Arguments: None
Returns: String
As `.ToArray` above, but limited to one result node -- a string. Like `.Limit(1)` for the above case.
As `.ToArray` above, but limited to one result node -- a string. Like `.Limit(1)` for the above case (alice).
####**`query.TagArray()`**
@ -405,10 +411,10 @@ Returns: Array of string-to-string objects
As `.ToArray` above, but instead of a list of top-level strings, returns an Array of tag-to-string dictionaries, much as `.All` would, except inside the Javascript environment.
Example:
```javascript
// fooNames contains an Array of names for foo.
var fooTags = g.V("foo").Tag("foo_value").Out("name").ToArray()
// fooValue should be the string "foo"
var fooValue = fooTags[0]["foo_value"]
// bobFollowers contains an Array of followers of bob (alice, charlie, dani).
var bobFollowers = g.V("bob").Tag("name").In("follows").ToArray()
// nameValue should be the string "bob"
var nameValue = bobTags[0]["name"]
```
####**`query.TagValue()`**

View file

@ -29,13 +29,13 @@ You can repeat the `--db` and `--dbpath` flags from here forward instead of the
First we load the data.
```bash
./cayley load --config=cayley.cfg.overview --quads=30kmoviedata.nq.gz
./cayley load --config=cayley.cfg.overview --quads=data/30kmoviedata.nq.gz
```
And wait. It will load. If you'd like to watch it load, you can run
```bash
./cayley load --config=cayley.cfg.overview --quads=30kmoviedata.nq.gz --alsologtostderr
./cayley load --config=cayley.cfg.overview --quads=data/30kmoviedata.nq.gz --alsologtostderr
```
And watch the log output go by.

View file

@ -28,29 +28,30 @@ import (
// This is a simple test graph.
//
// +---+ +---+
// | A |------- ->| F |<--
// +---+ \------>+---+-/ +---+ \--+---+
// ------>|#B#| | | E |
// +---+-------/ >+---+ | +---+
// | C | / v
// +---+ -/ +---+
// ---- +---+/ |#G#|
// \-->|#D#|------------->+---+
// +---+
// +-------+ +------+
// | alice |----- ->| fred |<--
// +-------+ \---->+-------+-/ +------+ \-+-------+
// ----->| #bob# | | | emily |
// +---------+--/ --->+-------+ | +-------+
// | charlie | / v
// +---------+ / +--------+
// \--- +--------+ | #greg# |
// \-->| #dani# |------------>+--------+
// +--------+
//
var simpleGraph = []quad.Quad{
{"A", "follows", "B", ""},
{"C", "follows", "B", ""},
{"C", "follows", "D", ""},
{"D", "follows", "B", ""},
{"B", "follows", "F", ""},
{"F", "follows", "G", ""},
{"D", "follows", "G", ""},
{"E", "follows", "F", ""},
{"B", "status", "cool", "status_graph"},
{"D", "status", "cool", "status_graph"},
{"G", "status", "cool", "status_graph"},
{"alice", "follows", "bob", ""},
{"charlie", "follows", "bob", ""},
{"charlie", "follows", "dani", ""},
{"dani", "follows", "bob", ""},
{"bob", "follows", "fred", ""},
{"fred", "follows", "greg", ""},
{"dani", "follows", "greg", ""},
{"emily", "follows", "fred", ""},
{"bob", "status", "cool_person", "status_graph"},
{"dani", "status", "cool_person", "status_graph"},
{"greg", "status", "cool_person", "status_graph"},
}
func makeTestSession(data []quad.Quad) *Session {
@ -72,67 +73,67 @@ var testQueries = []struct {
{
message: "get a single vertex",
query: `
g.V("A").All()
g.V("alice").All()
`,
expect: []string{"A"},
expect: []string{"alice"},
},
{
message: "use .Out()",
query: `
g.V("A").Out("follows").All()
g.V("alice").Out("follows").All()
`,
expect: []string{"B"},
expect: []string{"bob"},
},
{
message: "use .In()",
query: `
g.V("B").In("follows").All()
g.V("bob").In("follows").All()
`,
expect: []string{"A", "C", "D"},
expect: []string{"alice", "charlie", "dani"},
},
{
message: "use .Both()",
query: `
g.V("F").Both("follows").All()
g.V("fred").Both("follows").All()
`,
expect: []string{"B", "G", "E"},
expect: []string{"bob", "greg", "emily"},
},
{
message: "use .Tag()-.Is()-.Back()",
query: `
g.V("B").In("follows").Tag("foo").Out("status").Is("cool").Back("foo").All()
g.V("bob").In("follows").Tag("foo").Out("status").Is("cool_person").Back("foo").All()
`,
expect: []string{"D"},
expect: []string{"dani"},
},
{
message: "separate .Tag()-.Is()-.Back()",
query: `
x = g.V("C").Out("follows").Tag("foo").Out("status").Is("cool").Back("foo")
x.In("follows").Is("D").Back("foo").All()
x = g.V("charlie").Out("follows").Tag("foo").Out("status").Is("cool_person").Back("foo")
x.In("follows").Is("dani").Back("foo").All()
`,
expect: []string{"B"},
expect: []string{"bob"},
},
{
message: "do multiple .Back()s",
query: `
g.V("E").Out("follows").As("f").Out("follows").Out("status").Is("cool").Back("f").In("follows").In("follows").As("acd").Out("status").Is("cool").Back("f").All()
g.V("emily").Out("follows").As("f").Out("follows").Out("status").Is("cool_person").Back("f").In("follows").In("follows").As("acd").Out("status").Is("cool_person").Back("f").All()
`,
tag: "acd",
expect: []string{"D"},
expect: []string{"dani"},
},
{
message: "use Except to filter out a single vertex",
query: `
g.V("A", "B").Except(g.V("A")).All()
g.V("alice", "bob").Except(g.V("alice")).All()
`,
expect: []string{"B"},
expect: []string{"bob"},
},
{
message: "use chained Except",
query: `
g.V("A", "B", "C").Except(g.V("B")).Except(g.V("C")).All()
g.V("alice", "bob", "charlie").Except(g.V("bob")).Except(g.V("charlie")).All()
`,
expect: []string{"A"},
expect: []string{"alice"},
},
// Morphism tests.
@ -140,17 +141,17 @@ var testQueries = []struct {
message: "show simple morphism",
query: `
grandfollows = g.M().Out("follows").Out("follows")
g.V("C").Follow(grandfollows).All()
g.V("charlie").Follow(grandfollows).All()
`,
expect: []string{"G", "F", "B"},
expect: []string{"greg", "fred", "bob"},
},
{
message: "show reverse morphism",
query: `
grandfollows = g.M().Out("follows").Out("follows")
g.V("F").FollowR(grandfollows).All()
g.V("fred").FollowR(grandfollows).All()
`,
expect: []string{"A", "C", "D"},
expect: []string{"alice", "charlie", "dani"},
},
// Intersection tests.
@ -158,59 +159,59 @@ var testQueries = []struct {
message: "show simple intersection",
query: `
function follows(x) { return g.V(x).Out("follows") }
follows("D").And(follows("C")).All()
follows("dani").And(follows("charlie")).All()
`,
expect: []string{"B"},
expect: []string{"bob"},
},
{
message: "show simple morphism intersection",
query: `
grandfollows = g.M().Out("follows").Out("follows")
function gfollows(x) { return g.V(x).Follow(grandfollows) }
gfollows("A").And(gfollows("C")).All()
gfollows("alice").And(gfollows("charlie")).All()
`,
expect: []string{"F"},
expect: []string{"fred"},
},
{
message: "show double morphism intersection",
query: `
grandfollows = g.M().Out("follows").Out("follows")
function gfollows(x) { return g.V(x).Follow(grandfollows) }
gfollows("E").And(gfollows("C")).And(gfollows("B")).All()
gfollows("emily").And(gfollows("charlie")).And(gfollows("bob")).All()
`,
expect: []string{"G"},
expect: []string{"greg"},
},
{
message: "show reverse intersection",
query: `
grandfollows = g.M().Out("follows").Out("follows")
g.V("G").FollowR(grandfollows).Intersect(g.V("F").FollowR(grandfollows)).All()
g.V("greg").FollowR(grandfollows).Intersect(g.V("fred").FollowR(grandfollows)).All()
`,
expect: []string{"C"},
expect: []string{"charlie"},
},
{
message: "show standard sort of morphism intersection, continue follow",
query: `gfollowers = g.M().In("follows").In("follows")
function cool(x) { return g.V(x).As("a").Out("status").Is("cool").Back("a") }
cool("G").Follow(gfollowers).Intersect(cool("B").Follow(gfollowers)).All()
function cool(x) { return g.V(x).As("a").Out("status").Is("cool_person").Back("a") }
cool("greg").Follow(gfollowers).Intersect(cool("bob").Follow(gfollowers)).All()
`,
expect: []string{"C"},
expect: []string{"charlie"},
},
// Gremlin Has tests.
{
message: "show a simple Has",
query: `
g.V().Has("status", "cool").All()
g.V().Has("status", "cool_person").All()
`,
expect: []string{"G", "D", "B"},
expect: []string{"greg", "dani", "bob"},
},
{
message: "show a double Has",
query: `
g.V().Has("status", "cool").Has("follows", "F").All()
g.V().Has("status", "cool_person").Has("follows", "fred").All()
`,
expect: []string{"B"},
expect: []string{"bob"},
},
// Tag tests.
@ -220,20 +221,20 @@ var testQueries = []struct {
g.V().Save("status", "somecool").All()
`,
tag: "somecool",
expect: []string{"cool", "cool", "cool"},
expect: []string{"cool_person", "cool_person", "cool_person"},
},
{
message: "show a simple saveR",
query: `
g.V("cool").SaveR("status", "who").All()
g.V("cool_person").SaveR("status", "who").All()
`,
tag: "who",
expect: []string{"G", "D", "B"},
expect: []string{"greg", "dani", "bob"},
},
{
message: "show an out save",
query: `
g.V("D").Out(null, "pred").All()
g.V("dani").Out(null, "pred").All()
`,
tag: "pred",
expect: []string{"follows", "follows", "status"},
@ -241,7 +242,7 @@ var testQueries = []struct {
{
message: "show a tag list",
query: `
g.V("D").Out(null, ["pred", "foo", "bar"]).All()
g.V("dani").Out(null, ["pred", "foo", "bar"]).All()
`,
tag: "foo",
expect: []string{"follows", "follows", "status"},
@ -249,16 +250,16 @@ var testQueries = []struct {
{
message: "show a pred list",
query: `
g.V("D").Out(["follows", "status"]).All()
g.V("dani").Out(["follows", "status"]).All()
`,
expect: []string{"B", "G", "cool"},
expect: []string{"bob", "greg", "cool_person"},
},
{
message: "show a predicate path",
query: `
g.V("D").Out(g.V("follows"), "pred").All()
g.V("dani").Out(g.V("follows"), "pred").All()
`,
expect: []string{"B", "G"},
expect: []string{"bob", "greg"},
},
}

View file

@ -1,9 +0,0 @@
<alice> <follows> <bob> .
<bob> <follows> <alice> .
<charlie> <follows> <bob> .
<dani> <follows> <charlie> .
<dani> <follows> <alice> .
<alice> <is> "cool" .
<bob> <is> "not cool" .
<charlie> <is> "cool" .
<dani> <is> "not cool" .