blob: ebc4968ba821be29d31566fd5de53bb20a43506c [file] [log] [blame]
"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[3042],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>k});var n=a(67294);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function l(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function o(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var p=n.createContext({}),s=function(e){var t=n.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):l(l({},t),e)),a},d=function(e){var t=s(e.components);return n.createElement(p.Provider,{value:t},e.children)},g="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,p=e.parentName,d=o(e,["components","mdxType","originalType","parentName"]),g=s(a),u=r,k=g["".concat(p,".").concat(u)]||g[u]||m[u]||i;return a?n.createElement(k,l(l({ref:t},d),{},{components:a})):n.createElement(k,l({ref:t},d))}));function k(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,l=new Array(i);l[0]=u;var o={};for(var p in t)hasOwnProperty.call(t,p)&&(o[p]=t[p]);o.originalType=e,o[g]="string"==typeof e?e:r,l[1]=o;for(var s=2;s<i;s++)l[s]=a[s];return n.createElement.apply(null,l)}return n.createElement.apply(null,a)}u.displayName="MDXCreateElement"},20959:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>d,contentTitle:()=>p,default:()=>k,frontMatter:()=>o,metadata:()=>s,toc:()=>g});var n=a(87462),r=a(63366),i=(a(67294),a(3905)),l=["components"],o={id:"post-aggregations",title:"Post-aggregations"},p=void 0,s={unversionedId:"querying/post-aggregations",id:"querying/post-aggregations",title:"Post-aggregations",description:"\x3c!--",source:"@site/docs/28.0.1/querying/post-aggregations.md",sourceDirName:"querying",slug:"/querying/post-aggregations",permalink:"/docs/28.0.1/querying/post-aggregations",draft:!1,tags:[],version:"current",frontMatter:{id:"post-aggregations",title:"Post-aggregations"},sidebar:"docs",previous:{title:"Aggregations",permalink:"/docs/28.0.1/querying/aggregations"},next:{title:"Expressions",permalink:"/docs/28.0.1/querying/math-expr"}},d={},g=[{value:"Arithmetic post-aggregator",id:"arithmetic-post-aggregator",level:3},{value:"Field accessor post-aggregators",id:"field-accessor-post-aggregators",level:3},{value:"Constant post-aggregator",id:"constant-post-aggregator",level:3},{value:"Expression post-aggregator",id:"expression-post-aggregator",level:3},{value:"Greatest / Least post-aggregators",id:"greatest--least-post-aggregators",level:3},{value:"JavaScript post-aggregator",id:"javascript-post-aggregator",level:3},{value:"HyperUnique Cardinality post-aggregator",id:"hyperunique-cardinality-post-aggregator",level:3},{value:"Example Usage",id:"example-usage",level:2}],m={toc:g},u="wrapper";function k(e){var t=e.components,a=(0,r.Z)(e,l);return(0,i.kt)(u,(0,n.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"}," Apache Druid supports two query languages: ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/sql"},"Druid SQL")," and ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/"},"native queries"),".\nThis document describes the native\nlanguage. For information about functions available in SQL, refer to the\n",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/sql-aggregations"},"SQL documentation"),".")),(0,i.kt)("p",null,"Post-aggregations are specifications of processing that should happen on aggregated values as they come out of Apache Druid. If you include a post aggregation as part of a query, make sure to include all aggregators the post-aggregator requires."),(0,i.kt)("p",null,"There are several post-aggregators available."),(0,i.kt)("h3",{id:"arithmetic-post-aggregator"},"Arithmetic post-aggregator"),(0,i.kt)("p",null,"The arithmetic post-aggregator applies the provided function to the given\nfields from left to right. The fields can be aggregators or other post aggregators."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"arithmetic"'),"."),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fn")),(0,i.kt)("td",{parentName:"tr",align:null},"Supported functions are ",(0,i.kt)("inlineCode",{parentName:"td"},"+"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"-"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"*"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"/"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"pow")," and ",(0,i.kt)("inlineCode",{parentName:"td"},"quotient")),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fields")),(0,i.kt)("td",{parentName:"tr",align:null},"List of post-aggregator specs which define inputs to the ",(0,i.kt)("inlineCode",{parentName:"td"},"fn")),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"ordering")),(0,i.kt)("td",{parentName:"tr",align:null},"If no ordering (or ",(0,i.kt)("inlineCode",{parentName:"td"},"null"),") is specified, the default floating point ordering is used. ",(0,i.kt)("inlineCode",{parentName:"td"},"numericFirst")," ordering always returns finite values first, followed by ",(0,i.kt)("inlineCode",{parentName:"td"},"NaN"),", and infinite values last."),(0,i.kt)("td",{parentName:"tr",align:null},"No")))),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Note"),":"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"/")," division always returns ",(0,i.kt)("inlineCode",{parentName:"li"},"0")," if dividing by",(0,i.kt)("inlineCode",{parentName:"li"},"0"),", regardless of the numerator."),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("inlineCode",{parentName:"li"},"quotient")," division behaves like regular floating point division"),(0,i.kt)("li",{parentName:"ul"},"Arithmetic post-aggregators always use floating point arithmetic.")),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "type" : "arithmetic",\n "name" : "mult",\n "fn" : "*",\n "fields": [\n {"type": "fieldAccess", "fieldName": "someAgg"},\n {"type": "fieldAccess", "fieldName": "someOtherAgg"}\n ]\n}\n')),(0,i.kt)("h3",{id:"field-accessor-post-aggregators"},"Field accessor post-aggregators"),(0,i.kt)("p",null,"These post-aggregators return the value produced by the specified ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/dimensionspecs"},"dimension")," or ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/aggregations"},"aggregator"),"."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"fieldAccess"')," or ",(0,i.kt)("inlineCode",{parentName:"td"},'"finalizingFieldAccess"'),". Use type ",(0,i.kt)("inlineCode",{parentName:"td"},'"fieldAccess"')," to return the raw aggregation object, or use type ",(0,i.kt)("inlineCode",{parentName:"td"},'"finalizingFieldAccess"')," to return a finalized value, such as an estimated cardinality."),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes if defined as a standalone post-aggregation, but may be omitted if used inline to some other post-aggregator in a ",(0,i.kt)("inlineCode",{parentName:"td"},"fields")," list")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fieldName")),(0,i.kt)("td",{parentName:"tr",align:null},"The output name of the dimension or aggregator to reference"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")))),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{ "type" : "fieldAccess", "name": "someField", "fieldName" : "someAggregator" }\n')),(0,i.kt)("p",null,"or"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{ "type" : "finalizingFieldAccess", "name": "someFinalizedField", "fieldName" : "someAggregator" }\n')),(0,i.kt)("h3",{id:"constant-post-aggregator"},"Constant post-aggregator"),(0,i.kt)("p",null,"The constant post-aggregator always returns the specified value."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"constant"')),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"value")),(0,i.kt)("td",{parentName:"tr",align:null},"The constant value"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")))),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{ "type" : "constant", "name" : "someConstant", "value" : 1234 }\n')),(0,i.kt)("h3",{id:"expression-post-aggregator"},"Expression post-aggregator"),(0,i.kt)("p",null,"The expression post-aggregator is defined using a Druid ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/querying/math-expr"},"expression"),"."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"expression"')),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"expression")),(0,i.kt)("td",{parentName:"tr",align:null},"Native Druid ",(0,i.kt)("a",{parentName:"td",href:"/docs/28.0.1/querying/math-expr"},"expression")," to compute, may refer to any dimension or aggregator output names"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"ordering")),(0,i.kt)("td",{parentName:"tr",align:null},"If no ordering (or ",(0,i.kt)("inlineCode",{parentName:"td"},"null"),') is specified, the "natural" ordering is used. ',(0,i.kt)("inlineCode",{parentName:"td"},"numericFirst")," ordering always returns finite values first, followed by ",(0,i.kt)("inlineCode",{parentName:"td"},"NaN"),", and infinite values last. If the expression produces array or complex types, specify ",(0,i.kt)("inlineCode",{parentName:"td"},"ordering")," as null and use ",(0,i.kt)("inlineCode",{parentName:"td"},"outputType")," instead to use the correct type native ordering."),(0,i.kt)("td",{parentName:"tr",align:null},"No")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"outputType")),(0,i.kt)("td",{parentName:"tr",align:null},"Output type is optional, and can be any native Druid type: ",(0,i.kt)("inlineCode",{parentName:"td"},"LONG"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"FLOAT"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"DOUBLE"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"STRING"),", ",(0,i.kt)("inlineCode",{parentName:"td"},"ARRAY")," types (e.g. ",(0,i.kt)("inlineCode",{parentName:"td"},"ARRAY<LONG>"),"), or ",(0,i.kt)("inlineCode",{parentName:"td"},"COMPLEX")," types (e.g. ",(0,i.kt)("inlineCode",{parentName:"td"},"COMPLEX<json>"),"). If not specified, the output type will be inferred from the ",(0,i.kt)("inlineCode",{parentName:"td"},"expression"),". If specified and ",(0,i.kt)("inlineCode",{parentName:"td"},"ordering")," is null, the type native ordering will be used for sorting values. If the expression produces array or complex types, this value must be non-null to ensure the correct ordering is used. If ",(0,i.kt)("inlineCode",{parentName:"td"},"outputType")," does not match the actual output type of the ",(0,i.kt)("inlineCode",{parentName:"td"},"expression"),", the value will be attempted to coerced to the specified type, possibly failing if coercion is not possible."),(0,i.kt)("td",{parentName:"tr",align:null},"No")))),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "type": "expression",\n "name": "someExpression",\n "expression": "someAgg + someOtherAgg",\n "ordering": null,\n "outputType": "LONG" \n}\n')),(0,i.kt)("h3",{id:"greatest--least-post-aggregators"},"Greatest / Least post-aggregators"),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"doubleGreatest")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"longGreatest")," computes the maximum of all fields and Double.NEGATIVE_INFINITY.\n",(0,i.kt)("inlineCode",{parentName:"p"},"doubleLeast")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"longLeast")," computes the minimum of all fields and Double.POSITIVE_INFINITY."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"doubleGreatest"'),", ",(0,i.kt)("inlineCode",{parentName:"td"},'"doubleLeast"'),", ",(0,i.kt)("inlineCode",{parentName:"td"},'"longGreatest"'),", or ",(0,i.kt)("inlineCode",{parentName:"td"},'"longLeast"'),"."),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fields")),(0,i.kt)("td",{parentName:"tr",align:null},"List of post-aggregator specs which define inputs to the greatest or least function"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")))),(0,i.kt)("p",null,"The difference between the ",(0,i.kt)("inlineCode",{parentName:"p"},"doubleMax")," aggregator and the ",(0,i.kt)("inlineCode",{parentName:"p"},"doubleGreatest")," post-aggregator is that ",(0,i.kt)("inlineCode",{parentName:"p"},"doubleMax")," returns the highest value of\nall rows for one specific column while ",(0,i.kt)("inlineCode",{parentName:"p"},"doubleGreatest")," returns the highest value of multiple columns in one row. These are similar to the\nSQL ",(0,i.kt)("inlineCode",{parentName:"p"},"MAX")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"GREATEST")," functions."),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "type" : "doubleGreatest",\n "name" : "theGreatest",\n "fields": [\n { "type": "fieldAccess", "fieldName": "someAgg" },\n { "type": "fieldAccess", "fieldName": "someOtherAgg" }\n ]\n}\n')),(0,i.kt)("h3",{id:"javascript-post-aggregator"},"JavaScript post-aggregator"),(0,i.kt)("p",null,"Applies the provided JavaScript function to the given fields. Fields are passed as arguments to the JavaScript function in the given order."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"javascript"')),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fieldNames")),(0,i.kt)("td",{parentName:"tr",align:null},"List of input dimension or aggregator output names"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"function")),(0,i.kt)("td",{parentName:"tr",align:null},"String javascript function which accepts ",(0,i.kt)("inlineCode",{parentName:"td"},"fieldNames")," as arguments"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")))),(0,i.kt)("p",null,"Example:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "type": "javascript",\n "name": "someJavascript",\n "fieldNames" : ["someAgg", "someOtherAgg"],\n "function": "function(someAgg, someOtherAgg) { return 100 * Math.abs(someAgg) / someOtherAgg;"\n}\n')),(0,i.kt)("admonition",{type:"info"},(0,i.kt)("p",{parentName:"admonition"}," JavaScript-based functionality is disabled by default. Please refer to the Druid ",(0,i.kt)("a",{parentName:"p",href:"/docs/28.0.1/development/javascript"},"JavaScript programming guide")," for guidelines about using Druid's JavaScript functionality, including instructions on how to enable it.")),(0,i.kt)("h3",{id:"hyperunique-cardinality-post-aggregator"},"HyperUnique Cardinality post-aggregator"),(0,i.kt)("p",null,"The hyperUniqueCardinality post aggregator is used to wrap a hyperUnique object such that it can be used in post aggregations."),(0,i.kt)("table",null,(0,i.kt)("thead",{parentName:"table"},(0,i.kt)("tr",{parentName:"thead"},(0,i.kt)("th",{parentName:"tr",align:null},"Property"),(0,i.kt)("th",{parentName:"tr",align:null},"Description"),(0,i.kt)("th",{parentName:"tr",align:null},"Required"))),(0,i.kt)("tbody",{parentName:"table"},(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"type")),(0,i.kt)("td",{parentName:"tr",align:null},"Must be ",(0,i.kt)("inlineCode",{parentName:"td"},'"hyperUniqueCardinality"')),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"name")),(0,i.kt)("td",{parentName:"tr",align:null},"Output name of the post-aggregation"),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")),(0,i.kt)("tr",{parentName:"tbody"},(0,i.kt)("td",{parentName:"tr",align:null},(0,i.kt)("inlineCode",{parentName:"td"},"fieldName")),(0,i.kt)("td",{parentName:"tr",align:null},"The output name of a ",(0,i.kt)("a",{parentName:"td",href:"/docs/28.0.1/querying/aggregations#cardinality-hyperunique"},(0,i.kt)("inlineCode",{parentName:"a"},"hyperUnique")," aggregator")),(0,i.kt)("td",{parentName:"tr",align:null},"Yes")))),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n "type" : "hyperUniqueCardinality",\n "name": "someCardinality",\n "fieldName" : "someHyperunique"\n}\n')),(0,i.kt)("p",null,"It can be used in a sample calculation as so:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n ...\n "aggregations" : [{\n {"type" : "count", "name" : "rows"},\n {"type" : "hyperUnique", "name" : "unique_users", "fieldName" : "uniques"}\n }],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "average_users_per_row",\n "fn" : "/",\n "fields" : [\n { "type" : "hyperUniqueCardinality", "fieldName" : "unique_users" },\n { "type" : "fieldAccess", "name" : "rows", "fieldName" : "rows" }\n ]\n }]\n ...\n')),(0,i.kt)("p",null,'This post-aggregator will inherit the rounding behavior of the aggregator it references. Note that this inheritance\nis only effective if you directly reference an aggregator. Going through another post-aggregator, for example, will\ncause the user-specified rounding behavior to get lost and default to "no rounding".'),(0,i.kt)("h2",{id:"example-usage"},"Example Usage"),(0,i.kt)("p",null,'In this example, let\u2019s calculate a simple percentage using post aggregators. Let\u2019s imagine our data set has a metric called "total".'),(0,i.kt)("p",null,"The format of the query JSON is as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n ...\n "aggregations" : [\n { "type" : "count", "name" : "rows" },\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" }\n ],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "average",\n "fn" : "/",\n "fields" : [\n { "type" : "fieldAccess", "name" : "tot", "fieldName" : "tot" },\n { "type" : "fieldAccess", "name" : "rows", "fieldName" : "rows" }\n ]\n }]\n ...\n}\n')),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n ...\n "aggregations" : [\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" },\n { "type" : "doubleSum", "name" : "part", "fieldName" : "part" }\n ],\n "postAggregations" : [{\n "type" : "arithmetic",\n "name" : "part_percentage",\n "fn" : "*",\n "fields" : [\n { "type" : "arithmetic",\n "name" : "ratio",\n "fn" : "/",\n "fields" : [\n { "type" : "fieldAccess", "name" : "part", "fieldName" : "part" },\n { "type" : "fieldAccess", "name" : "tot", "fieldName" : "tot" }\n ]\n },\n { "type" : "constant", "name": "const", "value" : 100 }\n ]\n }]\n ...\n}\n')),(0,i.kt)("p",null,"The same could be computed using an expression post-aggregator: "),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-json"},'{\n ...\n "aggregations" : [\n { "type" : "doubleSum", "name" : "tot", "fieldName" : "total" },\n { "type" : "doubleSum", "name" : "part", "fieldName" : "part" }\n ],\n "postAggregations" : [{\n "type" : "expression",\n "name" : "part_percentage",\n "expression" : "100 * (part / tot)"\n }]\n ...\n}\n')))}k.isMDXComponent=!0}}]);