Is there a way for a macro or something similar to take a search (code) as a parameter, reuse across computing two different things, join the results, and return?
Ex: compute both indegree and outdegree for an edge list
Input edge list:
src dst
0 0
0 1
1 0
1 1
2 0
Output node degrees:
idx inDegree outDegree
0 3 2
1 2 2
2 0 1
Search pseudocode:
computeInOutDegrees('search source="trips" | table src dst')
or
search source="trips" | table src dst | computeInOutDegrees
Macro pseudocode:
computeInOutDegrees($qry$)
$qry$ | stats count(src) as outDegree by dst | rename dst as idx // table of "idx outDegree"
| join idx [$qry$ | stats count(dst) as inDegree by src | rename src as idx] //combine with "idx inDegree"
You could actually accomplish this with a macro that takes no arguments, assuming that you know the input search has fields src and dst to work on:
Your search would be:
source="trips" | table src dst | `computeInOutDegrees`
and your computeInOutDegrees
macro would be:
fields - idx | appendpipe [stats count(src) as outDegree by dst | rename dst as idx] | appendpipe [stats count(dst) as inDegree by src | rename src as idx] | stats max(*) as * by idx | fillnull
Step by step:
fields - idx
- ensures that the input does not have a field called idxappendpipe []
- adds the idx in-degree and idx out-degree pairings to the result set. stats max(*) as * by idx
- combines the two parings together based on common idx fieldsfillnull
- ensures any cell without a value is 0.This solution is neat! Essentially, it suggests intermediate computations can add new events, and as long as they're described in a way that subsequent ones can skip them while still giving the appropriate end result, it's good.
This sounds right for this particular scenario, but as is, doesn't seem generally applicable. I'll keep marked unanswered in case the general scenario can get solved, but as is, awesome. Thank you!
Edit: here's the corresponding macro
degree(src,dst,node,in,out,degree)
appendpipe [
stats count($src$) as $in$ by $dst$
| rename $dst$ as $node$]
| appendpipe [
stats count($dst$) as $out$ by $src$
| rename $src$ as $node$]
| stats max(*) as * by $node$
| fillnull $in$ $out$
| eval $degree$=$in$+$out$
One side note... consider if you want the stats in the appendpipe commands to use count(X)
or distinct_count(X)
the former would count duplicate pairings twice, whereas the latter woud count them once.