From f54119425003e45e6ae050a1a3c8dff8dcd0afd3 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Wed, 28 Apr 2021 20:35:10 +1000 Subject: [PATCH] Added complex merge example --- pkg/yqlib/doc/Multiply (Merge).md | 40 +++++++++++++++++++++++++++++ pkg/yqlib/operator_multiply_test.go | 16 ++++++++++++ 2 files changed, 56 insertions(+) diff --git a/pkg/yqlib/doc/Multiply (Merge).md b/pkg/yqlib/doc/Multiply (Merge).md index 7bff0786..181c2b62 100644 --- a/pkg/yqlib/doc/Multiply (Merge).md +++ b/pkg/yqlib/doc/Multiply (Merge).md @@ -29,6 +29,46 @@ will output 12 ``` +## Merge arrays of objects together, matching on a key +It's a complex command, the trickyness comes from needing to have the right context in the expressions. +First we save the second array into a variable '$two' which lets us reference it later. +We then need to update the first array. We will use the relative update (|=) because we need to update relative to the current element of the array in the LHS in the RHS expression. +We set the current element of the first array as $cur. Now we multiply (merge) $cur with the matching entry in $two, by passing $two through a select filter. + + +Given a sample.yml file of: +```yaml +- a: apple + b: appleB +- a: kiwi + b: kiwiB +- a: banana + b: bananaB +``` +And another sample another.yml file of: +```yaml +- a: banana + c: bananaC +- a: apple + b: appleB2 +- a: dingo + c: dingoC +``` +then +```bash +yq eval-all '(select(fi==1) | .[]) as $two | select(fi==0) | .[] |= (. as $cur | $cur * ($two | select(.a == $cur.a)))' sample.yml another.yml +``` +will output +```yaml +- a: apple + b: appleB2 +- a: kiwi + b: kiwiB +- a: banana + b: bananaB + c: bananaC +``` + ## Merge objects together, returning merged result only Given a sample.yml file of: ```yaml diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go index 6c2017a7..a9adf8da 100644 --- a/pkg/yqlib/operator_multiply_test.go +++ b/pkg/yqlib/operator_multiply_test.go @@ -24,6 +24,12 @@ list2: - "123" ` +var mergeArraysObjectKeysText = `It's a complex command, the trickyness comes from needing to have the right context in the expressions. +First we save the second array into a variable '$two' which lets us reference it later. +We then need to update the first array. We will use the relative update (|=) because we need to update relative to the current element of the array in the LHS in the RHS expression. +We set the current element of the first array as $cur. Now we multiply (merge) $cur with the matching entry in $two, by passing $two through a select filter. +` + var multiplyOperatorScenarios = []expressionScenario{ { description: "Multiply integers", @@ -123,6 +129,16 @@ var multiplyOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::{a: {also: [1]}, b: {also: [1]}}\n", }, }, + { + description: "Merge arrays of objects together, matching on a key", + subdescription: mergeArraysObjectKeysText, + document: `[{a: apple, b: appleB}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB}]`, + document2: `[{a: banana, c: bananaC}, {a: apple, b: appleB2}, {a: dingo, c: dingoC}]`, + expression: `(select(fi==1) | .[]) as $two | select(fi==0) | .[] |= (. as $cur | $cur * ($two | select(.a == $cur.a)))`, + expected: []string{ + "D0, P[], (doc)::[{a: apple, b: appleB2}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB, c: bananaC}]\n", + }, + }, { description: "Merge objects together, returning merged result only", document: `{a: {field: me, fieldA: cat}, b: {field: {g: wizz}, fieldB: dog}}`,