Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic field names in record expressions #5207

Open
philrz opened this issue Aug 7, 2024 · 1 comment
Open

Dynamic field names in record expressions #5207

philrz opened this issue Aug 7, 2024 · 1 comment

Comments

@philrz
Copy link
Contributor

philrz commented Aug 7, 2024

tl;dr

It's not currently possible to specify a dynamic field name in a record expression, such as my attempt here to get to output {hi:"bye"}.

$ echo '{my_key: "hi"}' | zq -z 'yield {this["my_key"]':"bye"} -
zq: error parsing Zed at line 1, column 12:
yield {this["my_key"]:bye}
       === ^ ===

Details

Repro is with Zed commit 343ac63.

This originally came up when fielding a user's question in a community Slack thread. In their own words:

this works fine - is there another way to do the 2nd half of this, to “directly” construct the new record without the […] and the drop ?

echo '[{"key":"bear","name":"fozzy"},
      {"key":"bear","name":"smokey the"},
      {"key":"cat","name":"morris"}]' |
 zq -J 'over this | collect(this) by key | this[this.key]:=this.collect | drop key,collect' -

i was trying something like

zq -J 'over this | collect(this) by key | {(this.key):this.collect}' -

but that’s not valid syntax
the tricky part (to me) being the name of the new field needs to be “dynamic” - set to the value.

@nwt ultimately showed the user a way to more directly get their desired result, but also noted:

As you’ve noticed, dynamic field names aren’t currently allowed in record expressions by design, but I don’t see any reason that couldn’t change.

My example in the opening issue text is a simplified take on illustrating this limitation. It's currently possible to get the desired result in a roundabout way, e.g.,

$ zq -version
Version: v1.17.0-14-g343ac63c

$ echo '{my_key: "hi"}' | zq -z 'over flatten(this) => (yield [{key:value,value:"bye"}] | unflatten(this))' -
{hi:"bye"}

However it's probably a tall order to expect users to come up with that on their own.

@philrz
Copy link
Contributor Author

philrz commented Aug 8, 2024

In a group discussion about this one, I was reminded that while this isn't yet possible via record expressions, we did previously make this possible via put and cut (#4795), which provides a cleaner interim workaround, e.g.,

$ zq -version
Version: v1.17.0-15-g54a5a15e

$ echo '{my_key: "hi"}' | zq -z 'cut this[my_key]:="bye"' -
{hi:"bye"}

Back on the subject of doing this via record expressions, @mccanne did express some nervousness about the potential for users to explode the number of types if we make it super easy to create dynamic keys via record expressions, though we certainly understand it's something people will sometimes want to do. An approach the group seemed to like was to point users toward using Zed map types whenever possible (e.g., create them via the collect_map aggregate function), then make it easy to cast those maps into record types if that's what they ultimately want.

See also: #2894, #4565

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant