query

package
v0.4.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2024 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package query contains methods for building queries executed by the Index.Query method.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Aggregator

type Aggregator[K feature.Key, F feature.Feature[K]] interface {
	Mapper[K, F]
	Reducer[K, F]
}

Aggregator is a map-reduce operation. It allows filtering and aggregation of results.

type Condition

type Condition[K feature.Key, F feature.Feature[K]] interface {
	IsMatch(feature F) (bool, error)
}

type Contains

type Contains[K feature.Key, F feature.Feature[K]] struct {
	primitives.Point
}

Contains is an example condition. It accepts all features containing a given point.

func (Contains[K, F]) IsMatch

func (c Contains[K, F]) IsMatch(feature F) (bool, error)

type Mapper

type Mapper[K feature.Key, F feature.Feature[K]] interface {
	Map(match *Match[K, F]) (*Match[K, F], error)
}

Mapper transforms a match, updating Match.ResultKeys.

type Match

type Match[K feature.Key, F feature.Feature[K]] struct {
	ResultKeys []ResultKey
	Feature    F
	Meta       interface{}
}

func (*Match[K, F]) AddKey

func (match *Match[K, F]) AddKey(resultKey ResultKey)

func (*Match[K, F]) ReplaceKeys

func (match *Match[K, F]) ReplaceKeys(resultKeys ...ResultKey)

type Pred

type Pred[K feature.Key, F feature.Feature[K]] func(feature F) (bool, error)

Pred is a predicate condition letting use a function instead of creating a structure implementing the Condition interface.

func (Pred[K, F]) IsMatch

func (p Pred[K, F]) IsMatch(feature F) (bool, error)

type Query

type Query[K feature.Key, F feature.Feature[K]] struct {
	Conditions  []Condition[K, F]  // Logical conjunction (AND).
	Aggregators []Aggregator[K, F] // Logical disjunction (OR).
	// contains filtered or unexported fields
}

Query holds configuration of a query pipeline for narrowing down spatial search results.

func (*Query[K, F]) Distinct

func (q *Query[K, F]) Distinct() []F

Distinct returns distinct features matching the query.

func (*Query[K, F]) Scan

func (q *Query[K, F]) Scan(feature F) error

Scan sends a feature through the query pipeline, first rejecting it unless all preconditions (conjunction step) match, then applying each of the filters and finally performing a reduce step to update query results.

type QueryBuilder

type QueryBuilder[K feature.Key, F feature.Feature[K]] struct {
	// contains filtered or unexported fields
}

func Build

func Build[K feature.Key, F feature.Feature[K]]() *QueryBuilder[K, F]

Build returns a new query builder.

Example (ComplexAggregation)

This example uses an example spatial feature implementation. See https://github.com/bilus/fencer/blob/master/query/query_test.go for more details.

package main

import (
	"fmt"
	"sort"
	"strconv"

	"github.com/bilus/fencer/primitives"
	"github.com/bilus/fencer/query"
	"github.com/bilus/fencer/testutil"
)

type CountryID int

func (id CountryID) String() string {
	return strconv.Itoa(int(id))
}

type Country struct {
	ID           CountryID
	Name         string
	Population   int
	Change       float64
	Region       string
	BoundingRect *primitives.Rect
}

func (c Country) Key() CountryID {
	return c.ID
}

func (c Country) Contains(p primitives.Point) (bool, error) {
	return testutil.Contains(*c.BoundingRect, p), nil
}

func (c Country) Bounds() *primitives.Rect {
	return c.BoundingRect
}

var countries = []Country{
	{1, "Vatican City", 800, -0.011, "Europe", makeRect(bounds[0])},
	{2, "Tokelau", 1300, 0.014, "Polynesia", makeRect(bounds[1])},
	{3, "Niue", 1600, -0.004, "Polynesia", makeRect(bounds[2])},
	{4, "Tuvalu", 11200, 0.009, "Oceania", makeRect(bounds[3])},
	{5, "Nauru", 11300, 0.001, "Oceania", makeRect(bounds[4])},
	{6, "Poland", 38224, -0.001, "Europe", makeRect(bounds[5])},
	{7, "Ukraine", 44400, 0, "Europe", makeRect(bounds[6])},
}

