Best way to handle, e.g., comma-separated lists as a field value?

I have data where each node is part of one or more groups – easiest to store that as a comma-separated list (string). The question is how to then pull that data apart later, e.g. to calculate the number of nodes per group.

import "generate"
import "strings"

// generate some test data with mixed group assignments
gen_groups = [ "a", "b,c", "c" ]
g = generate.from(count:12, fn: (n)=>n, start:now(), stop:now() )
  |> map(fn: (r)=>({ r with groups: gen_groups[r._value%3] }))

// now, calculate the size of each group
// (1) is there an easy way to calc the list of all groups?
all_groups = [ "a", "b", "c" ]
// (2) is there an easier way to replicate records to match against?
g1 = g
  |> map(fn: (r) => ({ r with match: all_groups[0] }) )
g2 = g
  |> map(fn: (r) => ({ r with match: all_groups[1] }) )
g3 = g
  |> map(fn: (r) => ({ r with match: all_groups[2] }) )

union(tables: [g1, g2, g3])
  |> map(fn: (r) => ({ r with _value: if strings.containsStr(v: r.groups, substr: r.match) then 1 else 0 }) )
  |> group(columns: ["match"])
  |> sum()

In (1), I’ve found an equally complex query to calculate the list of all possible groups, but it runs into the same issue as here …

In (2), I have to turn that one query into multiple queries, one for each possible group.

Then I can union the separate tables and do the actual calculations.

Seems like there must be a better way to do this? FWIW, you cannot use strings.split to store the unpacked list of groups; and yes, as written the containsStr call could lead to false positives (probably easiest to prepend/append a comma and search for “,group,”)