yq/pkg/yqlib/operator_group_by.go

75 lines
2.0 KiB
Go
Raw Normal View History

2021-10-26 04:07:50 +00:00
package yqlib
import (
"container/list"
"fmt"
"github.com/elliotchance/orderedmap"
)
2023-04-08 11:27:47 +00:00
func processIntoGroups(d *dataTreeNavigator, context Context, rhsExp *ExpressionNode, node *CandidateNode) (*orderedmap.OrderedMap, error) {
2021-10-26 04:07:50 +00:00
var newMatches = orderedmap.NewOrderedMap()
2023-04-08 11:27:47 +00:00
for _, child := range node.Content {
2021-10-26 04:07:50 +00:00
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(child), rhsExp)
if err != nil {
return nil, err
}
keyValue := "null"
if rhs.MatchingNodes.Len() > 0 {
first := rhs.MatchingNodes.Front()
keyCandidate := first.Value.(*CandidateNode)
2023-04-08 11:27:47 +00:00
keyValue = keyCandidate.Value
2021-10-26 04:07:50 +00:00
}
groupList, exists := newMatches.Get(keyValue)
if !exists {
groupList = list.New()
newMatches.Set(keyValue, groupList)
}
groupList.(*list.List).PushBack(node)
}
return newMatches, nil
}
func groupBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("-- groupBy Operator")
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
2023-04-08 11:27:47 +00:00
candidateNode := candidate.unwrapDocument()
2021-10-26 04:07:50 +00:00
2023-04-08 11:27:47 +00:00
if candidateNode.Kind != SequenceNode {
2021-10-26 04:07:50 +00:00
return Context{}, fmt.Errorf("Only arrays are supported for group by")
}
newMatches, err := processIntoGroups(d, context, expressionNode.RHS, candidateNode)
2021-10-26 04:07:50 +00:00
if err != nil {
return Context{}, err
}
2023-04-08 11:27:47 +00:00
resultNode := candidate.CreateReplacement(SequenceNode, "!!seq", "")
2021-10-26 04:07:50 +00:00
for groupEl := newMatches.Front(); groupEl != nil; groupEl = groupEl.Next() {
2023-04-08 11:27:47 +00:00
groupResultNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
2021-10-26 04:07:50 +00:00
groupList := groupEl.Value.(*list.List)
for groupItem := groupList.Front(); groupItem != nil; groupItem = groupItem.Next() {
2023-04-08 11:27:47 +00:00
groupResultNode.Content = append(groupResultNode.Content, groupItem.Value.(*CandidateNode))
2021-10-26 04:07:50 +00:00
}
resultNode.Content = append(resultNode.Content, groupResultNode)
}
2023-04-08 11:27:47 +00:00
results.PushBack(resultNode)
2021-10-26 04:07:50 +00:00
}
return context.ChildContext(results), nil
}