From 783b05d83a0255ce933f212354afeccb358e47fc Mon Sep 17 00:00:00 2001
From: Felipe Wu <felipeshiwu@gmail.com>
Date: Thu, 25 Apr 2019 11:13:40 -0300
Subject: [PATCH] [007] Finalizado saida no estilo padrao

Signed-off-by: Felipe Wu <felipeshiwu@gmail.com>
---
 src/adapter/elasticsearch.ts | 93 ++++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 21 deletions(-)

diff --git a/src/adapter/elasticsearch.ts b/src/adapter/elasticsearch.ts
index d3de47bc..8bf3e874 100644
--- a/src/adapter/elasticsearch.ts
+++ b/src/adapter/elasticsearch.ts
@@ -12,6 +12,17 @@ const elasticsearch = require('elasticsearch');
 /**
  * Adapter which connects with a Elasticsearch database.
  */
+interface ViewOperation {
+	opcode?: number;
+	values?: any[];
+	clauses?: any[];
+	sort?: any[];
+	origin?: boolean;
+	operation?: object;
+	id?: string;
+	name?: string;
+}
+
 export class ElasticsearchAdapter extends Adapter {
     /** Information used to connect with a PostgreSQL database. */
     private client: Client;
@@ -57,7 +68,6 @@ export class ElasticsearchAdapter extends Adapter {
 		let partialQuery = this.translateAggs(view, 0);
 		Object.assign(query, {aggs: partialQuery});
 
-		//console.log(JSON.stringify(view, null, 2));
 		return query;
 	}
 
@@ -66,42 +76,32 @@ export class ElasticsearchAdapter extends Adapter {
      * In other words perform a SELECT query.
      * @param view - "Location" from all data should be read.
      * @param cb - Callback function which contains the data read.
-     * @param cb.error - Error information when the method fails.
-     * @param cb.result - Data got from view.
      */
     public getDataFromView(view: View, cb: (error: Error, result?: any[]) => void): void {
 		const query = this.getQueryFromView(view);
-		if (view.clauses.length > 0 || view.dimensions.length == 1) {
-			this.executeQuery(view.operation.values[0].operation.values[0].name, query, cb);
-		} else {
-			this.executeQuery(view.operation.values[0].name, query, cb);
-		}
+		let partialView = view.operation;
+		const index = this.findIndex(partialView);
+		this.executeQuery(index, view, query, cb);
     }
 
     /**
      * Asynchronously executes a query and get its result.
-     * @param query - Query (SQL format) to be executed.
+     * @param query - Query (Elasticsearch DSL format) to be executed.
      * @param cb - Callback function which contains the data read.
      * @param cb.error - Error information when the method fails.
      * @param cb.result - Query result.
      */
-	private executeQuery(index: string, query: object, cb: (error: Error, result?: any[]) => void): void {
+	private executeQuery(index: string, view: View, query: object, cb: (error: Error, result?: any[]) => void): void {
 		this.client.search({
 			index: index.replace(/\"/g, ''),
 			body: query
 		
 		},(err, result) => {
-			cb(err, [result]);
+			let displayResult = this.formateResult(view, [result], 0);
+			cb(err, displayResult);
 		})
 	}	
 	
-	/**
-     * Asynchronously insert one register into a given Source.
-     * @param source - Insertion "location".
-     * @param cb - Callback function which contains the query result.
-     * @param cb.error - Error information when the method fails.
-     * @param cb.result - Query result.
-     */
     public insertIntoSource(source: Source, data: any[], cb: (err: Error, result?: any[]) =>  void): void {
     }
 
@@ -122,6 +122,18 @@ export class ElasticsearchAdapter extends Adapter {
         }
 
     }
+	
+	/** Elasticsearch, unlike the others adapter, need to find its index to do the query,
+	 * so need to use aliasAsName in the config.yaml and run the recursive function
+	 * below to find the index. 
+	 */
+	private findIndex(operation: ViewOperation): string{
+		if (operation.values[0].origin == true) {
+			return operation.values[0].name;
+		}
+		let index = this.findIndex(operation.values[0].operation);
+		return index;
+	}
 
 	private translateAggs(view: View, numDimensions: number): object {
 		if (numDimensions == view.dimensions.length) {
@@ -130,7 +142,7 @@ export class ElasticsearchAdapter extends Adapter {
 			let partialQuery = {};
 			for (let i=0; i<view.metrics.length; i++) {
 				func = this.getAggregateFunction(view.metrics[i].aggregation);
-				aggrName = view.metrics[i].name.toLowerCase();
+				aggrName = view.metrics[i].name;
 				Object.assign(partialQuery, { [aggrName]: {[func]: {field: view.metrics[i].name}}});
 			}
 			return partialQuery;
@@ -138,7 +150,7 @@ export class ElasticsearchAdapter extends Adapter {
 		let returnedQuery = this.translateAggs(view, numDimensions+1);
 
 		if (view.dimensions.length > 0) {
-			let group_by = "group_by_" + view.dimensions[numDimensions].name;
+			let group_by = view.dimensions[numDimensions].name;
 			let dim = view.dimensions[numDimensions].name;
 			if (view.dimensions[numDimensions].dataType < 3) {
 				dim = dim;
@@ -158,11 +170,50 @@ export class ElasticsearchAdapter extends Adapter {
 			Object.assign(aggregation[group_by], {aggs: returnedQuery});
 
 			if (numDimensions == view.dimensions.length - 1 && view.sort.length > 0) {
-				let aggrName = view.sort[0].name.toLowerCase();
+				let aggrName = view.sort[0].name;
 				Object.assign(aggregation[group_by].terms, {order: {[aggrName] : "asc"}});
 			}
 			
 			return aggregation;
 		}
 	}
+
+	private formateResult(view: View, result: any[], numDimensions: number): any[] {
+		let dimensionsResult = {};
+		let back = [];
+		let resultArray: any[] = [];
+		if (numDimensions == 0 && view.dimensions.length > 0) {
+			let firstDim = view.dimensions[0].name;
+			let resultArray: any[] = [];
+			for (let i=0; i< result[0].aggregations[firstDim].buckets.length; i++) {
+				back = this.formateResult(view, [result[0].aggregations[firstDim].buckets[i]], 1);
+				for (let j=0; j<back.length; j++) {
+					Object.assign(back[j], {[firstDim]: result[0].aggregations[firstDim].buckets[i].key});	
+				}
+				resultArray = resultArray.concat(back);
+			}
+			return resultArray;
+		}
+		if (numDimensions == view.dimensions.length) {
+			let metricsResult = {};
+			let findPrefix = result[0];
+			if (view.dimensions.length == 0) {
+				findPrefix = result[0].aggregations;
+			}
+			for (let i=0; i<view.metrics.length; i++) {
+				let met = view.metrics[i].name;
+				Object.assign(metricsResult, {[met]: findPrefix[met].value});
+			}
+			return [metricsResult];
+		}
+		let nDim = view.dimensions[numDimensions].name;
+		for (let i=0; i< result[0][nDim].buckets.length; i++) {
+			back = this.formateResult(view, [result[0][nDim].buckets[i]], numDimensions+1);
+			for (let j=0; j<back.length; j++) {
+				Object.assign(back[j], {[nDim]: result[0][nDim].buckets[i].key});
+			}	
+			resultArray = resultArray.concat(back);
+		}
+		return resultArray;
+	}
 }
-- 
GitLab