type GroupByRegion struct{}

func (GroupByRegion) Map(match *query.Match[CountryID, Country]) (*query.Match[CountryID, Country], error) {
	match.ReplaceKeys(match.Feature.Region)
	return match, nil
}

type MostPopulated struct{}

func (MostPopulated) Reduce(result *query.Result[CountryID, Country], match *query.Match[CountryID, Country]) error {
	for _, key := range match.ResultKeys {

		err := result.Update(key, func(entry *query.ResultEntry[CountryID, Country]) error {

			if len(entry.Features) == 0 {
				entry.Features = []Country{match.Feature}
				return nil
			}

			existingCountry := entry.Features[0]
			currentCountry := match.Feature

			if existingCountry.Population < currentCountry.Population {
				entry.Features = []Country{match.Feature}
			}
			return nil
		})
		if err != nil {
			return err
		}
	}

	return nil
}

type DecliningPopulation struct{}

func (DecliningPopulation) Map(match *query.Match[CountryID, Country]) (*query.Match[CountryID, Country], error) {
	country := match.Feature
	if country.Change < 0 {
		match.AddKey("declining")
	}
	return match, nil
}

func main() {
	qb := query.Build[CountryID, Country]()
	stream := qb.StreamTo(MostPopulated{})
	stream.Map(GroupByRegion{})
	stream.Map(DecliningPopulation{})
	query := qb.Query() // Map(MostPopulatedByRegion{}).Query()
	for _, country := range countries {
		query.Scan(country)
	}
	// Output will include Poland which isn't the largest country in its region
	// but it's the largest one with declining population.
	fmt.Println("Most populated countries per region and most populated country with declining population:", len(query.Distinct()))
	printNamesSorted(query.Distinct())
}

var bounds = [][]primitives.Point{

	{
		{12.44450569152832, 41.89978557507729},
		{12.459547519683836, 41.89978557507729},
		{12.459547519683836, 41.907946360630994},
		{12.44450569152832, 41.907946360630994},
	},

	{
		{-172.7874755859375, -9.66573839518868},
		{-170.947265625, -9.66573839518868},
		{-170.947265625, -8.303905908124174},
		{-172.7874755859375, -8.303905908124174},
	},

	{
		{-170.13702392578125, -19.265776189877485},
		{-169.5849609375, -19.265776189877485},
		{-169.5849609375, -18.818567424622376},
		{-170.13702392578125, -18.818567424622376},
	},

	{
		{174.74853515625, -11.059820828563412},
		{180.296630859375, -11.059820828563412},
		{180.296630859375, -5.397273407690904},
		{174.74853515625, -5.397273407690904},
	},

	{
		{166.79443359375, -0.6227752122036241},
		{167.07595825195312, -0.6227752122036241},
		{167.07595825195312, -0.4051174740026618},
		{166.79443359375, -0.4051174740026618},
	},

	{
		{14.04052734375, 48.922499263758255},
		{24.27978515625, 48.922499263758255},
		{24.27978515625, 54.99022172004893},
		{14.04052734375, 54.99022172004893},
	},

	{
		{21.665039062499996, 44.02442151965934},
		{40.341796875, 44.02442151965934},
		{40.341796875, 52.482780222078226},
		{21.665039062499996, 52.482780222078226},
	},
}

func makeRect(points []primitives.Point) *primitives.Rect {
	p := points[0]
	op := points[2]
	rect, err := primitives.NewRect(p, op[0]-p[0], op[1]-p[1])
	if err != nil {
		panic(err)
	}
	return rect
}

