add InPredicates/OutPredicates

This commit is contained in:
Barak Michener 2015-10-28 19:42:59 -04:00
parent b91b7ab824
commit 97247ae40f
3 changed files with 77 additions and 7 deletions

View file

@ -137,6 +137,28 @@ func inMorphism(via ...interface{}) morphism {
}
}
// predicatesMorphism iterates to the uniqified set of predicates from
// the given set of nodes in the path.
func predicatesMorphism(isIn bool) morphism {
m := morphism{
Name: "out_predicates",
Reversal: func() morphism { panic("not implemented: need a function from predicates to their associated edges") },
Apply: func(qs graph.QuadStore, in graph.Iterator, ctx *context) (graph.Iterator, *context) {
dir := quad.Subject
if isIn {
dir = quad.Object
}
lto := iterator.NewLinksTo(qs, in, dir)
hasa := iterator.NewHasA(qs, lto, quad.Predicate)
return iterator.NewUnique(hasa), ctx
},
}
if isIn {
m.Name = "in_predicates"
}
return m
}
// iteratorMorphism simply tacks the input iterator onto the chain.
func iteratorMorphism(it graph.Iterator) morphism {
return morphism{

View file

@ -98,11 +98,6 @@ func (p *Path) Tag(tags ...string) *Path {
return p
}
// As is a synonym for Tag.
func (p *Path) As(tags ...string) *Path {
return p.Tag(tags...)
}
// Out updates this Path to represent the nodes that are adjacent to the
// current nodes, via the given outbound predicate.
//
@ -131,6 +126,33 @@ func (p *Path) In(via ...interface{}) *Path {
return p
}
// InPredicates updates this path to represent the nodes of the valid inbound
// predicates from the current nodes.
//
// For example:
// // Returns a list of predicates valid from "bob"
// //
// // Will return []string{"follows"} if there are any things that "follow" Bob
// StartPath(qs, "bob").InPredicates()
func (p *Path) InPredicates() *Path {
p.stack = append(p.stack, predicatesMorphism(true))
return p
}
// OutPredicates updates this path to represent the nodes of the valid inbound
// predicates from the current nodes.
//
// For example:
// // Returns a list of predicates valid from "bob"
// //
// // Will return []string{"follows", "status"} if there are edges from "bob"
// // labelled "follows", and edges from "bob" that describe his "status".
// StartPath(qs, "bob").OutPredicates()
func (p *Path) OutPredicates() *Path {
p.stack = append(p.stack, predicatesMorphism(false))
return p
}
// And updates the current Path to represent the nodes that match both the
// current Path so far, and the given Path.
func (p *Path) And(path *Path) *Path {
@ -221,7 +243,6 @@ func (p *Path) Back(tag string) *Path {
newPath.stack = append(newPath.stack, p.stack[i].Reversal())
i--
}
}
// BuildIterator returns an iterator from this given Path. Note that you must

View file

@ -108,6 +108,12 @@ type test struct {
tag string
}
// Define morphisms without a QuadStore
var (
grandfollows = StartMorphism().Out("follows").Out("follows")
)
func testSet(qs graph.QuadStore) []test {
return []test{
{
@ -197,10 +203,31 @@ func testSet(qs graph.QuadStore) []test {
},
{
message: "do multiple .Back()s",
path: StartPath(qs, "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"),
path: StartPath(qs, "emily").Out("follows").Tag("f").Out("follows").Out("status").Is("cool_person").Back("f").In("follows").In("follows").Tag("acd").Out("status").Is("cool_person").Back("f"),
tag: "acd",
expect: []string{"dani"},
},
{
message: "InPredicates()",
path: StartPath(qs, "bob").InPredicates(),
expect: []string{"follows"},
},
{
message: "OutPredicates()",
path: StartPath(qs, "bob").OutPredicates(),
expect: []string{"follows", "status"},
},
// Morphism tests
{
message: "show simple morphism",
path: StartPath(qs, "charlie").Follow(grandfollows),
expect: []string{"greg", "fred", "bob"},
},
{
message: "show reverse morphism",
path: StartPath(qs, "fred").FollowReverse(grandfollows),
expect: []string{"alice", "charlie", "dani"},
},
}
}