Kétirányú relációk #
Probléma #
Ha van egy A <-1-> B <-2-> C
gráfunk ahol A
, B
, C
subject-ek, és object-ek az 1
, 2
predikátumokkal vannak összekapcsolva mindkét irányban (bidirectional),
akkor hogyan tudjuk C
-t elérni A
-ból egy path segítségével?
Teszt adatok #

Fig 1.: A tesz adat gráfja
A teszt adatok megjelenítése in nquads formátumban
<A> <predicate-1> <B> .
<B> <predicate-1> <A> .
<B> <predicate-2> <C> .
<C> <predicate-2> <B> .
<A1> <predicate-1> <B1> .
<B1> <predicate-1> <A1> .
<B1> <predicate-2> <C1> .
<C1> <predicate-2> <B1> .
<A2> <predicate-1> <B2> .
<B2> <predicate-1> <A2> .
<B2> <predicate-2> <C2> .
<C2> <predicate-2> <B2> .
Gizmo Query #
Egyszerű Query #
g.V().Tag("source").Out("<predicate-1>").Out("<predicate-2>").Tag('target').Out("<predicate-2>").Out("<predicate-1>").All()
Kimenet:
{"id":"A","source":"A","target":"C"}
{"id":"A1","source":"A1","target":"C1"}
{"id":"A2","source":"A2","target":"C2"}
Query kétirányú predicate alkalmazásával #
g.V().Tag("source").Both("<predicate-1>").Both("<predicate-2>").Tag('target').All()
Kimenet:
{"id":"C","source":"A","target":"C"}
{"id":"C1","source":"A1","target":"C1"}
{"id":"C2","source":"A2","target":"C2"}
{"id":"C","source":"A","target":"C"}
{"id":"C1","source":"A1","target":"C1"}
{"id":"C2","source":"A2","target":"C2"}
Query morphism alkalmazásával #
// with morphism
forth = g.V().Tag("source").Out("<predicate-1>").Out("<predicate-2>").Tag("target");
back = g.M().Out("<predicate-2>").Out("<predicate-1>")
forth.Follow(back).All()
Kimenet:
{"id":"A","source":"A","target":"C"}
{"id":"A1","source":"A1","target":"C1"}
{"id":"A2","source":"A2","target":"C2"}
Golang implementáció #
A forráskód megjelenítése
package main
import (
"context"
"fmt"
"github.com/cayleygraph/cayley"
"github.com/cayleygraph/quad"
)
func main() {
// Create an in-memory store
store := InitStore()
// Create Quads and uploads to the store
quads := makeQuads()
AddQuadsToStore(store, quads)
// Execute the query
doQuery(store)
}
// Create a mem-store for testing
func InitStore() *cayley.Handle {
store, err := cayley.NewMemoryGraph()
if err != nil {
panic(err)
}
return store
}
func makeQuads() []quad.Quad {
quads := []quad.Quad{}
quads = append(quads, quad.Make("A", "1", "B", ""))
quads = append(quads, quad.Make("B", "1", "A", ""))
quads = append(quads, quad.Make("B", "2", "C", ""))
quads = append(quads, quad.Make("C", "2", "B", ""))
quads = append(quads, quad.Make("A1", "1", "B1", ""))
quads = append(quads, quad.Make("B1", "1", "A1", ""))
quads = append(quads, quad.Make("B1", "2", "C1", ""))
quads = append(quads, quad.Make("C1", "2", "B1", ""))
quads = append(quads, quad.Make("A2", "1", "B2", ""))
quads = append(quads, quad.Make("B2", "1", "A2", ""))
quads = append(quads, quad.Make("B2", "2", "C2", ""))
quads = append(quads, quad.Make("C2", "2", "B2", ""))
return quads
}
func AddQuadsToStore(store *cayley.Handle, quads []quad.Quad) {
for _, q := range quads {
store.AddQuad(q)
}
}
func doQuery(store *cayley.Handle) {
p := cayley.StartPath(store).Tag("source").Out("1").Out("2").Tag("target").Out("2").Out("1")
p.Iterate(context.Background()).EachValue(nil, func(value quad.Value) {
fmt.Printf("%v\n", value)
})
p.Iterate(context.Background()).TagValues(store, func(t map[string]quad.Value) {
fmt.Printf("%v\n", t)
})
}
Results:
"A"
"A1"
"A2"
map[source:"A" target:"C"]
map[source:"A1" target:"C1"]
map[source:"A2" target:"C2"]