Home > Software design >  How to spare & group objects according key-value
How to spare & group objects according key-value

Time:12-31

I'm new on this, those are my first steps. I guess I've started with a not simple case.

Let's see: I have objects, with an ID (name) and a resource group (rgs). Each object may be part of several groups. And what a do need is to get the intersections of the groups.

It is important to say that the object may part of several groups, which are parent-child groups, and I just need to get the parent group. It is easy to identify the parenthoods as they share prefixes.

e.g. Group PROM_FD_ARCNA contains the child groups PROM_FD_ARCNA_TGM and PROM_FD_ARCNA_TGM_TGA. And the child groups contains the objects itself. But, as long as I can get the information from object, it is over.

The parent groups are PROM_FD_ARCNA, PROM_JOB_ICMP and PROM_JOB_WIN. That is to say, I need to get those objects which belong to the intersections of those groups.

The JSON file which looks like:

[
    {
        "id_ci": "487006",
        "name": "LABTNSARWID625",
        "id_ci_class": "host",
        "rgs": "PROM_FD_ARCNA, PROM_FD_ARCNA_TGM, PROM_FD_ARCNA_TGM_TGA"
    },
    {
        "id_ci": "5706",
        "name": "HCCQ2001",
        "id_ci_class": "host",
        "rgs": "PROM_JOB_ICMP"
    },
    {
        "id_ci": "9106",
        "name": "HCC02155",
        "id_ci_class": "host",
        "rgs": "PROM_FD_ARCNA, PROM_FD_ARCNA_TGA, PROM_JOB_ICMP"
    },
    {
        "id_ci": "2306",
        "name": "VM00006",
        "id_ci_class": "host",
        "rgs": "PROM_FD_ARCNA, PROM_FD_ARCNA_TGA, PROM_JOB_WIN, PROM_JOB_WIN_TGA"
    }
]

If my explanation was not good, I need to get a JSON like this:

PROM_FD_ARCNA, PROM_JOB_ICMP
{
"HCC02155"
}

PROM_FD_ARCNA, PROM_JOB_WIN 
{
"VM00006"
}

As those are the intersections.


So far, I tried this:

jq '[.[] | select(.id_ci_class == "host") | select (.rgs | startswith("PROM_FD_ARCNA")) | .rgs = "PROM_FD_ARCNA"] 
| group_by(.rgs) | map({"rgs": .[0].rgs, "Hosts": map(.name)}) '  ./prom_jobs.json >> Step0A.json 
jq '[.[] | select(.id_ci_class == "host") | select (.rgs | startswith("PROM_JOB_WIN")) | .rgs = "PROM_JOB_WIN"] 
| group_by(.rgs) | map({"rgs": .[0].rgs, "Hosts": map(.name)}) '  ./prom_jobs.json >> Step0A.json 
jq '[.[] | select(.id_ci_class == "host") | select (.rgs | startswith("PROM_JOB_ICMP")) | .rgs = "PROM_JOB_ICMP"] 
| group_by(.rgs) | map({"rgs": .[0].rgs, "Hosts": map(.name)}) '  ./prom_jobs.json >> Step0A.json

And the result is:

[
  {
    "rgs": "PROM_FD_ARCNA",
    "Hosts": [
      "LABTNSARWID625",
      "HCC02155",
      "VM00006"
    ]
  }
]
[
  {
    "rgs": "PROM_JOB_WIN",
    "Hosts": [
      "VM00006"
    ]
  }
]
[
  {
    "rgs": "PROM_JOB_ICMP",
    "Hosts": [
      "HCCQ2001",
      "HCC02155"
    ]
  }
]

Of course, the full JSON is quite long and I need to process this as lightweight as possible. Don't know if I've started well or bad.

CodePudding user response:

def to_set(s): reduce s as $_ ( {}; .[ $_ ] = true );

[ "PROM_FD_ARCNA", "PROM_JOB_ICMP", "PROM_JOB_WIN" ] as $roots |

map(
   {
      name,
      has_rg: to_set( .rgs | split( ", " )[] )
   }
) as $hosts |

[
   range( 0;    $roots | length ) as $i |  $roots[ $i ] as $g1 |
   range( $i 1; $roots | length ) as $j |  $roots[ $j ] as $g2 |
   {
      root_rgs: [ $g1, $g2 ],
      names: [
         $hosts[] |
         select( .has_rg[ $g1 ] and .has_rg[ $g2 ] ) |
         .name
      ]
   } |
   select( .names | length > 0 )
]

produces

[
  {
    "root_rgs": [
      "PROM_FD_ARCNA",
      "PROM_JOB_ICMP"
    ],
    "names": [
      "HCC02155"
    ]
  },
  {
    "root_rgs": [
      "PROM_FD_ARCNA",
      "PROM_JOB_WIN"
    ],
    "names": [
      "VM00006"
    ]
  }
]

Demo on jqplay

  • Related