Skip to content

Commit

Permalink
Updated post-aggs to be easier to express and use
Browse files Browse the repository at this point in the history
  • Loading branch information
Deep Ganguli committed Nov 18, 2013
1 parent 71e2753 commit 3fae2b7
Showing 1 changed file with 49 additions and 41 deletions.
90 changes: 49 additions & 41 deletions pydruid/utils/postaggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,52 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pprint as pp
import re

# determine whether arguments are strings or numeric constants
def is_numeric(field):
for obj in [int, float, long]:
try:
obj(field)
return True
except:
pass

return False

# specify field type as source field name (string) or constant and build json
def field_spec(field):
if is_numeric(field):
return {"type" : "constant",
"name" : "constant_%d" % int(field),
"value" : field}
else:
return {"type" : "fieldAccess",
"fieldName" : field}

# use regex to extract fields and operand from user-submitted postAgg string
def parse_calc(postAggOpString):
fields = []
rgx = "(.+)[ ]?([*+/-])[ ]?(.+)"
postAggOp = re.findall(rgx, postAggOpString).pop()

if postAggOp:
operation = postAggOp[0]
fn = postAggOp[1]
fields.append(field_spec(postAggOp[0]))
fields.append(field_spec(postAggOp[2]))
base = {"type" : "arithmetic",
"fn" : fn,
"fields" : fields}
return base
else:
raise Exception("Not a valid postAggregation operation")
from __future__ import division

class Postaggregator:

def __init__(self, fn, fields, name):

self.post_aggregator = {'type' : 'arithmetic',
'name' : name,
'fn' : fn,
'fields': fields}
self.name = name

def __mul__(self, other):
return Postaggregator('*', self.fields(other), self.name + 'mul' + other.name)


def __sub__(self, other):
return Postaggregator('-', self.fields(other), self.name + 'sub' + other.name)


def __add__(self, other):
return Postaggregator('+', self.fields(other), self.name + 'add' + other.name)

def __truediv__(self, other):
return Postaggregator('/', self.fields(other), self.name + 'div' + other.name)

def fields(self, other):
return [self.post_aggregator, other.post_aggregator]


class Field(Postaggregator):

def __init__(self, aggregatorName):

self.post_aggregator = {'type' : 'fieldAccess', 'fieldName' : aggregatorName}
self.name = aggregatorName


class Const(Postaggregator):

def __init__(self, value, output_name=None):

if output_name is None:
name = 'const'
else:
name = output_name

self.post_aggregator = {'type' : 'constant', 'name' : name, 'value' : value}
self.name = name

0 comments on commit 3fae2b7

Please sign in to comment.