package org.apache.blur.console.util;
import org.apache.blur.console.model.ResultRow;
import org.apache.blur.console.model.User;
import org.apache.blur.thirdparty.thrift_0_9_0.TException;
import org.apache.blur.thrift.generated.*;
import org.apache.blur.thrift.generated.Blur.Iface;
import org.apache.blur.user.UserContext;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.util.*;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* <p/>
* http://www.apache.org/licenses/LICENSE-2.0
* <p/>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class SearchUtil {
private static final String TOTAL_KEY = "total";
private static final String DATA_KEY = "results";
private static final String FAMILY_KEY = "families";
private static final String TIME_KEY = "time";
private static final String ROW_ROW_OPTION = "rowrow";
private static final String RECORD_RECORD_OPTION = "recordrecord";
public static Map<String, Object> search(Map<String, String[]> params, User user) throws IOException, TException {
String table = HttpUtil.getFirstParam(params.get("table"));
String query = HttpUtil.getFirstParam(params.get("query"));
String rowQuery = HttpUtil.getFirstParam(params.get("rowRecordOption"));
String start = HttpUtil.getFirstParam(params.get("start"));
String fetch = HttpUtil.getFirstParam(params.get("fetch"));
String[] families = params.get("families[]");
String securityUser = HttpUtil.getFirstParam(params.get("securityUser"));
if (query.indexOf("rowid:") >= 0) {
return fetchRow(table, query, families, user, securityUser);
}
return searchAndFetch(table, query, rowQuery, start, fetch, families, user, securityUser);
}
public static Map<String, Long> facetSearch(Map<String, String[]> params, User user) throws IOException, TException {
String table = HttpUtil.getFirstParam(params.get("table"));
String query = HttpUtil.getFirstParam(params.get("query"));
String family = HttpUtil.getFirstParam(params.get("family"));
String column = HttpUtil.getFirstParam(params.get("column"));
String[] terms = params.get("terms[]");
String rowQuery = HttpUtil.getFirstParam(params.get("rowRecordOption"));
String securityUser = HttpUtil.getFirstParam(params.get("securityUser"));
System.out.println(params);
Iface client = Config.getClient(user, securityUser);
BlurQuery blurQuery = new BlurQuery();
Query q = new Query(query, ROW_ROW_OPTION.equalsIgnoreCase(rowQuery), ScoreType.SUPER, null, null);
blurQuery.setQuery(q);
blurQuery.setUserContext(user.getName());
for(String term : terms) {
blurQuery.addToFacets(new Facet("+(+" + family + "." + column + ":(" + term + "))", 1000));
}
BlurResults blurResults = client.query(table, blurQuery);
List<Long> facetCounts = blurResults.getFacetCounts();
Map<String, Long> countMap = new HashMap<String, Long>();
for (int i = 0; i < terms.length; i++) {
countMap.put(terms[i], facetCounts.get(i));
}
return countMap;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static Map<String, Object> searchAndFetch(String table, String query, String rowQuery, String start, String fetch, String[] families, User user, String securityUser) throws IOException, TException {
try {
Iface client = Config.getClient(user, securityUser);
boolean recordsOnly = RECORD_RECORD_OPTION.equalsIgnoreCase(rowQuery);
BlurQuery blurQuery = new BlurQuery();
Query q = new Query(query, ROW_ROW_OPTION.equalsIgnoreCase(rowQuery), ScoreType.SUPER, null, null);
blurQuery.setQuery(q);
blurQuery.setStart(Long.parseLong(start));
blurQuery.setFetch(Integer.parseInt(fetch));
blurQuery.setUserContext(user.getName());
Selector s = new Selector();
s.setRecordOnly(recordsOnly);
s.setColumnFamiliesToFetch(new HashSet<String>(Arrays.asList(families)));
blurQuery.setSelector(s);
Map<String, Object> results = new HashMap<String, Object>();
long startTime = System.currentTimeMillis();
BlurResults blurResults = client.query(table, blurQuery);
results.put(TIME_KEY, System.currentTimeMillis() - startTime);
results.put(TOTAL_KEY, blurResults.getTotalResults());
Map<String, List> rows = new HashMap<String, List>();
for (BlurResult result : blurResults.getResults()) {
FetchResult fetchResult = result.getFetchResult();
if (recordsOnly) {
// Record Result
FetchRecordResult recordResult = fetchResult.getRecordResult();
Record record = recordResult.getRecord();
String family = record.getFamily();
List<Map<String, String>> fam = (List<Map<String, String>>) getFam(family, rows, recordsOnly);
fam.add(buildRow(record.getColumns(), record.getRecordId()));
} else {
// Row Result
FetchRowResult rowResult = fetchResult.getRowResult();
Row row = rowResult.getRow();
if (row.getRecords() == null || row.getRecords().size() == 0) {
for (String family : families) {
List<ResultRow> fam = (List<ResultRow>) getFam(family, rows, recordsOnly);
getRow(row.getId(), fam);
}
} else {
for (Record record : row.getRecords()) {
String family = record.getFamily();
List<ResultRow> fam = (List<ResultRow>) getFam(family, rows, recordsOnly);
ResultRow rowData = getRow(row.getId(), fam);
rowData.getRecords().add(buildRow(record.getColumns(), record.getRecordId()));
}
}
}
}
results.put(FAMILY_KEY, new HashSet<String>(Arrays.asList(families)));
results.put(DATA_KEY, rows);
return results;
} finally {
UserContext.reset();
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private static Map<String, Object> fetchRow(String table, String query, String[] families, User user, String securityUser) throws IOException, TException {
try {
Iface client = Config.getClient(user, securityUser);
Selector selector = new Selector();
String rowid = StringUtils.remove(query, "rowid:");
selector.setRowId(rowid);
selector.setColumnFamiliesToFetch(new HashSet<String>(Arrays.asList(families)));
Map<String, Object> results = new HashMap<String, Object>();
long startTime = System.currentTimeMillis();
FetchResult fetchRow = client.fetchRow(table, selector);
results.put(TIME_KEY, System.currentTimeMillis() - startTime);
results.put(TOTAL_KEY, fetchRow.getRowResult().getRow() == null ? 0 : 1);
Map<String, List> rows = new HashMap<String, List>();
Row row = fetchRow.getRowResult().getRow();
if (row != null && row.getRecords() != null) {
for (Record record : row.getRecords()) {
String family = record.getFamily();
List<ResultRow> fam = (List<ResultRow>) getFam(family, rows, false);
ResultRow rowData = getRow(row.getId(), fam);
rowData.getRecords().add(buildRow(record.getColumns(), record.getRecordId()));
}
}
results.put(DATA_KEY, rows);
results.put(FAMILY_KEY, new HashSet<String>(Arrays.asList(families)));
return results;
} finally {
UserContext.reset();
}
}
private static Map<String, String> buildRow(List<Column> columns, String recordid) {
Map<String, String> map = new TreeMap<String, String>();
map.put("recordid", recordid);
for (Column column : columns) {
map.put(column.getName(), column.getValue());
}
return map;
}
@SuppressWarnings("rawtypes")
private static List getFam(String fam, Map<String, List> results, boolean recordOnly) {
List famResults = results.get(fam);
if (famResults == null) {
if (recordOnly) {
famResults = new ArrayList<Map<String, String>>();
} else {
famResults = new ArrayList<ResultRow>();
}
results.put(fam, famResults);
}
return famResults;
}
private static ResultRow getRow(String rowid, List<ResultRow> rows) {
ResultRow row = null;
for (ResultRow r : rows) {
if (r.getRowid().equals(rowid)) {
row = r;
break;
}
}
if (row == null) {
row = new ResultRow(rowid);
rows.add(row);
}
return row;
}
}