From: Stephane Gamard Date: Wed, 30 Apr 2014 14:34:51 +0000 (+0200) Subject: SONAR-5237 - Updated RuleService#search X-Git-Tag: 4.4-RC1~1306 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3c10c4c0b74d90b37a15ced1c3436a7c4ab58b2a;p=sonarqube.git SONAR-5237 - Updated RuleService#search --- diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java index 4a138c4a371..00892f775e4 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleIndex.java @@ -19,14 +19,14 @@ */ 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; @@ -35,7 +35,9 @@ import org.sonar.core.profiling.Profiling; 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; @@ -139,20 +141,43 @@ public class RuleIndex extends BaseIndex { 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; } - } diff --git a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java index f7703c3894e..986624d6982 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java +++ b/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java @@ -29,6 +29,8 @@ import org.elasticsearch.action.update.UpdateRequest; 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; @@ -40,6 +42,7 @@ import org.sonar.server.es.ESNode; import java.io.IOException; import java.io.Serializable; +import java.util.Collection; public abstract class BaseIndex> implements Index { @@ -55,10 +58,10 @@ public abstract class BaseIndex> implem private final Profiling profiling; private Client client; private final ESNode node; - protected BaseNormalizer normalizer; + protected BaseNormalizer normalizer; - public BaseIndex(BaseNormalizer normalizer, WorkQueue workQueue, - Profiling profiling, ESNode node) { + public BaseIndex(BaseNormalizer normalizer, WorkQueue workQueue, + Profiling profiling, ESNode node) { this.normalizer = normalizer; this.profiling = profiling; this.node = node; @@ -216,4 +219,26 @@ public abstract class BaseIndex> implem // TODO need to read that in the admin index; return 0l; } + + /* ES QueryHelper Methods */ + + protected BoolFilterBuilder addTermFilter(String field, Collection 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; + } } diff --git a/sonar-server/src/main/java/org/sonar/server/search/Hit.java b/sonar-server/src/main/java/org/sonar/server/search/Hit.java index ea373a4ec09..32991d77c04 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Hit.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Hit.java @@ -28,12 +28,18 @@ public class Hit implements Comparable { private Map fields; private Integer rank; + private Float score; public Hit(Integer rank) { this.fields = new HashMap(); this.rank = rank; } + public Hit(Float score){ + this.fields = new HashMap(); + this.score = score; + } + public Map getFields() { return this.fields; } @@ -53,9 +59,17 @@ public class Hit implements Comparable { 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 fieldMap) { @@ -63,4 +77,10 @@ public class Hit implements Comparable { hit.fields = fieldMap; return hit; } + + public static Hit fromMap(float score, Map fieldMap) { + Hit hit = new Hit(score); + hit.fields = fieldMap; + return hit; + } } diff --git a/sonar-server/src/main/java/org/sonar/server/search/Results.java b/sonar-server/src/main/java/org/sonar/server/search/Results.java index 3504fb2ad76..48c6fd246cd 100644 --- a/sonar-server/src/main/java/org/sonar/server/search/Results.java +++ b/sonar-server/src/main/java/org/sonar/server/search/Results.java @@ -19,6 +19,7 @@ */ package org.sonar.server.search; +import java.util.ArrayList; import java.util.Collection; public class Results { @@ -29,6 +30,12 @@ public class Results { private int offset; + private long time; + + public Results() { + this.hits = new ArrayList(); + } + public Collection getHits() { return hits; } @@ -40,4 +47,23 @@ public class Results { 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; + } }