// Chained n-hop walk-count aggregation: the multi-hop path of Aggregation,// which seeds per-node walk multiplicity from the filtered sources and// expands hop by hop over the CSR (two dense buffers ping-pong, frontier// tracked so clears are O(active)), emitting one row per reached endpoint.// Split from aggregate_run.go, which holds the single-scan Run.
package chickpeasimport ()// checkHopsSupported rejects option combinations the walk path would// silently ignore.func ( *Aggregation) () error {for , := range []struct {boolstring }{ {len(.having) > 0, "Having"}, {.byLabel, "ByLabel"}, {len(.group) > 0, "By/Bin/TemporalComponent/ByLabelMembership"}, {.hasSum, "Sum"}, {.hasThrough, "Through"}, {.neighborFilter != nil, "OnlyNeighbors"}, {len(.requirePresent) > 0, "RequirePresent"}, } {if . {returnfmt.Errorf("%w: chained Hop walk counts do not support %s (it would be silently ignored)", ErrSchema, .) } }returnnil}// runHops is the chained n-hop walk count: seed per-node walk multiplicity// from the filtered sources, expand hop by hop over the CSR accumulating// next[neighbor] += mult[node] (two dense buffers ping-pong, frontier// tracked so clears are O(active)), then emit one row per endpoint.func ( *Aggregation) () (*AggResult, error) { := .g , := .resolveFilters(.filters)if != nil {returnnil, } , := .resolveProjFilters()if != nil {returnnil, } := make([]*nodeset.Set, 0, len(.labels))for , := range .labels { , := .NodesWithLabel()if ! {returnnil, fmt.Errorf("%w: label %q not found", ErrSchema, ) } = append(, ) } := make([]struct {RelMatchDirection }, len(.hops))for , := range .hops {// A missing type matches nothing, so the walk dies there. []. = .Match(.RelType) []. = .Dir }// Walk-multiplicity buffers size by the CSR id space, not NodeCount: // they index by raw node id (sparse-id safety). := int(.CSRIDSpace()) := make([]uint64, ) := make([]uint64, )var []NodeIDvaruint64for , := range {for := range .Iter() {if !passes(, ) {continue } := falsefor , := range {ifint() >= len(.projection) { = truebreak } , := .column.Get(.projection[])if ! { = truebreak }if , := .allowed[]; ! { = truebreak } }if {continue }if [] == 0 { = append(, ) } []++ ++ } }for , := range {var []NodeIDfor , := range { := []for := range .NeighborsMatch(, ., .) {if [] == 0 { = append(, ) } [] += } }// Clear the spent multiplicities (O(active)), then swap so next is // the all-zero scratch for the following hop.for , := range { [] = 0 } , = , = } := make([]AggRow, 0, len())for , := range { = append(, AggRow{Key: []int64{int64()}, Count: []}) }return &AggResult{Total: , Rows: , Fields: []string{"endpoint"}}, nil}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.