Using a filter map

version: >= 20220422

It’s a common OpenAF practice to use the $from construct to build queries around arrays:

// Querying files (excluding folders) and get a list of filenames sorted by size
var sortedList = $from( io.listFiles(".").files )
                 .equals("isFile", true)
                 .sort("-size")
                 .select({ filename: "n/a", size: - 1 })

It’s a powerfull tool to declare queries to arrays but in advance cases (like nAttrMon and others) you might want to configure these queries from a YAML/JSON map. To make it easier you can use ow.obj.filter:

init:
  myFilter:
    where:
    - cond: equals
      args:
      - isFile
      - true
    transform:
    - func: sort
      args:
      - "-size"
    select:
      canonicalPath: n/a
      size         : -1

todo:
- Run my filter

jobs:
- name : Run my filter
  check:
    in:
      path: isString.default(".")
  exec : |
    ow.loadObj()
    args.result = ow.obj.filter( io.listFiles(args.path).files, args.init.myFilter )

    ow.oJob.output(args.result, args)

In the above ojob all the $from construct has been “outsourced” to the myFilter map. Sure it seems a lot more than the simple OpenAF javascript code but it now allows it to be customized without any changes on the code and placed as part of any JSON/YAML map construct needed without having to expose the code itself directly.

If needed the code can still control the select map entry to ensure it gets the data needed

Running the above ojob would return something similar to:

$ ojob test.yaml __format=table
>> [Run my filter] | 300511 | STARTED ──────────────────
        canonicalPath        │  size  
─────────────────────────────┼────────
/root/kubectl                │46931968
/root/.viminfo               │14695   
/root/.bash_history          │12950   
/root/.openaf-console_history│7695    
/root/test.md                │4864    
/root/.bashrc                │3106  

<< [Run my filter] | 300511 | SUCCESS ══════════════════

Understanding ow.obj.filter map

The filter map is composed of the following sections:

section $from correspondent
where all the filtering functions like equals, less, match, contains, etc… It expects a cond and then an array of args
transform all the transforming functions like attach, sort, etc… It expects a func and then an array of args
select a map or the code for a select function
selector all the selector functions like at, min, max, etc… It expects a func and then an array of args

In-map coding

If you really need to code functions in the map (should be discouraged) where are some examples:

Adding an attach code:

myFilter:
  // ...
  transform:
  - func: attach
    args:
    - lastAccess
    - !!js/eval elem => new Date(elem.lastAccess)
  - func: sort
    args:
    - lastAccess
  // ...

In order to use “!!js/eval” in __YAMLFormat.unsafe flag must be true

Adding a select code:

myFilter:
  // ...
  select: |
    elem.id = sha256( stringify(elem, __, "") )

    return id