func printNamesSorted(features []Country) {
	names := make([]string, 0)
	for _, f := range features {
		names = append(names, f.Name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Println(name)
	}
}
Output:

Most populated countries per region and most populated country with declining population: 4
Nauru
Niue
Poland
Ukraine
Example (Conjunction)

This example uses an example spatial feature implementation. See https://github.com/bilus/fencer/blob/master/query/query_test.go for more details.

package main

import (
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/bilus/fencer/primitives"
	"github.com/bilus/fencer/query"
	"github.com/bilus/fencer/testutil"
)

type CountryID int

func (id CountryID) String() string {
	return strconv.Itoa(int(id))
}

type Country struct {
	ID           CountryID
	Name         string
	Population   int
	Change       float64
	Region       string
	BoundingRect *primitives.Rect
}

func (c Country) Key() CountryID {
	return c.ID
}

func (c Country) Contains(p primitives.Point) (bool, error) {
	return testutil.Contains(*c.BoundingRect, p), nil
}

func (c Country) Bounds() *primitives.Rect {
	return c.BoundingRect
}

var countries = []Country{
	{1, "Vatican City", 800, -0.011, "Europe", makeRect(bounds[0])},
	{2, "Tokelau", 1300, 0.014, "Polynesia", makeRect(bounds[1])},
	{3, "Niue", 1600, -0.004, "Polynesia", makeRect(bounds[2])},
	{4, "Tuvalu", 11200, 0.009, "Oceania", makeRect(bounds[3])},
	{5, "Nauru", 11300, 0.001, "Oceania", makeRect(bounds[4])},
	{6, "Poland", 38224, -0.001, "Europe", makeRect(bounds[5])},
	{7, "Ukraine", 44400, 0, "Europe", makeRect(bounds[6])},
}

func main() {
	// Both preconditions must match.
	q := query.Build[CountryID, Country]()
	q.Where(
		query.Pred[CountryID, Country](func(feature Country) (bool, error) {
			return feature.Population > 10000, nil
		}))
	q.Where(
		query.Pred[CountryID, Country](func(feature Country) (bool, error) {
			return strings.HasPrefix(feature.Name, "T"), nil
		}),
	)
	query := q.Query()
	for _, country := range countries {
		query.Scan(country)
	}
	fmt.Println("Countries with population > 10000 with name beginning with T:", len(query.Distinct()))
	printNamesSorted(query.Distinct())
}

var bounds = [][]primitives.Point{

	{
		{12.44450569152832, 41.89978557507729},
		{12.459547519683836, 41.89978557507729},
		{12.459547519683836, 41.907946360630994},
		{12.44450569152832, 41.907946360630994},
	},

	{
		{-172.7874755859375, -9.66573839518868},
		{-170.947265625, -9.66573839518868},
		{-170.947265625, -8.303905908124174},
		{-172.7874755859375, -8.303905908124174},
	},

	{
		{-170.13702392578125, -19.265776189877485},
		{-169.5849609375, -19.265776189877485},
		{-169.5849609375, -18.818567424622376},
		{-170.13702392578125, -18.818567424622376},
	},

	{
		{174.74853515625, -11.059820828563412},
		{180.296630859375, -11.059820828563412},
		{180.296630859375, -5.397273407690904},
		{174.74853515625, -5.397273407690904},
	},

	{
		{166.79443359375, -0.6227752122036241},
		{167.07595825195312, -0.6227752122036241},
		{167.07595825195312, -0.4051174740026618},
		{166.79443359375, -0.4051174740026618},
	},

	{
		{14.04052734375, 48.922499263758255},
		{24.27978515625, 48.922499263758255},
		{24.27978515625, 54.99022172004893},
		{14.04052734375, 54.99022172004893},
	},

	{
		{21.665039062499996, 44.02442151965934},
		{40.341796875, 44.02442151965934},
		{40.341796875, 52.482780222078226},
		{21.665039062499996, 52.482780222078226},
	},
}

func makeRect(points []primitives.Point) *primitives.Rect {
	p := points[0]
	op := points[2]
	rect, err := primitives.NewRect(p, op[0]-p[0], op[1]-p[1])
	if err != nil {
		panic(err)
	}
	return rect
}

func printNamesSorted(features []Country) {
	names := make([]string, 0)
	for _, f := range features {
		names = append(names, f.Name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Println(name)
	}
}
Output:

Countries with population > 10000 with name beginning with T: 1
Tuvalu
Example (GroupingResults)

This example uses an example spatial feature implementation. See https://github.com/bilus/fencer/blob/master/query/query_test.go for more details.

package main

import (
	"fmt"
	"sort"
	"strconv"

	"github.com/bilus/fencer/primitives"
	"github.com/bilus/fencer/query"
	"github.com/bilus/fencer/testutil"
)

type CountryID int

func (id CountryID) String() string {
	return strconv.Itoa(int(id))
}

type Country struct {
	ID           CountryID
	Name         string
	Population   int
	Change       float64
	Region       string
	BoundingRect *primitives.Rect
}

func (c Country) Key() CountryID {
	return c.ID
}

func (c Country) Contains(p primitives.Point) (bool, error) {
	return testutil.Contains(*c.BoundingRect, p), nil
}

func (c Country) Bounds() *primitives.Rect {
	return c.BoundingRect
}

var countries = []Country{
	{1, "Vatican City", 800, -0.011, "Europe", makeRect(bounds[0])},
	{2, "Tokelau", 1300, 0.014, "Polynesia", makeRect(bounds[1])},
	{3, "Niue", 1600, -0.004, "Polynesia", makeRect(bounds[2])},
	{4, "Tuvalu", 11200, 0.009, "Oceania", makeRect(bounds[3])},
	{5, "Nauru", 11300, 0.001, "Oceania", makeRect(bounds[4])},
	{6, "Poland", 38224, -0.001, "Europe", makeRect(bounds[5])},
	{7, "Ukraine", 44400, 0, "Europe", makeRect(bounds[6])},
}

type GroupByRegion struct{}

func (GroupByRegion) Map(match *query.Match[CountryID, Country]) (*query.Match[CountryID, Country], error) {
	match.ReplaceKeys(match.Feature.Region)
	return match, nil
}

type MostPopulated struct{}

func (MostPopulated) Reduce(result *query.Result[CountryID, Country], match *query.Match[CountryID, Country]) error {
	for _, key := range match.ResultKeys {

		err := result.Update(key, func(entry *query.ResultEntry[CountryID, Country]) error {

			if len(entry.Features) == 0 {
				entry.Features = []Country{match.Feature}
				return nil
			}

			existingCountry := entry.Features[0]
			currentCountry := match.Feature

			if existingCountry.Population < currentCountry.Population {
				entry.Features = []Country{match.Feature}
			}
			return nil
		})
		if err != nil {
			return err
		}
	}

	return nil
}

func main() {
	qb := query.Build[CountryID, Country]()
	stream := qb.StreamTo(MostPopulated{})
	stream.Map(GroupByRegion{})
	query := qb.Query() // Map(MostPopulatedByRegion{}).Query()
	for _, country := range countries {
		query.Scan(country)
	}
	fmt.Println("Most populated countries per region:", len(query.Distinct()))
	printNamesSorted(query.Distinct())
}

var bounds = [][]primitives.Point{

	{
		{12.44450569152832, 41.89978557507729},
		{12.459547519683836, 41.89978557507729},
		{12.459547519683836, 41.907946360630994},
		{12.44450569152832, 41.907946360630994},
	},

	{
		{-172.7874755859375, -9.66573839518868},
		{-170.947265625, -9.66573839518868},
		{-170.947265625, -8.303905908124174},
		{-172.7874755859375, -8.303905908124174},
	},

	{
		{-170.13702392578125, -19.265776189877485},
		{-169.5849609375, -19.265776189877485},
		{-169.5849609375, -18.818567424622376},
		{-170.13702392578125, -18.818567424622376},
	},

	{
		{174.74853515625, -11.059820828563412},
		{180.296630859375, -11.059820828563412},
		{180.296630859375, -5.397273407690904},
		{174.74853515625, -5.397273407690904},
	},

	{
		{166.79443359375, -0.6227752122036241},
		{167.07595825195312, -0.6227752122036241},
		{167.07595825195312, -0.4051174740026618},
		{166.79443359375, -0.4051174740026618},
	},

	{
		{14.04052734375, 48.922499263758255},
		{24.27978515625, 48.922499263758255},
		{24.27978515625, 54.99022172004893},
		{14.04052734375, 54.99022172004893},
	},

	{
		{21.665039062499996, 44.02442151965934},
		{40.341796875, 44.02442151965934},
		{40.341796875, 52.482780222078226},
		{21.665039062499996, 52.482780222078226},
	},
}

func makeRect(points []primitives.Point) *primitives.Rect {
	p := points[0]
	op := points[2]
	rect, err := primitives.NewRect(p, op[0]-p[0], op[1]-p[1])
	if err != nil {
		panic(err)
	}
	return rect
}

func printNamesSorted(features []Country) {
	names := make([]string, 0)
	for _, f := range features {
		names = append(names, f.Name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Println(name)
	}
}
Output:

Most populated countries per region: 3
Nauru
Niue
Ukraine
Example (PreconditionsUsingPredicates)

This example uses an example spatial feature implementation. See https://github.com/bilus/fencer/blob/master/query/query_test.go for more details.

package main

import (
	"fmt"
	"strconv"

	"github.com/bilus/fencer/primitives"
	"github.com/bilus/fencer/query"
	"github.com/bilus/fencer/testutil"
)

type CountryID int

func (id CountryID) String() string {
	return strconv.Itoa(int(id))
}

type Country struct {
	ID           CountryID
	Name         string
	Population   int
	Change       float64
	Region       string
	BoundingRect *primitives.Rect
}

func (c Country) Key() CountryID {
	return c.ID
}

func (c Country) Contains(p primitives.Point) (bool, error) {
	return testutil.Contains(*c.BoundingRect, p), nil
}

func (c Country) Bounds() *primitives.Rect {
	return c.BoundingRect
}

var countries = []Country{
	{1, "Vatican City", 800, -0.011, "Europe", makeRect(bounds[0])},
	{2, "Tokelau", 1300, 0.014, "Polynesia", makeRect(bounds[1])},
	{3, "Niue", 1600, -0.004, "Polynesia", makeRect(bounds[2])},
	{4, "Tuvalu", 11200, 0.009, "Oceania", makeRect(bounds[3])},
	{5, "Nauru", 11300, 0.001, "Oceania", makeRect(bounds[4])},
	{6, "Poland", 38224, -0.001, "Europe", makeRect(bounds[5])},
	{7, "Ukraine", 44400, 0, "Europe", makeRect(bounds[6])},
}

func main() {
	query := query.Build[CountryID, Country]().Where(
		query.Pred[CountryID, Country](func(country Country) (bool, error) {
			return country.Population > 10000, nil
		}),
	).Query()
	for _, country := range countries {
		query.Scan(country)
	}
	fmt.Println("Countries with population > 10000:", len(query.Distinct()))
}

var bounds = [][]primitives.Point{

	{
		{12.44450569152832, 41.89978557507729},
		{12.459547519683836, 41.89978557507729},
		{12.459547519683836, 41.907946360630994},
		{12.44450569152832, 41.907946360630994},
	},

	{
		{-172.7874755859375, -9.66573839518868},
		{-170.947265625, -9.66573839518868},
		{-170.947265625, -8.303905908124174},
		{-172.7874755859375, -8.303905908124174},
	},

	{
		{-170.13702392578125, -19.265776189877485},
		{-169.5849609375, -19.265776189877485},
		{-169.5849609375, -18.818567424622376},
		{-170.13702392578125, -18.818567424622376},
	},

	{
		{174.74853515625, -11.059820828563412},
		{180.296630859375, -11.059820828563412},
		{180.296630859375, -5.397273407690904},
		{174.74853515625, -5.397273407690904},
	},

	{
		{166.79443359375, -0.6227752122036241},
		{167.07595825195312, -0.6227752122036241},
		{167.07595825195312, -0.4051174740026618},
		{166.79443359375, -0.4051174740026618},
	},

	{
		{14.04052734375, 48.922499263758255},
		{24.27978515625, 48.922499263758255},
		{24.27978515625, 54.99022172004893},
		{14.04052734375, 54.99022172004893},
	},

	{
		{21.665039062499996, 44.02442151965934},
		{40.341796875, 44.02442151965934},
		{40.341796875, 52.482780222078226},
		{21.665039062499996, 52.482780222078226},
	},
}

func makeRect(points []primitives.Point) *primitives.Rect {
	p := points[0]
	op := points[2]
	rect, err := primitives.NewRect(p, op[0]-p[0], op[1]-p[1])
	if err != nil {
		panic(err)
	}
	return rect
}
Output:

Countries with population > 10000: 4
Example (PreconditionsUsingStructs)

This example uses an example spatial feature implementation. See https://github.com/bilus/fencer/blob/master/query/query_test.go for more details.

package main

import (
	"fmt"
	"sort"
	"strconv"

	"github.com/bilus/fencer/primitives"
	"github.com/bilus/fencer/query"
	"github.com/bilus/fencer/testutil"
)

type CountryID int

func (id CountryID) String() string {
	return strconv.Itoa(int(id))
}

type Country struct {
	ID           CountryID
	Name         string
	Population   int
	Change       float64
	Region       string
	BoundingRect *primitives.Rect
}

func (c Country) Key() CountryID {
	return c.ID
}

func (c Country) Contains(p primitives.Point) (bool, error) {
	return testutil.Contains(*c.BoundingRect, p), nil
}

func (c Country) Bounds() *primitives.Rect {
	return c.BoundingRect
}

var countries = []Country{
	{1, "Vatican City", 800, -0.011, "Europe", makeRect(bounds[0])},
	{2, "Tokelau", 1300, 0.014, "Polynesia", makeRect(bounds[1])},
	{3, "Niue", 1600, -0.004, "Polynesia", makeRect(bounds[2])},
	{4, "Tuvalu", 11200, 0.009, "Oceania", makeRect(bounds[3])},
	{5, "Nauru", 11300, 0.001, "Oceania", makeRect(bounds[4])},
	{6, "Poland", 38224, -0.001, "Europe", makeRect(bounds[5])},
	{7, "Ukraine", 44400, 0, "Europe", makeRect(bounds[6])},
}

type PopulationGreaterThan struct {
	threshold int
}

func (p PopulationGreaterThan) IsMatch(feature Country) (bool, error) {
	return feature.Population > p.threshold, nil
}

func main() {
	// This is how you implement struct conditions:
	//
	//   type PopulationGreaterThan struct {
	//   	  threshold int
	//   }

	//   func (p PopulationGreaterThan) IsMatch(feature feature.Feature) (bool, error) {
	//   	  return feature.(*Country).Population > p.threshold, nil
	//   }

	query := query.Build[CountryID, Country]().Where(PopulationGreaterThan{10000}).Query()
	for _, country := range countries {
		query.Scan(country)
	}
	fmt.Println("Countries with population > 10000:", len(query.Distinct()))
	printNamesSorted(query.Distinct())
}

var bounds = [][]primitives.Point{

	{
		{12.44450569152832, 41.89978557507729},
		{12.459547519683836, 41.89978557507729},
		{12.459547519683836, 41.907946360630994},
		{12.44450569152832, 41.907946360630994},
	},

	{
		{-172.7874755859375, -9.66573839518868},
		{-170.947265625, -9.66573839518868},
		{-170.947265625, -8.303905908124174},
		{-172.7874755859375, -8.303905908124174},
	},

	{
		{-170.13702392578125, -19.265776189877485},
		{-169.5849609375, -19.265776189877485},
		{-169.5849609375, -18.818567424622376},
		{-170.13702392578125, -18.818567424622376},
	},

	{
		{174.74853515625, -11.059820828563412},
		{180.296630859375, -11.059820828563412},
		{180.296630859375, -5.397273407690904},
		{174.74853515625, -5.397273407690904},
	},

	{
		{166.79443359375, -0.6227752122036241},
		{167.07595825195312, -0.6227752122036241},
		{167.07595825195312, -0.4051174740026618},
		{166.79443359375, -0.4051174740026618},
	},

	{
		{14.04052734375, 48.922499263758255},
		{24.27978515625, 48.922499263758255},
		{24.27978515625, 54.99022172004893},
		{14.04052734375, 54.99022172004893},
	},

	{
		{21.665039062499996, 44.02442151965934},
		{40.341796875, 44.02442151965934},
		{40.341796875, 52.482780222078226},
		{21.665039062499996, 52.482780222078226},
	},
}

func makeRect(points []primitives.Point) *primitives.Rect {
	p := points[0]
	op := points[2]
	rect, err := primitives.NewRect(p, op[0]-p[0], op[1]-p[1])
	if err != nil {
		panic(err)
	}
	return rect
}

func printNamesSorted(features []Country) {
	names := make([]string, 0)
	for _, f := range features {
		names = append(names, f.Name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Println(name)
	}
}
Output:

Countries with population > 10000: 4
Nauru
Poland
Tuvalu
Ukraine

func (*QueryBuilder[K, F]) Aggregate

func (builder *QueryBuilder[K, F]) Aggregate(aggregator Aggregator[K, F]) *QueryBuilder[K, F]

Aggregate adds a new aggregator.

func (*QueryBuilder[K, F]) Query

func (builder *QueryBuilder[K, F]) Query() Query[K, F]

Query returns a complete constructed query.

func (*QueryBuilder[K, F]) StreamTo

func (builder *QueryBuilder[K, F]) StreamTo(reducer Reducer[K, F]) *streamBuilder[K, F]

StreamTo creates a new aggregator stream and returns its builder.

func (*QueryBuilder[K, F]) Where

func (builder *QueryBuilder[K, F]) Where(condition Condition[K, F]) *QueryBuilder[K, F]

Where adds a filter to the query. Multiple filters act as a logical AND.

type Reducer

type Reducer[K feature.Key, F feature.Feature[K]] interface {
	Reduce(result *Result[K, F], match *Match[K, F]) error
}

Reducer updates result based on a match.

type Result

type Result[K feature.Key, F feature.Feature[K]] struct {
	// contains filtered or unexported fields
}

Result is a map of keys and the corresponding entries containing a query result.

func (*Result[K, F]) Update

func (result *Result[K, F]) Update(key ResultKey, f UpdateFunc[K, F]) error

Update is a method for updating result for a given key.

type ResultEntry

type ResultEntry[K feature.Key, F feature.Feature[K]] struct {
	Features []F
	Meta     interface{}
}

ResultEntry is a list of features associated with a result key with metadata user code can use for caching etc.

type ResultKey

type ResultKey any

ResultKey is a key generated by a mapper, associated with a feature.

type StreamAggregator

type StreamAggregator[K feature.Key, F feature.Feature[K]] struct {
	Mappers []Mapper[K, F]
	Reducer[K, F]
}

StreamAggregator is a an aggregator supporting a sequence of mappers.

func (StreamAggregator[K, F]) Map

func (stream StreamAggregator[K, F]) Map(match *Match[K, F]) (*Match[K, F], error)

Map takes a match and sends it through a sequence of mappers.

type UpdateFunc

type UpdateFunc[K feature.Key, F feature.Feature[K]] func(entry *ResultEntry[K, F]) error

UpdateFunc is a callback passed to Result.Update.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL