Manual Reference Source

app/modules/entities/crud/aggregation.js

  1. // @flow
  2. const _ = require('lodash');
  3.  
  4. class Aggregation {
  5. _name: string;
  6. _object: Object;
  7. _field: ?string;
  8.  
  9. constructor(name: string, object: Object = {}) {
  10. this._name = name;
  11. this._object = object;
  12. this._field = 'field' in object ? object.field : null;
  13. }
  14.  
  15. get name(): string {
  16. return this._name;
  17. }
  18.  
  19. field(f: string) {
  20. this._field = f;
  21. return this;
  22. }
  23.  
  24. generate(): Object {
  25. return this._object;
  26. }
  27. }
  28.  
  29. class TopHitsAggregation extends Aggregation {
  30. _size: number;
  31. _from: number;
  32. _sort: Array<Object>;
  33. _source: ?Object;
  34.  
  35. constructor(name: string, object: Object = {}) {
  36. super(name, object);
  37. this._name = name;
  38. this._object = object;
  39. this._size = 'size' in object ? object.size : 0;
  40. this._from = 'from' in object ? object.from : 0;
  41. this._sort = 'sort' in object ? object.sort : [];
  42. this._source = '_source' in object ? object._source : null;
  43. }
  44.  
  45. size(s: number): TopHitsAggregation {
  46. this._size = s;
  47. return this;
  48. }
  49.  
  50. from(f: number): TopHitsAggregation {
  51. this._from = f;
  52. return this;
  53. }
  54.  
  55. sort(s: Array): TopHitsAggregation {
  56. this._sort = s;
  57. return this;
  58. }
  59.  
  60. source(s: ?Object): TopHitsAggregation {
  61. this._source = source;
  62. return this;
  63. }
  64.  
  65. generate(): Object {
  66. const obj = {
  67. [this._name]: {},
  68. };
  69.  
  70. obj[this._name] = {
  71. top_hits: {
  72. sort: this._sort,
  73. size: this._size,
  74. from: this._from,
  75. },
  76. };
  77.  
  78. if (this._source) {
  79. obj[this._name].top_hits._source = this._source;
  80. }
  81.  
  82. return obj;
  83. }
  84. }
  85.  
  86. class MetricAggregation extends Aggregation {
  87. }
  88.  
  89. class SingleValueMetricAggregation extends MetricAggregation {
  90. _missing: any;
  91. constructor(name: string, object: Object = {}) {
  92. super(name, object);
  93. this._missing = 'missing' in object ? object.missing : null;
  94. }
  95.  
  96. missing(v: any) {
  97. if (v == null) {
  98. return this;
  99. }
  100. this._missing = v;
  101. return this;
  102. }
  103.  
  104.  
  105. generate() {
  106. const obj = {
  107. [this._name]: {},
  108. };
  109.  
  110. const subobj = {
  111. field: this._field,
  112. };
  113.  
  114. if (this._missing != null) {
  115. subobj.missing = this._missing;
  116. }
  117.  
  118. const cname = this.constructor.name.toLowerCase().replace('aggregation', '');
  119. if (cname === 'valuecount') {
  120. obj[this._name].value_count = subobj;
  121. } else {
  122. obj[this._name][cname] = subobj;
  123. }
  124. return obj;
  125. }
  126. }
  127.  
  128. class AvgAggregation extends SingleValueMetricAggregation {}
  129. class MinAggregation extends SingleValueMetricAggregation {}
  130. class MaxAggregation extends SingleValueMetricAggregation {}
  131. class SumAggregation extends SingleValueMetricAggregation {}
  132. class ValueCountAggregation extends SingleValueMetricAggregation {
  133. missing() {
  134. // Not existent for this aggregation
  135. return this;
  136. }
  137. }
  138. class CardinalityAggregation extends SingleValueMetricAggregation {
  139. _precision_threshold: number;
  140. constructor(name: string, object: Object = {}) {
  141. super(name, object);
  142. this._precision_threshold = 'precision_threshold' in object ? object.precision_threshold : 3000; // Default in ES;
  143. }
  144.  
  145. precision_threshold(n: number) {
  146. if (typeof n !== 'number') {
  147. return this;
  148. }
  149. this._precision_threshold = n;
  150. return this;
  151. }
  152.  
  153. generate(): Object {
  154. const obj = super.generate();
  155. obj[this._name].cardinality.precision_threshold = this._precision_threshold;
  156. return obj;
  157. }
  158. }
  159.  
  160. class MultiValueMetricAggregation extends SingleValueMetricAggregation {
  161. }
  162.  
  163. class ExtendedStatsAggregation extends MultiValueMetricAggregation {
  164. _sigma: ?number;
  165. constructor(name: string, object: Object = {}) {
  166. super(name, object);
  167. this._sigma = 'sigma' in object ? object.sigma : null;
  168. }
  169.  
  170. sigma(v: number): Aggregation {
  171. this._sigma = v;
  172. return this;
  173. }
  174.  
  175. generate(): Object {
  176. return this;
  177. }
  178. }
  179.  
  180. class StatsAggregation extends MultiValueMetricAggregation {
  181. generate(): Object {
  182. return this;
  183. }
  184. }
  185.  
  186. class PercentilesAggregation extends MultiValueMetricAggregation {
  187. _percents: Array<number>;
  188. _keyed: boolean;
  189. _hdr_significant_value_digits: number;
  190. _hdr: boolean;
  191. constructor(name: string, object: Object = {}) {
  192. super(name, object);
  193. this._percents = 'percents' in object ? object.percents : [];
  194. this._keyed = 'keyed' in object ? object.keyed : true;
  195. this._hdr = 'hdr' in object;
  196. this._hdr_significant_value_digits = 'hdr' in object
  197. && 'number_of_significant_value_digits' in object.hdr ? object.hdr.number_of_significant_value_digits : 3;
  198. }
  199.  
  200. percents(arr: Array<number>): Aggregation {
  201. this._percents = arr;
  202. return this;
  203. }
  204.  
  205. keyed(b: boolean): Aggregation {
  206. this._keyed = b;
  207. return this;
  208. }
  209.  
  210. hdr_significant_digits(d: number): Aggregation {
  211. this._hdr = true;
  212. this._hdr_significant_value_digits = d;
  213. return this;
  214. }
  215.  
  216. generate(): Object {
  217. return this;
  218. }
  219. }
  220.  
  221. class PercentileRanksAggregation extends PercentilesAggregation {
  222. _values: Array<number>;
  223. constructor(name: string, object: Object = {}) {
  224. super(name, object);
  225. this._values = 'values' in object ? object.values : [];
  226. }
  227.  
  228. values(arr: Array<number>): Aggregation {
  229. this._values = arr;
  230. return this;
  231. }
  232.  
  233. generate(): Object {
  234. return this;
  235. }
  236. }
  237.  
  238. class BucketAggregation extends Aggregation {
  239. _sub_aggregations: Array<Aggregation>;
  240. _keyed: boolean;
  241. constructor(name: string, object: Object = {}) {
  242. super(name, object);
  243. this._sub_aggregations = [];
  244. this._keyed = 'keyed' in object ? object.keyed : false;
  245. }
  246.  
  247. aggregation(agg: Aggregation) {
  248. this._sub_aggregations.push(agg);
  249. return this;
  250. }
  251. }
  252.  
  253. class NestedAggregation extends BucketAggregation {
  254. _path: ?string;
  255. constructor(name: string, object: Object = {}) {
  256. super(name, object);
  257. this._path = 'path' in object ? object.path : null;
  258. }
  259.  
  260. path(p: string) {
  261. this._path = p;
  262. return this;
  263. }
  264.  
  265. generate() {
  266. return {
  267. [this._name]: {
  268. nested: {
  269. path: this._path,
  270. },
  271. aggs: this._sub_aggregations.reduce((obj, agg) => {
  272. obj = _.merge(obj, agg.generate());
  273. return obj;
  274. }, {}),
  275. },
  276. };
  277. }
  278. }
  279.  
  280. class FilterAggregation extends BucketAggregation {
  281. _query: ?Object;
  282. constructor(name: string, object: Object = {}) {
  283. super(name, object);
  284. this._query = null;
  285. }
  286.  
  287. query(q: Object) {
  288. this._query = q;
  289. return this;
  290. }
  291.  
  292. generate() {
  293. return {
  294. [this._name]: {
  295. filter: this._query == null ? {} : this._query,
  296. aggs: this._sub_aggregations.reduce((obj, agg) => {
  297. obj = _.merge(obj, agg.generate());
  298. return obj;
  299. }, {}),
  300. },
  301. };
  302. }
  303. }
  304.  
  305. class TermsAggregation extends BucketAggregation {
  306. _include: ?string | ?Array<string>;
  307. _exclude: ?string | ?Array<string>;
  308. _missing: any;
  309. _size: number;
  310. _shard_size: number;
  311. _min_doc_count: number;
  312. _shard_min_doc_count: number;
  313. _order: ?Object;
  314.  
  315. constructor(name: string, object: Object = {}) {
  316. super(name, object);
  317. this._include = 'include' in object ? object.include : null;
  318. this._exclude = 'exclude' in object ? object.exclude : null;
  319. this._missing = 'missing' in object ? object.missing : null;
  320. this._size = 'size' in object ? object.size : 10;
  321. this._shard_size = 'shard_size' in object ? object.shard_size : this._size;
  322. this._min_doc_count = 'min_doc_count' in object ?
  323. object.min_doc_count : 1;
  324. this._shard_min_doc_count = 'shard_min_doc_count' in object ?
  325. object.shard_min_doc_count : 1;
  326. // Check with an enum TODO
  327. this._collect_mode = 'collect_mode' in object ? object.collect_mode : null;
  328. this._order = 'order' in object ? this._extract_order(object.order) : null;
  329. }
  330.  
  331. _extract_order(order: Object): ?Object {
  332. if (order && Object.keys(order).length === 1) {
  333. const keys = Object.keys(order);
  334. const key = keys[0];
  335. if (order[key] === 'desc' || order[key] === 'asc') {
  336. return order;
  337. }
  338. return null;
  339. }
  340. return null;
  341. }
  342.  
  343. include(inc: string | Array<string>) {
  344. this._include = inc;
  345. return this;
  346. }
  347.  
  348. exclude(exc: string | Array<string>) {
  349. this._exclude = exc;
  350. return this;
  351. }
  352.  
  353. missing(m: any) {
  354. this._missing = m;
  355. return this;
  356. }
  357.  
  358. size(s: number) {
  359. this._size = s;
  360. return this;
  361. }
  362.  
  363. shard_size(s: number) {
  364. this._shard_size = s;
  365. return this;
  366. }
  367.  
  368. min_doc_count(dc: number) {
  369. this._min_doc_count = dc;
  370. return this;
  371. }
  372.  
  373. shard_min_doc_count(dc: number) {
  374. this._shard_min_doc_count = dc;
  375. return this;
  376. }
  377.  
  378. generate() {
  379. const obj = {
  380. [this._name]: {
  381. terms: {
  382. field: this._field,
  383. },
  384. },
  385. };
  386.  
  387. obj[this._name].terms.size = this._size;
  388. obj[this._name].terms.shard_size = this._shard_size;
  389. obj[this._name].terms.shard_size = this._shard_size;
  390. obj[this._name].terms.min_doc_count = this._min_doc_count;
  391. obj[this._name].terms.shard_min_doc_count = this._shard_min_doc_count;
  392.  
  393. if (this._missing != null) {
  394. obj[this._name].terms.missing = this._missing;
  395. }
  396.  
  397. if (this._include != null) {
  398. obj[this._name].terms.include = this._include;
  399. }
  400.  
  401. if (this._exclude != null) {
  402. obj[this._name].terms.exclude = this._exclude;
  403. }
  404.  
  405. if (this._order != null) {
  406. obj[this._name].terms.order = this._order;
  407. }
  408.  
  409. if (this._sub_aggregations.length > 0) {
  410. obj[this._name].aggs = {};
  411. obj[this._name].aggs = this._sub_aggregations.reduce((o, agg) => {
  412. o = _.merge(o, agg.generate());
  413. return o;
  414. }, obj[this._name].aggs);
  415. }
  416.  
  417. return obj;
  418. }
  419. }
  420.  
  421. class DateHistogramAggregation extends BucketAggregation {
  422. _timezone: ?string;
  423. _offset: ?string;
  424. _format: ?string;
  425. _interval: ?string;
  426. _missing: any;
  427. _shard_size: number;
  428. _min_doc_count: number;
  429. _order: ?Object;
  430.  
  431. constructor(name: string, object: Object = {}) {
  432. super(name, object);
  433. this._missing = 'missing' in object ? object.missing : null;
  434. this._shard_size = 'shard_size' in object ? object.shard_size : this._size;
  435. this._min_doc_count = 'min_doc_count' in object ?
  436. object.min_doc_count : 1;
  437. this._format = 'format' in object ? object.format : null;
  438. this._timezone = 'timezone' in object ? object.timezone : null;
  439. this._interval = 'interval' in object ? object.interval : null;
  440. this._offset = 'offset' in object ? object.offset : null;
  441. this._order = 'order' in object ? this._extract_order(object.order) : null;
  442. }
  443.  
  444. _extract_order(order: Object): ?Object {
  445. if (order && Object.keys(order).length === 1) {
  446. const keys = Object.keys(order);
  447. const key = keys[0];
  448. if (order[key] === 'desc' || order[key] === 'asc') {
  449. return order;
  450. }
  451. return null;
  452. }
  453. return null;
  454. }
  455.  
  456. missing(m: any) {
  457. this._missing = m;
  458. return this;
  459. }
  460.  
  461. shard_size(s: number) {
  462. this._shard_size = s;
  463. return this;
  464. }
  465.  
  466. min_doc_count(dc: number) {
  467. this._min_doc_count = dc;
  468. return this;
  469. }
  470.  
  471. format(f: string): DateHistogramAggregation {
  472. this._format = f;
  473. return this;
  474. }
  475.  
  476. timezone(tz: string): DateHistogramAggregation {
  477. this._timezone = tz;
  478. return this;
  479. }
  480.  
  481. interval(inter: string): DateHistogramAggregation {
  482. this._interval = inter;
  483. return this;
  484. }
  485.  
  486. order(o: ?Object): DateHistogramAggregation {
  487. this._order = this._extract_order(o);
  488. return this;
  489. }
  490.  
  491. generate() {
  492. const obj = {
  493. [this._name]: {
  494. date_histogram: {
  495. field: this._field,
  496. },
  497. },
  498. };
  499.  
  500. obj[this._name].date_histogram.shard_size = this._shard_size;
  501. obj[this._name].date_histogram.shard_size = this._shard_size;
  502. obj[this._name].date_histogram.min_doc_count = this._min_doc_count;
  503.  
  504. if (this._format) {
  505. obj[this._name].date_histogram.format = this._format;
  506. }
  507.  
  508. if (this._timezone) {
  509. obj[this._name].date_histogram.time_zone = this._timezone;
  510. }
  511.  
  512. if (this._interval) {
  513. obj[this._name].date_histogram.interval = this._interval;
  514. }
  515.  
  516. if (this._offset) {
  517. obj[this._name].date_histogram.offset = this._offset;
  518. }
  519.  
  520. if (this._missing != null) {
  521. obj[this._name].date_histogram.missing = this._missing;
  522. }
  523.  
  524. if (this._order != null) {
  525. obj[this._name].date_histogram.order = this._order;
  526. }
  527.  
  528. if (this._sub_aggregations.length > 0) {
  529. obj[this._name].aggs = {};
  530. obj[this._name].aggs = this._sub_aggregations.reduce((o, agg) => {
  531. o = _.merge(o, agg.generate());
  532. return o;
  533. }, obj[this._name].aggs);
  534. }
  535.  
  536. return obj;
  537. }
  538. }
  539.  
  540. module.exports = {
  541. Aggregation,
  542. BucketAggregation,
  543. SingleValueMetricAggregation,
  544. MultiValueMetricAggregation,
  545. AvgAggregation,
  546. MinAggregation,
  547. MaxAggregation,
  548. SumAggregation,
  549. ValueCountAggregation,
  550. CardinalityAggregation,
  551. ExtendedStatsAggregation,
  552. StatsAggregation,
  553. PercentilesAggregation,
  554. PercentileRanksAggregation,
  555. NestedAggregation,
  556. FilterAggregation,
  557. TermsAggregation,
  558. DateHistogramAggregation,
  559. TopHitsAggregation,
  560. };