*/
package org.sonar.server.rule2;
-import org.sonar.server.rule2.RuleNormalizer.RuleField;
-
-import org.elasticsearch.action.search.SearchResponse;
import com.google.common.collect.ImmutableSet;
+import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
-import org.elasticsearch.index.query.MultiMatchQueryBuilder;
+import org.elasticsearch.index.query.BoolFilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.rule.RuleConstants;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.es.ESNode;
+import org.sonar.server.rule2.RuleNormalizer.RuleField;
import org.sonar.server.search.BaseIndex;
+import org.sonar.server.search.Hit;
import org.sonar.server.search.QueryOptions;
import org.sonar.server.search.Results;
public Results search(RuleQuery query, QueryOptions options) {
-// QueryBuilder qb;
-// if(query.getQueryText() != null && !query.getQueryText().isEmpty()){
-// qb = QueryBuilders.multiMatchQuery("test", "toto");
-// } else {
-// qb = QueryBuilders.matchAllQuery();
-// }
-//
-// SearchResponse esResult = getClient()
-// .prepareSearch(this.getIndexName())
-// .setQuery(qb)
-// .get();
-//
- Results results = new Results();
+ // Build main query (search based)
+ QueryBuilder qb;
+ if (query.getQueryText() != null && !query.getQueryText().isEmpty()) {
+ qb = QueryBuilders.multiMatchQuery(query.getQueryText(),
+ RuleField.NAME.key(),
+ RuleField.DESCRIPTION.key(),
+ RuleField.KEY.key(),
+ RuleField.LANGUAGE.key(),
+ RuleField.TAGS.key());
+ } else {
+ qb = QueryBuilders.matchAllQuery();
+ }
+
+ // Build main filter (match based)
+ BoolFilterBuilder fb = FilterBuilders.boolFilter();
+
+ this.addTermFilter(RuleField.LANGUAGE.key(), query.getLanguages(), fb);
+ this.addTermFilter(RuleField.REPOSITORY.key(), query.getRepositories(), fb);
+ this.addTermFilter(RuleField.SEVERITY.key(), query.getSeverities(), fb);
+ this.addTermFilter(RuleField.KEY.key(), query.getKey(), fb);
+
+ //Create ES query Object;
+ SearchResponse esResult = getClient()
+ .prepareSearch(this.getIndexName())
+ .setQuery(QueryBuilders.filteredQuery(qb, fb))
+ .addFields(options.getFieldsToReturn().toArray(new String[options.getFieldsToReturn().size()]))
+ .get();
+
+ Results results = new Results()
+ .setTotal((int) esResult.getHits().totalHits())
+ .setTime(esResult.getTookInMillis());
+
+ for (SearchHit hit : esResult.getHits().getHits()) {
+ results.getHits().add(
+ Hit.fromMap(hit.score(), hit.sourceAsMap()));
+ }
+
return results;
}
-
}
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.index.query.BoolFilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.core.cluster.WorkQueue;
import java.io.IOException;
import java.io.Serializable;
+import java.util.Collection;
public abstract class BaseIndex<K extends Serializable, E extends Dto<K>> implements Index<K> {
private final Profiling profiling;
private Client client;
private final ESNode node;
- protected BaseNormalizer<E,K> normalizer;
+ protected BaseNormalizer<E, K> normalizer;
- public BaseIndex(BaseNormalizer<E,K> normalizer, WorkQueue workQueue,
- Profiling profiling, ESNode node) {
+ public BaseIndex(BaseNormalizer<E, K> normalizer, WorkQueue workQueue,
+ Profiling profiling, ESNode node) {
this.normalizer = normalizer;
this.profiling = profiling;
this.node = node;
// TODO need to read that in the admin index;
return 0l;
}
+
+ /* ES QueryHelper Methods */
+
+ protected BoolFilterBuilder addTermFilter(String field, Collection<String> values, BoolFilterBuilder filter) {
+ if (values != null && !values.isEmpty()) {
+ BoolFilterBuilder valueFilter = FilterBuilders.boolFilter()
+ .cache(true)
+ .cacheKey(field + "_vs");
+ for (String value : values) {
+ valueFilter.should(FilterBuilders.termFilter(field, value));
+ }
+ filter.must(valueFilter);
+ }
+ return filter;
+ }
+
+ protected BoolFilterBuilder addTermFilter(String field, String value, BoolFilterBuilder filter) {
+ if (value != null && !value.isEmpty()) {
+ filter.must(FilterBuilders.termFilter(field, value));
+ }
+ return filter;
+ }
}
private Map<String, Object> fields;
private Integer rank;
+ private Float score;
public Hit(Integer rank) {
this.fields = new HashMap<String, Object>();
this.rank = rank;
}
+ public Hit(Float score){
+ this.fields = new HashMap<String, Object>();
+ this.score = score;
+ }
+
public Map<String, Object> getFields() {
return this.fields;
}
return this.rank;
}
+ public Float getScore() {
+ return this.score;
+ }
+
@Override
public int compareTo(Hit hit) {
- return this.getRank().compareTo(hit.getRank());
+ if (this.getRank() != null) {
+ return this.getRank().compareTo(hit.getRank());
+ } else {
+ return this.getScore().compareTo(hit.getScore());
+ }
}
public static Hit fromMap(Integer rank, Map<String, Object> fieldMap) {
hit.fields = fieldMap;
return hit;
}
+
+ public static Hit fromMap(float score, Map<String, Object> fieldMap) {
+ Hit hit = new Hit(score);
+ hit.fields = fieldMap;
+ return hit;
+ }
}
*/
package org.sonar.server.search;
+import java.util.ArrayList;
import java.util.Collection;
public class Results {
private int offset;
+ private long time;
+
+ public Results() {
+ this.hits = new ArrayList<Hit>();
+ }
+
public Collection<Hit> getHits() {
return hits;
}
public int getOffset() {
return offset;
}
+
+ public Results setTotal(int total) {
+ this.total = total;
+ return this;
+ }
+
+ public Results setOffset(int offset) {
+ this.offset = offset;
+ return this;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public Results setTime(long time) {
+ this.time = time;
+ return this;
+ }
}