mirror of
https://github.com/datahub-project/datahub.git
synced 2025-08-19 22:58:05 +00:00
support the elasticsearch as search engine
This commit is contained in:
parent
d06d732e1f
commit
fba2c90c33
@ -16,8 +16,10 @@ package controllers.api.v1;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import dao.AdvSearchDAO;
|
||||
import dao.SearchDAO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import play.Logger;
|
||||
import play.Play;
|
||||
import play.libs.Json;
|
||||
import play.mvc.Controller;
|
||||
import play.mvc.Result;
|
||||
@ -137,17 +139,46 @@ public class AdvSearch extends Controller
|
||||
}
|
||||
}
|
||||
result.put("status", "ok");
|
||||
String searchEngine = Play.application().configuration().getString(SearchDAO.WHEREHOWS_SEARCH_ENGINE__KEY);
|
||||
|
||||
if (searchOpt != null && searchOpt.has("category"))
|
||||
{
|
||||
String category = searchOpt.get("category").asText();
|
||||
if(category.equalsIgnoreCase("flow"))
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.searchFlows(searchOpt, page, size)));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.elasticSearchFlowJobs(searchOpt, page, size)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.searchFlows(searchOpt, page, size)));
|
||||
}
|
||||
return ok(result);
|
||||
}
|
||||
else if(category.equalsIgnoreCase("metric"))
|
||||
{
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.elasticSearchMetric(searchOpt, page, size)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.searchMetrics(searchOpt, page, size)));
|
||||
}
|
||||
return ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
result.set("result", Json.toJson(AdvSearchDAO.search(searchOpt, page, size)));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.elasticSearch(searchOpt, page, size)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", Json.toJson(AdvSearchDAO.search(searchOpt, page, size)));
|
||||
}
|
||||
|
||||
return ok(result);
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import dao.SearchDAO;
|
||||
import models.DatasetColumn;
|
||||
import play.Play;
|
||||
import play.api.libs.json.JsValue;
|
||||
import play.libs.Json;
|
||||
import play.mvc.Controller;
|
||||
@ -92,51 +93,71 @@ public class Search extends Controller
|
||||
{
|
||||
category = "datasets";
|
||||
}
|
||||
if (StringUtils.isBlank(source))
|
||||
if (StringUtils.isBlank(source) || source.equalsIgnoreCase("all") || source.equalsIgnoreCase("default"))
|
||||
{
|
||||
source = "all";
|
||||
}
|
||||
else if (source.equalsIgnoreCase("default"))
|
||||
{
|
||||
source = "all";
|
||||
isDefault = true;
|
||||
source = null;
|
||||
}
|
||||
|
||||
String searchEngine = Play.application().configuration().getString(SearchDAO.WHEREHOWS_SEARCH_ENGINE__KEY);
|
||||
|
||||
if (category.toLowerCase().equalsIgnoreCase("metric"))
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedMetricByKeyword(category, keyword, page, size));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", SearchDAO.elasticSearchMetricByKeyword(category, keyword, page, size));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedMetricByKeyword(category, keyword, page, size));
|
||||
}
|
||||
}
|
||||
else if (category.toLowerCase().equalsIgnoreCase("flows"))
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedFlowByKeyword(category, keyword, page, size));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", SearchDAO.elasticSearchFlowByKeyword(category, keyword, page, size));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedFlowByKeyword(category, keyword, page, size));
|
||||
}
|
||||
}
|
||||
else if (category.toLowerCase().equalsIgnoreCase("jobs"))
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedJobByKeyword(category, keyword, page, size));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", SearchDAO.elasticSearchFlowByKeyword(category, keyword, page, size));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedJobByKeyword(category, keyword, page, size));
|
||||
}
|
||||
}
|
||||
else if (category.toLowerCase().equalsIgnoreCase("comments"))
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedCommentsByKeyword(category, keyword, page, size));
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
result.set("result", SearchDAO.elasticSearchDatasetByKeyword(category, keyword, null, page, size));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedCommentsByKeyword(category, keyword, page, size));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectNode node = SearchDAO.getPagedDatasetByKeyword(category, keyword, source, page, size);
|
||||
if (isDefault && node != null && node.has("count"))
|
||||
if(StringUtils.isNotBlank(searchEngine) && searchEngine.equalsIgnoreCase("elasticsearch"))
|
||||
{
|
||||
Long count = node.get("count").asLong();
|
||||
if (count != null && count == 0)
|
||||
{
|
||||
node = SearchDAO.getPagedFlowByKeyword("flows", keyword, page, size);
|
||||
if (node!= null && node.has("count"))
|
||||
{
|
||||
Long flowCount = node.get("count").asLong();
|
||||
if (flowCount != null && flowCount == 0)
|
||||
{
|
||||
node = SearchDAO.getPagedJobByKeyword("jobs", keyword, page, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.set("result", SearchDAO.elasticSearchDatasetByKeyword(category, keyword, source, page, size));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.set("result", SearchDAO.getPagedDatasetByKeyword(category, keyword, source, page, size));
|
||||
}
|
||||
result.set("result", node);
|
||||
}
|
||||
|
||||
return ok(result);
|
||||
|
@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import models.Dataset;
|
||||
import models.FlowJob;
|
||||
import models.Metric;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@ -26,12 +27,12 @@ import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import play.Logger;
|
||||
import play.Play;
|
||||
import play.libs.F;
|
||||
import play.libs.Json;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import play.libs.WS;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AdvSearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
{
|
||||
@ -100,6 +101,14 @@ public class AdvSearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
"FROM flow_job j JOIN flow f on j.app_id = f.app_id AND j.flow_id = f.flow_id " +
|
||||
"JOIN cfg_application a on j.app_id = a.app_id ";
|
||||
|
||||
public final static String ADV_SEARCH_METRIC = "SELECT SQL_CALC_FOUND_ROWS metric_id, " +
|
||||
"metric_name, metric_description, dashboard_name, metric_group, metric_category, " +
|
||||
"metric_sub_category, metric_level, metric_source_type, metric_source, " +
|
||||
"metric_source_dataset_id, metric_ref_id_type, metric_ref_id, metric_type, metric_grain, " +
|
||||
"metric_display_factor, metric_display_factor_sym, metric_good_direction, " +
|
||||
"metric_formula, dimensions, owners, tags, urn, metric_url, wiki_url, scm_url, 0 as watch_id " +
|
||||
"FROM dict_business_metric ";
|
||||
|
||||
|
||||
|
||||
public static List<String> getDatasetSources()
|
||||
@ -193,6 +202,246 @@ public class AdvSearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
return getJdbcTemplate().queryForList(GET_JOB_NAMES, String.class);
|
||||
}
|
||||
|
||||
public static ObjectNode elasticSearch(JsonNode searchOpt, int page, int size)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<Dataset> pagedDatasets = new ArrayList<Dataset>();
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
|
||||
JsonNode searchNode = utils.Search.generateDatasetAdvSearchQueryString(searchOpt);
|
||||
|
||||
if (searchNode != null && searchNode.isContainerNode())
|
||||
{
|
||||
queryNode.put("query", searchNode);
|
||||
}
|
||||
F.Promise < WS.Response> responsePromise = WS.url(
|
||||
Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_DATASET_URL_KEY)).post(queryNode);
|
||||
JsonNode responseNode = responsePromise.get().asJson();
|
||||
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", "Datasets");
|
||||
resultNode.put("itemsPerPage", size);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits")) {
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null) {
|
||||
if (hitsNode.has("total")) {
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits")) {
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray()) {
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null) {
|
||||
while (arrayIterator.hasNext()) {
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id")) {
|
||||
Dataset dataset = new Dataset();
|
||||
dataset.id = node.get("_id").asLong();
|
||||
if (node.has("_source")) {
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null) {
|
||||
if (sourceNode.has("name")) {
|
||||
dataset.name = sourceNode.get("name").asText();
|
||||
}
|
||||
if (sourceNode.has("source")) {
|
||||
dataset.source = sourceNode.get("source").asText();
|
||||
}
|
||||
if (sourceNode.has("urn")) {
|
||||
dataset.urn = sourceNode.get("urn").asText();
|
||||
}
|
||||
if (sourceNode.has("schema")) {
|
||||
dataset.schema = sourceNode.get("schema").asText();
|
||||
}
|
||||
}
|
||||
}
|
||||
pagedDatasets.add(dataset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedDatasets));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode elasticSearchMetric(JsonNode searchOpt, int page, int size)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<Metric> pagedMetrics = new ArrayList<Metric>();
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
|
||||
JsonNode searchNode = utils.Search.generateMetricAdvSearchQueryString(searchOpt);
|
||||
|
||||
if (searchNode != null && searchNode.isContainerNode())
|
||||
{
|
||||
queryNode.put("query", searchNode);
|
||||
}
|
||||
|
||||
F.Promise < WS.Response> responsePromise = WS.url(Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_METRIC_URL_KEY)).post(queryNode);
|
||||
JsonNode responseNode = responsePromise.get().asJson();
|
||||
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", "Metrics");
|
||||
resultNode.put("isMetrics", true);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits")) {
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null) {
|
||||
if (hitsNode.has("total")) {
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits")) {
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray()) {
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null) {
|
||||
while (arrayIterator.hasNext()) {
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id")) {
|
||||
Metric metric = new Metric();
|
||||
metric.id = node.get("_id").asInt();
|
||||
if (node.has("_source")) {
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null) {
|
||||
if (sourceNode.has("metric_name")) {
|
||||
metric.name = sourceNode.get("metric_name").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_description")) {
|
||||
metric.description = sourceNode.get("metric_description").asText();
|
||||
}
|
||||
if (sourceNode.has("dashboard_name")) {
|
||||
metric.dashboardName = sourceNode.get("dashboard_name").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_group")) {
|
||||
metric.group = sourceNode.get("metric_group").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_category")) {
|
||||
metric.category = sourceNode.get("metric_category").asText();
|
||||
}
|
||||
if (sourceNode.has("urn")) {
|
||||
metric.urn = sourceNode.get("urn").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_source")) {
|
||||
metric.source = sourceNode.get("metric_source").asText();
|
||||
if (StringUtils.isBlank(metric.source))
|
||||
{
|
||||
metric.source = null;
|
||||
}
|
||||
}
|
||||
metric.schema = sourceNode.toString();
|
||||
}
|
||||
}
|
||||
pagedMetrics.add(metric);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedMetrics));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode elasticSearchFlowJobs(JsonNode searchOpt, int page, int size)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<FlowJob> pagedFlows = new ArrayList<FlowJob>();
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
|
||||
JsonNode searchNode = utils.Search.generateFlowJobAdvSearchQueryString(searchOpt);
|
||||
|
||||
if (searchNode != null && searchNode.isContainerNode())
|
||||
{
|
||||
queryNode.put("query", searchNode);
|
||||
}
|
||||
|
||||
F.Promise < WS.Response> responsePromise = WS.url(Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_FLOW_URL_KEY)).post(queryNode);
|
||||
JsonNode responseNode = responsePromise.get().asJson();
|
||||
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", "Flows");
|
||||
resultNode.put("isFlowJob", true);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits")) {
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null) {
|
||||
if (hitsNode.has("total")) {
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits")) {
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray()) {
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null) {
|
||||
while (arrayIterator.hasNext()) {
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id")) {
|
||||
FlowJob flowJob = new FlowJob();
|
||||
if (node.has("_source")) {
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null) {
|
||||
if (sourceNode.has("app_code")) {
|
||||
flowJob.appCode = sourceNode.get("app_code").asText();
|
||||
}
|
||||
if (sourceNode.has("app_id")) {
|
||||
flowJob.appId = sourceNode.get("app_id").asInt();
|
||||
}
|
||||
if (sourceNode.has("flow_id")) {
|
||||
flowJob.flowId = sourceNode.get("flow_id").asLong();
|
||||
}
|
||||
if (sourceNode.has("flow_name")) {
|
||||
flowJob.flowName = sourceNode.get("flow_name").asText();
|
||||
flowJob.displayName = flowJob.flowName;
|
||||
}
|
||||
if (sourceNode.has("flow_path")) {
|
||||
flowJob.flowPath = sourceNode.get("flow_path").asText();
|
||||
}
|
||||
if (sourceNode.has("flow_group")) {
|
||||
flowJob.flowGroup = sourceNode.get("flow_group").asText();
|
||||
}
|
||||
flowJob.link = "#/flows/" + flowJob.appCode + "/" +
|
||||
flowJob.flowGroup + "/" + Long.toString(flowJob.flowId) + "/page/1";
|
||||
flowJob.path = flowJob.appCode + "/" + flowJob.flowPath;
|
||||
|
||||
flowJob.schema = sourceNode.toString();
|
||||
}
|
||||
}
|
||||
pagedFlows.add(flowJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedFlows));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode search(JsonNode searchOpt, int page, int size)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
@ -1291,4 +1540,495 @@ public class AdvSearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode searchMetrics(JsonNode searchOpt, int page, int size)
|
||||
{
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
int count = 0;
|
||||
List<String> dashboardInList = new ArrayList<String>();
|
||||
List<String> dashboardNotInList = new ArrayList<String>();
|
||||
List<String> groupInList = new ArrayList<String>();
|
||||
List<String> groupNotInList = new ArrayList<String>();
|
||||
List<String> categoryInList = new ArrayList<String>();
|
||||
List<String> categoryNotInList = new ArrayList<String>();
|
||||
List<String> metricInList = new ArrayList<String>();
|
||||
List<String> metricNotInList = new ArrayList<String>();
|
||||
|
||||
if (searchOpt != null && (searchOpt.isContainerNode()))
|
||||
{
|
||||
if (searchOpt.has("dashboard")) {
|
||||
JsonNode dashboardNode = searchOpt.get("dashboard");
|
||||
if (dashboardNode != null && dashboardNode.isContainerNode())
|
||||
{
|
||||
if (dashboardNode.has("in"))
|
||||
{
|
||||
JsonNode dashboardInNode = dashboardNode.get("in");
|
||||
if (dashboardInNode != null)
|
||||
{
|
||||
String dashboardInStr = dashboardInNode.asText();
|
||||
if (StringUtils.isNotBlank(dashboardInStr))
|
||||
{
|
||||
String[] dashboardInArray = dashboardInStr.split(",");
|
||||
if (dashboardInArray != null)
|
||||
{
|
||||
for(String value : dashboardInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
dashboardInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dashboardNode.has("not"))
|
||||
{
|
||||
JsonNode dashboardNotInNode = dashboardNode.get("not");
|
||||
if (dashboardNotInNode != null)
|
||||
{
|
||||
String dashboardNotInStr = dashboardNotInNode.asText();
|
||||
if (StringUtils.isNotBlank(dashboardNotInStr))
|
||||
{
|
||||
String[] dashboardNotInArray = dashboardNotInStr.split(",");
|
||||
if (dashboardNotInArray != null)
|
||||
{
|
||||
for(String value : dashboardNotInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
dashboardNotInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchOpt.has("group")) {
|
||||
JsonNode groupNode = searchOpt.get("group");
|
||||
if (groupNode != null && groupNode.isContainerNode())
|
||||
{
|
||||
if (groupNode.has("in"))
|
||||
{
|
||||
JsonNode groupInNode = groupNode.get("in");
|
||||
if (groupInNode != null)
|
||||
{
|
||||
String groupInStr = groupInNode.asText();
|
||||
if (StringUtils.isNotBlank(groupInStr))
|
||||
{
|
||||
String[] groupInArray = groupInStr.split(",");
|
||||
if (groupInArray != null)
|
||||
{
|
||||
for(String value : groupInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
groupInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (groupNode.has("not"))
|
||||
{
|
||||
JsonNode groupNotInNode = groupNode.get("not");
|
||||
if (groupNotInNode != null)
|
||||
{
|
||||
String groupNotInStr = groupNotInNode.asText();
|
||||
if (StringUtils.isNotBlank(groupNotInStr))
|
||||
{
|
||||
String[] groupNotInArray = groupNotInStr.split(",");
|
||||
if (groupNotInArray != null)
|
||||
{
|
||||
for(String value : groupNotInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
groupNotInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchOpt.has("cat")) {
|
||||
JsonNode categoryNode = searchOpt.get("cat");
|
||||
if (categoryNode != null && categoryNode.isContainerNode())
|
||||
{
|
||||
if (categoryNode.has("in"))
|
||||
{
|
||||
JsonNode categoryInNode = categoryNode.get("in");
|
||||
if (categoryInNode != null)
|
||||
{
|
||||
String categoryInStr = categoryInNode.asText();
|
||||
if (StringUtils.isNotBlank(categoryInStr))
|
||||
{
|
||||
String[] categoryInArray = categoryInStr.split(",");
|
||||
if (categoryInArray != null)
|
||||
{
|
||||
for(String value : categoryInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
categoryInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (categoryNode.has("not"))
|
||||
{
|
||||
JsonNode categoryNotInNode = categoryNode.get("not");
|
||||
if (categoryNotInNode != null)
|
||||
{
|
||||
String categoryNotInStr = categoryNotInNode.asText();
|
||||
if (StringUtils.isNotBlank(categoryNotInStr))
|
||||
{
|
||||
String[] categoryNotInArray = categoryNotInStr.split(",");
|
||||
if (categoryNotInArray != null)
|
||||
{
|
||||
for(String value : categoryNotInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
categoryNotInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchOpt.has("metric")) {
|
||||
JsonNode metricNode = searchOpt.get("metric");
|
||||
if (metricNode != null && metricNode.isContainerNode())
|
||||
{
|
||||
if (metricNode.has("in"))
|
||||
{
|
||||
JsonNode metricInNode = metricNode.get("in");
|
||||
if (metricInNode != null)
|
||||
{
|
||||
String metricInStr = metricInNode.asText();
|
||||
if (StringUtils.isNotBlank(metricInStr))
|
||||
{
|
||||
String[] metricInArray = metricInStr.split(",");
|
||||
if (metricInArray != null)
|
||||
{
|
||||
for(String value : metricInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
metricInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (metricNode.has("not"))
|
||||
{
|
||||
JsonNode metricNotInNode = metricNode.get("not");
|
||||
if (metricNotInNode != null)
|
||||
{
|
||||
String metricNotInStr = metricNotInNode.asText();
|
||||
if (StringUtils.isNotBlank(metricNotInStr))
|
||||
{
|
||||
String[] metricNotInArray = metricNotInStr.split(",");
|
||||
if (metricNotInArray != null)
|
||||
{
|
||||
for(String value : metricNotInArray)
|
||||
{
|
||||
if (StringUtils.isNotBlank(value))
|
||||
{
|
||||
metricNotInList.add(value.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean needAndKeyword = false;
|
||||
|
||||
final List<Metric> pagedMetrics = new ArrayList<Metric>();
|
||||
final JdbcTemplate jdbcTemplate = getJdbcTemplate();
|
||||
javax.sql.DataSource ds = jdbcTemplate.getDataSource();
|
||||
DataSourceTransactionManager tm = new DataSourceTransactionManager(ds);
|
||||
|
||||
TransactionTemplate txTemplate = new TransactionTemplate(tm);
|
||||
|
||||
ObjectNode result;
|
||||
String query = ADV_SEARCH_METRIC;
|
||||
|
||||
if (dashboardInList.size() > 0 || dashboardNotInList.size() > 0)
|
||||
{
|
||||
boolean dashboardNeedAndKeyword = false;
|
||||
if (dashboardInList.size() > 0)
|
||||
{
|
||||
int indexForDashboardInList = 0;
|
||||
for (String dashboard : dashboardInList)
|
||||
{
|
||||
if (indexForDashboardInList == 0)
|
||||
{
|
||||
query += "WHERE dashboard_name in ('" + dashboard + "'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += ", '" + dashboard + "'";
|
||||
}
|
||||
indexForDashboardInList++;
|
||||
}
|
||||
query += ") ";
|
||||
dashboardNeedAndKeyword = true;
|
||||
}
|
||||
if (dashboardNotInList.size() > 0)
|
||||
{
|
||||
if (dashboardNeedAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " WHERE ";
|
||||
}
|
||||
int indexForDashboardNotInList = 0;
|
||||
for (String dashboard : dashboardNotInList)
|
||||
{
|
||||
if (indexForDashboardNotInList == 0)
|
||||
{
|
||||
query += "dashboard_name not in ('" + dashboard + "'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += ", '" + dashboard + "'";
|
||||
}
|
||||
indexForDashboardNotInList++;
|
||||
}
|
||||
query += ") ";
|
||||
}
|
||||
needAndKeyword = true;
|
||||
}
|
||||
|
||||
if (groupInList.size() > 0 || groupNotInList.size() > 0)
|
||||
{
|
||||
if (needAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " WHERE ";
|
||||
}
|
||||
query += "( ";
|
||||
boolean groupNeedAndKeyword = false;
|
||||
if (groupInList.size() > 0)
|
||||
{
|
||||
query += "( ";
|
||||
int indexForGroupInList = 0;
|
||||
for (String group : groupInList)
|
||||
{
|
||||
if (indexForGroupInList == 0)
|
||||
{
|
||||
query += "metric_group LIKE '%" + group + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " or metric_group LIKE '%" + group + "%'";
|
||||
}
|
||||
indexForGroupInList++;
|
||||
}
|
||||
query += ") ";
|
||||
groupNeedAndKeyword = true;
|
||||
}
|
||||
if (groupNotInList.size() > 0)
|
||||
{
|
||||
if (groupNeedAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
query += "( ";
|
||||
int indexForGroupNotInList = 0;
|
||||
for (String group : groupNotInList)
|
||||
{
|
||||
if (indexForGroupNotInList == 0)
|
||||
{
|
||||
query += "metric_group NOT LIKE '%" + group + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " and metric_group NOT LIKE '%" + group + "%'";
|
||||
}
|
||||
indexForGroupNotInList++;
|
||||
}
|
||||
query += ") ";
|
||||
}
|
||||
query += ") ";
|
||||
needAndKeyword = true;
|
||||
}
|
||||
|
||||
if (categoryInList.size() > 0 || categoryNotInList.size() > 0)
|
||||
{
|
||||
if (needAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " WHERE ";
|
||||
}
|
||||
query += "( ";
|
||||
boolean categoryNeedAndKeyword = false;
|
||||
if (categoryInList.size() > 0)
|
||||
{
|
||||
int indexForCategoryInList = 0;
|
||||
query += "( ";
|
||||
for (String category : categoryInList)
|
||||
{
|
||||
if (indexForCategoryInList == 0)
|
||||
{
|
||||
query += "metric_category LIKE '%" + category + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " or metric_category LIKE '%" + category + "%'";
|
||||
}
|
||||
indexForCategoryInList++;
|
||||
}
|
||||
query += ") ";
|
||||
categoryNeedAndKeyword = true;
|
||||
}
|
||||
if (categoryNotInList.size() > 0)
|
||||
{
|
||||
if (categoryNeedAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
query += "( ";
|
||||
int indexForCategoryNotInList = 0;
|
||||
for (String category : categoryNotInList)
|
||||
{
|
||||
if (indexForCategoryNotInList == 0)
|
||||
{
|
||||
query += "metric_category NOT LIKE '%" + category + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " and metric_category NOT LIKE '%" + category + "%'";
|
||||
}
|
||||
indexForCategoryNotInList++;
|
||||
}
|
||||
query += ") ";
|
||||
}
|
||||
query += ") ";
|
||||
needAndKeyword = true;
|
||||
}
|
||||
|
||||
if (metricInList.size() > 0 || metricNotInList.size() > 0)
|
||||
{
|
||||
if (needAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " WHERE ";
|
||||
}
|
||||
query += "( ";
|
||||
boolean metricNeedAndKeyword = false;
|
||||
if (metricInList.size() > 0)
|
||||
{
|
||||
int indexForMetricInList = 0;
|
||||
query += " ( ";
|
||||
for (String metric : metricInList)
|
||||
{
|
||||
if (indexForMetricInList == 0)
|
||||
{
|
||||
query += "metric_name LIKE '%" + metric + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " or metric_name LIKE '%" + metric + "%'";
|
||||
}
|
||||
indexForMetricInList++;
|
||||
}
|
||||
query += ") ";
|
||||
metricNeedAndKeyword = true;
|
||||
}
|
||||
if (metricNotInList.size() > 0)
|
||||
{
|
||||
if (metricNeedAndKeyword)
|
||||
{
|
||||
query += " AND ";
|
||||
}
|
||||
query += "( ";
|
||||
int indexForMetricNotInList = 0;
|
||||
for (String metric : metricNotInList)
|
||||
{
|
||||
if (indexForMetricNotInList == 0)
|
||||
{
|
||||
query += "metric_name NOT LIKE '%" + metric + "%'";
|
||||
}
|
||||
else
|
||||
{
|
||||
query += " and metric_name NOT LIKE '%" + metric + "%'";
|
||||
}
|
||||
indexForMetricNotInList++;
|
||||
}
|
||||
query += ") ";
|
||||
}
|
||||
query += " )";
|
||||
}
|
||||
|
||||
query += " LIMIT " + (page-1)*size + ", " + size;
|
||||
final String queryString = query;
|
||||
|
||||
result = txTemplate.execute(new TransactionCallback<ObjectNode>()
|
||||
{
|
||||
public ObjectNode doInTransaction(TransactionStatus status)
|
||||
{
|
||||
List<Metric> pagedMetrics = jdbcTemplate.query(queryString, new MetricRowMapper());
|
||||
|
||||
long count = 0;
|
||||
try {
|
||||
count = jdbcTemplate.queryForObject(
|
||||
"SELECT FOUND_ROWS()",
|
||||
Long.class);
|
||||
}
|
||||
catch(EmptyResultDataAccessException e)
|
||||
{
|
||||
Logger.error("Exception = " + e.getMessage());
|
||||
}
|
||||
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("isMetrics", true);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedMetrics));
|
||||
|
||||
return resultNode;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
resultNode.put("count", 0);
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("totalPages", 0);
|
||||
resultNode.set("data", Json.toJson(""));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,13 +13,11 @@
|
||||
*/
|
||||
package dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@ -29,12 +27,23 @@ import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import play.Logger;
|
||||
import play.Play;
|
||||
import play.libs.F;
|
||||
import play.libs.Json;
|
||||
import play.cache.Cache;
|
||||
import models.*;
|
||||
import play.libs.WS;
|
||||
|
||||
public class SearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
{
|
||||
public static String ELASTICSEARCH_DATASET_URL_KEY = "elasticsearch.dataset.url";
|
||||
|
||||
public static String ELASTICSEARCH_METRIC_URL_KEY = "elasticsearch.metric.url";
|
||||
|
||||
public static String ELASTICSEARCH_FLOW_URL_KEY = "elasticsearch.flow.url";
|
||||
|
||||
public static String WHEREHOWS_SEARCH_ENGINE__KEY = "search.engine";
|
||||
|
||||
public final static String SEARCH_DATASET_WITH_PAGINATION = "SELECT SQL_CALC_FOUND_ROWS " +
|
||||
"id, `name`, `schema`, `source`, `urn`, FROM_UNIXTIME(source_modified_time) as modified, " +
|
||||
"rank_01 + rank_02 + rank_03 + rank_04 + rank_05 + rank_06 + rank_07 + rank_08 + rank_09 as rank " +
|
||||
@ -169,6 +178,324 @@ public class SearchDAO extends AbstractMySQLOpenSourceDAO
|
||||
return cachedAutoCompleteList;
|
||||
}
|
||||
|
||||
public static JsonNode elasticSearchDatasetByKeyword(
|
||||
String category,
|
||||
String keywords,
|
||||
String source,
|
||||
int page,
|
||||
int size)
|
||||
{
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
JsonNode responseNode = null;
|
||||
ObjectNode keywordNode = null;
|
||||
|
||||
try
|
||||
{
|
||||
keywordNode = utils.Search.generateElasticSearchQueryString(category, source, keywords);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.error("Elastic search dataset input query is not JSON format. Error message :" + e.getMessage());
|
||||
}
|
||||
|
||||
if (keywordNode != null)
|
||||
{
|
||||
queryNode.put("query", keywordNode);
|
||||
F.Promise < WS.Response> responsePromise = WS.url(Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_DATASET_URL_KEY)).post(queryNode);
|
||||
responseNode = responsePromise.get().asJson();
|
||||
}
|
||||
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<Dataset> pagedDatasets = new ArrayList<Dataset>();
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", category);
|
||||
resultNode.put("source", source);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("keywords", keywords);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits"))
|
||||
{
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null)
|
||||
{
|
||||
if (hitsNode.has("total"))
|
||||
{
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits"))
|
||||
{
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray())
|
||||
{
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null)
|
||||
{
|
||||
while (arrayIterator.hasNext())
|
||||
{
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id"))
|
||||
{
|
||||
Dataset dataset = new Dataset();
|
||||
dataset.id = node.get("_id").asLong();
|
||||
if (node.has("_source"))
|
||||
{
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null)
|
||||
{
|
||||
if (sourceNode.has("name"))
|
||||
{
|
||||
dataset.name = sourceNode.get("name").asText();
|
||||
}
|
||||
if (sourceNode.has("source"))
|
||||
{
|
||||
dataset.source = sourceNode.get("source").asText();
|
||||
}
|
||||
if (sourceNode.has("urn"))
|
||||
{
|
||||
dataset.urn = sourceNode.get("urn").asText();
|
||||
}
|
||||
if (sourceNode.has("schema"))
|
||||
{
|
||||
dataset.schema = sourceNode.get("schema").asText();
|
||||
}
|
||||
}
|
||||
}
|
||||
pagedDatasets.add(dataset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedDatasets));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static JsonNode elasticSearchMetricByKeyword(
|
||||
String category,
|
||||
String keywords,
|
||||
int page,
|
||||
int size)
|
||||
{
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
JsonNode responseNode = null;
|
||||
ObjectNode keywordNode = null;
|
||||
|
||||
try
|
||||
{
|
||||
keywordNode = utils.Search.generateElasticSearchQueryString(category, null, keywords);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.error("Elastic search metric input query is not JSON format. Error message :" + e.getMessage());
|
||||
}
|
||||
|
||||
if (keywordNode != null)
|
||||
{
|
||||
queryNode.put("query", keywordNode);
|
||||
F.Promise < WS.Response> responsePromise = WS.url(Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_METRIC_URL_KEY)).post(queryNode);
|
||||
responseNode = responsePromise.get().asJson();
|
||||
}
|
||||
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<Metric> pagedMetrics = new ArrayList<Metric>();
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", category);
|
||||
resultNode.put("isMetrics", true);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("keywords", keywords);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits"))
|
||||
{
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null)
|
||||
{
|
||||
if (hitsNode.has("total"))
|
||||
{
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits"))
|
||||
{
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray())
|
||||
{
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null)
|
||||
{
|
||||
while (arrayIterator.hasNext())
|
||||
{
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id"))
|
||||
{
|
||||
Metric metric = new Metric();
|
||||
metric.id = node.get("_id").asInt();
|
||||
if (node.has("_source")) {
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null) {
|
||||
if (sourceNode.has("metric_name")) {
|
||||
metric.name = sourceNode.get("metric_name").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_description")) {
|
||||
metric.description = sourceNode.get("metric_description").asText();
|
||||
}
|
||||
if (sourceNode.has("dashboard_name")) {
|
||||
metric.dashboardName = sourceNode.get("dashboard_name").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_group")) {
|
||||
metric.group = sourceNode.get("metric_group").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_category")) {
|
||||
metric.category = sourceNode.get("metric_category").asText();
|
||||
}
|
||||
if (sourceNode.has("urn")) {
|
||||
metric.urn = sourceNode.get("urn").asText();
|
||||
}
|
||||
if (sourceNode.has("metric_source")) {
|
||||
metric.source = sourceNode.get("metric_source").asText();
|
||||
if (StringUtils.isBlank(metric.source))
|
||||
{
|
||||
metric.source = null;
|
||||
}
|
||||
}
|
||||
metric.schema = sourceNode.toString();
|
||||
}
|
||||
}
|
||||
pagedMetrics.add(metric);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedMetrics));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static JsonNode elasticSearchFlowByKeyword(
|
||||
String category,
|
||||
String keywords,
|
||||
int page,
|
||||
int size)
|
||||
{
|
||||
ObjectNode queryNode = Json.newObject();
|
||||
queryNode.put("from", (page-1)*size);
|
||||
queryNode.put("size", size);
|
||||
JsonNode searchOpt = null;
|
||||
JsonNode responseNode = null;
|
||||
ObjectNode keywordNode = null;
|
||||
|
||||
try
|
||||
{
|
||||
keywordNode = utils.Search.generateElasticSearchQueryString(category, null, keywords);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.error("Elastic search flow input query is not JSON format. Error message :" + e.getMessage());
|
||||
}
|
||||
|
||||
if (keywordNode != null)
|
||||
{
|
||||
queryNode.put("query", keywordNode);
|
||||
F.Promise < WS.Response> responsePromise = WS.url(Play.application().configuration().getString(
|
||||
SearchDAO.ELASTICSEARCH_FLOW_URL_KEY)).post(queryNode);
|
||||
responseNode = responsePromise.get().asJson();
|
||||
}
|
||||
|
||||
ObjectNode resultNode = Json.newObject();
|
||||
Long count = 0L;
|
||||
List<FlowJob> pagedFlowJobs = new ArrayList<FlowJob>();
|
||||
resultNode.put("page", page);
|
||||
resultNode.put("category", category);
|
||||
resultNode.put("isFlowJob", true);
|
||||
resultNode.put("itemsPerPage", size);
|
||||
resultNode.put("keywords", keywords);
|
||||
|
||||
if (responseNode != null && responseNode.isContainerNode() && responseNode.has("hits"))
|
||||
{
|
||||
JsonNode hitsNode = responseNode.get("hits");
|
||||
if (hitsNode != null)
|
||||
{
|
||||
if (hitsNode.has("total"))
|
||||
{
|
||||
count = hitsNode.get("total").asLong();
|
||||
}
|
||||
if (hitsNode.has("hits"))
|
||||
{
|
||||
JsonNode dataNode = hitsNode.get("hits");
|
||||
if (dataNode != null && dataNode.isArray())
|
||||
{
|
||||
Iterator<JsonNode> arrayIterator = dataNode.elements();
|
||||
if (arrayIterator != null)
|
||||
{
|
||||
while (arrayIterator.hasNext())
|
||||
{
|
||||
JsonNode node = arrayIterator.next();
|
||||
if (node.isContainerNode() && node.has("_id"))
|
||||
{
|
||||
FlowJob flowJob = new FlowJob();
|
||||
if (node.has("_source")) {
|
||||
JsonNode sourceNode = node.get("_source");
|
||||
if (sourceNode != null) {
|
||||
if (sourceNode.has("app_code")) {
|
||||
flowJob.appCode = sourceNode.get("app_code").asText();
|
||||
}
|
||||
if (sourceNode.has("app_id")) {
|
||||
flowJob.appId = sourceNode.get("app_id").asInt();
|
||||
}
|
||||
if (sourceNode.has("flow_id")) {
|
||||
flowJob.flowId = sourceNode.get("flow_id").asLong();
|
||||
}
|
||||
if (sourceNode.has("flow_name")) {
|
||||
flowJob.flowName = sourceNode.get("flow_name").asText();
|
||||
flowJob.displayName = flowJob.flowName;
|
||||
}
|
||||
if (sourceNode.has("flow_path")) {
|
||||
flowJob.flowPath = sourceNode.get("flow_path").asText();
|
||||
}
|
||||
if (sourceNode.has("flow_group")) {
|
||||
flowJob.flowGroup = sourceNode.get("flow_group").asText();
|
||||
}
|
||||
flowJob.link = "#/flows/" + flowJob.appCode + "/" +
|
||||
flowJob.flowGroup + "/" + Long.toString(flowJob.flowId) + "/page/1";
|
||||
flowJob.path = flowJob.appCode + "/" + flowJob.flowPath;
|
||||
|
||||
flowJob.schema = sourceNode.toString();
|
||||
}
|
||||
}
|
||||
pagedFlowJobs.add(flowJob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
resultNode.put("count", count);
|
||||
resultNode.put("totalPages", (int)Math.ceil(count/((double)size)));
|
||||
resultNode.set("data", Json.toJson(pagedFlowJobs));
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
public static ObjectNode getPagedDatasetByKeyword(String category, String keyword, String source, int page, int size)
|
||||
{
|
||||
List<Dataset> pagedDatasets = new ArrayList<Dataset>();
|
||||
|
@ -28,4 +28,5 @@ public class FlowJob {
|
||||
public String path;
|
||||
public Integer appId;
|
||||
public Long flowId;
|
||||
public String schema;
|
||||
}
|
||||
|
1194
web/app/utils/Search.java
Normal file
1194
web/app/utils/Search.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -1198,6 +1198,7 @@
|
||||
<td class="col-xs-12">
|
||||
<div class="dataset-name">
|
||||
<td class="dataset-info">
|
||||
<i class="fa fa-random"></i>
|
||||
<a href="{{flowJob.link}}">
|
||||
{{flowJob.displayName}}
|
||||
</a>
|
||||
@ -1206,6 +1207,9 @@
|
||||
{{{ flowJob.path }}}
|
||||
</p>
|
||||
<p>source: {{{ flowJob.appCode }}}</p>
|
||||
<div class="schematext" style="margin-top:5px;margin-bottom: 10px;">
|
||||
{{{ flowJob.schema }}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -1221,10 +1225,12 @@
|
||||
<div class="dataset-name">
|
||||
<td class="dataset-info">
|
||||
{{#if isMetric}}
|
||||
<i class="fa fa-plus-square-o"></i>
|
||||
{{#link-to 'metric' dataset}}
|
||||
{{{dataset.name}}}
|
||||
{{/link-to}}
|
||||
{{else}}
|
||||
<i class="fa fa-database"></i>
|
||||
{{#link-to 'dataset' dataset}}
|
||||
{{{dataset.name}}}
|
||||
{{/link-to}}
|
||||
@ -1233,7 +1239,11 @@
|
||||
<p>
|
||||
{{{ dataset.urn }}}
|
||||
</p>
|
||||
<p>source: {{{ dataset.source }}}</p>
|
||||
{{#if dataset.source}}
|
||||
<p>source: {{{ dataset.source }}}</p>
|
||||
{{else}}
|
||||
<p>source: Metric</p>
|
||||
{{/if}}
|
||||
<div class="schematext" style="margin-top:5px;margin-bottom: 10px;">
|
||||
{{{ dataset.schema }}}
|
||||
</div>
|
||||
@ -1302,6 +1312,7 @@
|
||||
<td class="col-xs-12">
|
||||
<div class="dataset-name">
|
||||
<td class="dataset-info">
|
||||
<i class="fa fa-random"></i>
|
||||
<a href="{{flowJob.link}}">
|
||||
{{flowJob.displayName}}
|
||||
</a>
|
||||
@ -1310,6 +1321,9 @@
|
||||
{{{ flowJob.path }}}
|
||||
</p>
|
||||
<p>source: {{{ flowJob.appCode }}}</p>
|
||||
<div class="schematext" style="margin-top:5px;margin-bottom: 10px;">
|
||||
{{{ flowJob.schema }}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -1324,6 +1338,7 @@
|
||||
<td class="col-xs-12">
|
||||
<div class="dataset-name">
|
||||
<td class="dataset-info">
|
||||
<i class="fa fa-database"></i>
|
||||
{{#link-to 'dataset' dataset}}
|
||||
{{{dataset.name}}}
|
||||
{{/link-to}}
|
||||
|
@ -90,20 +90,55 @@
|
||||
</li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-left" role="search">
|
||||
<div class="input-group">
|
||||
<input id="searchInput"
|
||||
type="text"
|
||||
class="form-control input-sm keyword-search"
|
||||
placeholder="Enter Keywords..."
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button id="searchBtn"
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
>
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
<div class="row">
|
||||
<div class="btn-group" role="group">
|
||||
<button style="height: 30px;margin-right:-4px;"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<i id="categoryIcon" class="fa fa-database"></i>
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<!--
|
||||
<li class="active">
|
||||
<a href="#" class="searchCategory">All</a>
|
||||
</li>
|
||||
-->
|
||||
<li id="categoryDatasets" class="active">
|
||||
<a href="#" class="searchCategory">Datasets</a>
|
||||
</li>
|
||||
<li id="categoryComments" >
|
||||
<a href="#" class="searchCategory">Comments</a>
|
||||
</li>
|
||||
<!--
|
||||
<li id="categoryMetrics" >
|
||||
<a href="#" class="searchCategory">Metrics</a>
|
||||
</li>
|
||||
-->
|
||||
<li id="categoryFlows" >
|
||||
<a href="#" class="searchCategory">Flows</a>
|
||||
</li>
|
||||
<li id="categoryJobs" >
|
||||
<a href="#" class="searchCategory">Jobs</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input id="searchInput"
|
||||
type="text"
|
||||
class="form-control input-sm keyword-search"
|
||||
placeholder="Enter Keywords..."
|
||||
/>
|
||||
<span class="input-group-btn">
|
||||
<button id="searchBtn"
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
>
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="nav nabar-nav navbar-left">
|
||||
|
@ -93,6 +93,101 @@ var convertQueryStringToObject = function() {
|
||||
return queryString;
|
||||
}
|
||||
|
||||
function resetCategoryActiveFlag(category)
|
||||
{
|
||||
$('#categoryDatasets').removeClass('active');
|
||||
$('#categoryComments').removeClass('active');
|
||||
$('#categoryMetrics').removeClass('active');
|
||||
$('#categoryFlows').removeClass('active');
|
||||
$('#categoryJobs').removeClass('active');
|
||||
if (category.toLowerCase() == 'datasets')
|
||||
{
|
||||
$('#categoryDatasets').addClass('active');
|
||||
}
|
||||
else if (category.toLowerCase() == 'comments')
|
||||
{
|
||||
$('#categoryComments').addClass('active');
|
||||
}
|
||||
else if (category.toLowerCase() == 'metrics')
|
||||
{
|
||||
$('#categoryMetrics').addClass('active');
|
||||
}
|
||||
else if (category.toLowerCase() == 'flows')
|
||||
{
|
||||
$('#categoryFlows').addClass('active');
|
||||
}
|
||||
else if (category.toLowerCase() == 'jobs')
|
||||
{
|
||||
$('#categoryJobs').addClass('active');
|
||||
}
|
||||
currentCategory = category;
|
||||
}
|
||||
|
||||
function updateSearchCategories(category)
|
||||
{
|
||||
if (category.toLowerCase() == 'all')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-list');
|
||||
}
|
||||
else if (category.toLowerCase() == 'datasets')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-database');
|
||||
}
|
||||
else if (category.toLowerCase() == 'comments')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-comment');
|
||||
}
|
||||
else if (category.toLowerCase() == 'metrics')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-plus-square-o');
|
||||
}
|
||||
else if (category.toLowerCase() == 'flows')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-random');
|
||||
}
|
||||
else if (category.toLowerCase() == 'jobs')
|
||||
{
|
||||
$('#categoryIcon').removeClass('fa fa-list');
|
||||
$('#categoryIcon').removeClass('fa fa-database');
|
||||
$('#categoryIcon').removeClass('fa fa-comment');
|
||||
$('#categoryIcon').removeClass('fa fa-random');
|
||||
$('#categoryIcon').removeClass('fa fa-plus-square-o');
|
||||
$('#categoryIcon').removeClass('fa fa-file-o');
|
||||
$('#categoryIcon').addClass('fa fa-file-o');
|
||||
}
|
||||
resetCategoryActiveFlag(category);
|
||||
}
|
||||
|
||||
String.prototype.toProperCase = function(){
|
||||
return this.replace(/\w\S*/g, function(txt){
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
|
||||
|
@ -20,8 +20,11 @@ function highlightResults(result, index, keyword)
|
||||
var newContent = content.replace(query, "<b>$1</b>");
|
||||
result[index].schema = newContent;
|
||||
var urn = result[index].urn;
|
||||
var newUrn = urn.replace(query, "<b>$1</b>");
|
||||
result[index].urn = newUrn;
|
||||
if (urn)
|
||||
{
|
||||
var newUrn = urn.replace(query, "<b>$1</b>");
|
||||
result[index].urn = newUrn;
|
||||
}
|
||||
};
|
||||
|
||||
App.SearchRoute = Ember.Route.extend({
|
||||
@ -65,6 +68,9 @@ App.SearchRoute = Ember.Route.extend({
|
||||
$.get(url, function(data) {
|
||||
if (data && data.status == "ok") {
|
||||
var result = data.result;
|
||||
var keywords = result.keywords;
|
||||
window.g_currentCategory = result.category;
|
||||
updateSearchCategories(result.category);
|
||||
for(var index = 0; index < result.data.length; index++) {
|
||||
var schema = result.data[index].schema;
|
||||
if (schema) {
|
||||
|
@ -1,6 +1,10 @@
|
||||
(function ($) {
|
||||
(function (window, $) {
|
||||
$('#advsearchtabs a:first').tab("show");
|
||||
$('#datasetAdvSearchLink').addClass("active");
|
||||
String.prototype.replaceAll = function(target, replacement) {
|
||||
return this.split(target).join(replacement);
|
||||
};
|
||||
window.g_currentCategory = 'Datasets';
|
||||
function renderAdvSearchDatasetSources(parent, sources)
|
||||
{
|
||||
if ((!parent) || (!sources) || sources.length == 0)
|
||||
@ -72,7 +76,21 @@
|
||||
parent.append(content);
|
||||
}
|
||||
|
||||
var datasetSourcesUrl = '/api/v1/advsearch/sources';
|
||||
$(".searchCategory").click(function(e){
|
||||
var objs = $(".searchCategory");
|
||||
if (objs)
|
||||
{
|
||||
$.each(objs, function( index, value ) {
|
||||
$(objs[index]).parent().removeClass("active");
|
||||
});
|
||||
}
|
||||
window.g_currentCategory = e.target.text;
|
||||
updateSearchCategories(e.target.text);
|
||||
//$(e.target).parent().addClass( "active" );
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
var datasetSourcesUrl = '/api/v1/advsearch/sources';
|
||||
$.get(datasetSourcesUrl, function(data) {
|
||||
if (data && data.status == "ok")
|
||||
{
|
||||
@ -87,32 +105,25 @@
|
||||
}
|
||||
});
|
||||
|
||||
$("#searchInput").on( "keydown", function(event) {
|
||||
if(event.which == 13)
|
||||
{
|
||||
event.preventDefault();
|
||||
var inputObj = $('#searchInput');
|
||||
if (inputObj) {
|
||||
var keyword = inputObj.val();
|
||||
if (keyword) {
|
||||
window.location = '/#/search?keywords=' + btoa(keyword) +
|
||||
'&category=Datasets&source=default&page=1';
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.get('/api/v1/autocomplete/search', function(data){
|
||||
$('#searchInput').autocomplete({
|
||||
source: function(request, response) {
|
||||
var result = [];
|
||||
if (data && data.source && request.term)
|
||||
{
|
||||
result = sortAutocompleteResult(data.source, request.term);
|
||||
}
|
||||
return response(result);
|
||||
}
|
||||
});
|
||||
source: function( req, res ) {
|
||||
var results = $.ui.autocomplete.filter(data.source, extractLast( req.term ));
|
||||
res(results.slice(0,maxReturnedResults));
|
||||
},
|
||||
focus: function() {
|
||||
return false;
|
||||
},
|
||||
select: function( event, ui ) {
|
||||
var terms = split( this.value );
|
||||
terms.pop();
|
||||
terms.push( ui.item.value );
|
||||
terms.push( "" );
|
||||
this.value = terms.join( ", " );
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -296,7 +307,7 @@
|
||||
if (keyword)
|
||||
{
|
||||
window.location = '/#/search?keywords=' + btoa(keyword) +
|
||||
'&category=Datasets&source=default&page=1';
|
||||
'&category=' + window.g_currentCategory + '&source=default&page=1'
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -577,4 +588,4 @@
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery)
|
||||
})(window, jQuery)
|
||||
|
@ -669,4 +669,8 @@ div.commentsArea td, div.commentsArea th, div.commentsArea table{
|
||||
|
||||
.wh-clickable-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.keyword-search {
|
||||
min-width: 500px;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user