diff options
author | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2014-10-30 16:10:46 +0100 |
---|---|---|
committer | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2014-10-30 16:16:44 +0100 |
commit | be93f8c42f7951ec1ff5851405c2dc6d786dd473 (patch) | |
tree | d3fe5223d4a0187f966dd50cffd0a97a906bda0f | |
parent | 6137d755bac7fa51b6b69546d5fccbb65dff25ad (diff) | |
download | sonarqube-be93f8c42f7951ec1ff5851405c2dc6d786dd473.tar.gz sonarqube-be93f8c42f7951ec1ff5851405c2dc6d786dd473.zip |
SONAR-5718 Refactor sticky facet building
4 files changed, 132 insertions, 77 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 94f0ba2a837..fcb869847f4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -337,22 +337,23 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { private void setFacets(IssueQuery query, QueryContext options, Map<String, FilterBuilder> filters, QueryBuilder esQuery, SearchRequestBuilder esSearch) { if (options.isFacet()) { + StickyFacetBuilder stickyFacetBuilder = stickyFacetBuilder(esQuery, filters); // Execute Term aggregations - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.SEVERITIES, IssueNormalizer.IssueField.SEVERITY.field(), 0); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.STATUSES, IssueNormalizer.IssueField.STATUS.field(), 0); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.ACTION_PLANS, IssueNormalizer.IssueField.ACTION_PLAN.field(), 1, query.actionPlans().toArray()); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.COMPONENT_ROOT_UUIDS, IssueNormalizer.IssueField.MODULE_PATH.field(), 1, query.componentRootUuids().toArray()); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.COMPONENT_UUIDS, IssueNormalizer.IssueField.COMPONENT.field(), 1, query.componentUuids().toArray()); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.LANGUAGES, IssueNormalizer.IssueField.LANGUAGE.field(), 0, query.languages().toArray()); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.RULES, IssueNormalizer.IssueField.RULE_KEY.field(), 1, query.rules().toArray()); - addSimpleStickyFacetIfNeeded(query, options, filters, esQuery, esSearch, + addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, IssueFilterParameters.REPORTERS, IssueNormalizer.IssueField.REPORTER.field(), 1); if (options.facets().contains(IssueFilterParameters.RESOLUTIONS)) { @@ -364,10 +365,10 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { } } - private void addSimpleStickyFacetIfNeeded(IssueQuery query, QueryContext options, Map<String, FilterBuilder> filters, QueryBuilder esQuery, SearchRequestBuilder esSearch, + private void addSimpleStickyFacetIfNeeded(QueryContext options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch, String facetName, String fieldName, int minDocCount, Object... selectedValues) { if (options.facets().contains(facetName)) { - esSearch.addAggregation(stickyFacetBuilder(esQuery, filters, fieldName, facetName, DEFAULT_ISSUE_FACET_SIZE, minDocCount, selectedValues)); + esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_ISSUE_FACET_SIZE, minDocCount, selectedValues)); } } @@ -379,9 +380,10 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { Map<String, FilterBuilder> assigneeFilters = Maps.newHashMap(filters); assigneeFilters.remove("__isAssigned"); assigneeFilters.remove(fieldName); - BoolFilterBuilder facetFilter = getStickyFacetFilter(esQuery, assigneeFilters, fieldName); - FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 1); - addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.assignees().toArray()); + StickyFacetBuilder assigneeFacetBuilder = new StickyFacetBuilder(esQuery, assigneeFilters); + BoolFilterBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName); + FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 1); + facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.assignees().toArray()); // Add missing facet for unassigned issues facetTopAggregation.subAggregation( @@ -403,9 +405,10 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { Map<String, FilterBuilder> resolutionFilters = Maps.newHashMap(filters); resolutionFilters.remove("__isResolved"); resolutionFilters.remove(fieldName); - BoolFilterBuilder facetFilter = getStickyFacetFilter(esQuery, resolutionFilters, fieldName); - FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 0); - addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.resolutions().toArray()); + StickyFacetBuilder assigneeFacetBuilder = new StickyFacetBuilder(esQuery, resolutionFilters); + BoolFilterBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName); + FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_ISSUE_FACET_SIZE, 0); + facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, query.resolutions().toArray()); // Add missing facet for unresolved issues facetTopAggregation.subAggregation( diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java index b1d4c86cd71..f87aa8ba4a0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java @@ -318,9 +318,10 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> { protected Map<String, AggregationBuilder> getFacets(QueryBuilder query, Map<String, FilterBuilder> filters) { Map<String, AggregationBuilder> aggregations = new HashMap<String, AggregationBuilder>(); - aggregations.put(FACET_LANGUAGES + "global", stickyFacetBuilder(query, filters, RuleNormalizer.RuleField.LANGUAGE.field(), FACET_LANGUAGES)); - aggregations.put(FACET_TAGS + "global", stickyFacetBuilder(query, filters, RuleNormalizer.RuleField.ALL_TAGS.field(), FACET_TAGS)); - aggregations.put(FACET_REPOSITORIES + "global", stickyFacetBuilder(query, filters, RuleNormalizer.RuleField.REPOSITORY.field(), FACET_REPOSITORIES)); + StickyFacetBuilder stickyFacetBuilder = stickyFacetBuilder(query, filters); + aggregations.put(FACET_LANGUAGES + "global", stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.LANGUAGE.field(), FACET_LANGUAGES)); + aggregations.put(FACET_TAGS + "global", stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.ALL_TAGS.field(), FACET_TAGS)); + aggregations.put(FACET_REPOSITORIES + "global", stickyFacetBuilder.buildStickyFacet(RuleNormalizer.RuleField.REPOSITORY.field(), FACET_REPOSITORIES)); return aggregations; diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java index bded61a64e8..a179b88fbf7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java @@ -19,12 +19,10 @@ */ package org.sonar.server.search; -import com.google.common.base.Joiner; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; -import org.apache.commons.lang.StringUtils; import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; import org.elasticsearch.action.count.CountRequestBuilder; import org.elasticsearch.action.count.CountResponse; @@ -38,10 +36,8 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.query.*; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.aggregations.Aggregation; -import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; -import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; import org.elasticsearch.search.aggregations.bucket.terms.StringTerms; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.max.Max; @@ -62,10 +58,6 @@ import java.util.*; public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serializable> implements Index<DOMAIN, DTO, KEY> { - private static final int FACET_DEFAULT_MIN_DOC_COUNT = 1; - - private static final int FACET_DEFAULT_SIZE = 10; - private static final Logger LOG = LoggerFactory.getLogger(BaseIndex.class); private final SearchClient client; @@ -613,55 +605,7 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial } - protected AggregationBuilder stickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters, String fieldName, String facetName, - Object... selected) { - return stickyFacetBuilder(query, filters, fieldName, facetName, FACET_DEFAULT_SIZE, FACET_DEFAULT_MIN_DOC_COUNT, selected); - } - - protected AggregationBuilder stickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters, String fieldName, String facetName, int size, int minDocCount, - Object... selected) { - BoolFilterBuilder facetFilter = getStickyFacetFilter(query, filters, fieldName); - FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size, minDocCount); - facetTopAggregation = addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, selected); - - return AggregationBuilders - .global(facetName) - .subAggregation(facetTopAggregation); - } - - protected BoolFilterBuilder getStickyFacetFilter(QueryBuilder query, Map<String, FilterBuilder> filters, String fieldName) { - BoolFilterBuilder facetFilter = FilterBuilders.boolFilter().must(FilterBuilders.queryFilter(query)); - for (Map.Entry<String, FilterBuilder> filter : filters.entrySet()) { - if (filter.getValue() != null && !StringUtils.equals(filter.getKey(), fieldName)) { - facetFilter.must(filter.getValue()); - } - } - return facetFilter; - } - - protected FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter, int size, int minDocCount) { - return AggregationBuilders - .filter(facetName + "_filter") - .filter(facetFilter) - .subAggregation( - AggregationBuilders.terms(facetName) - .field(fieldName) - .order(Terms.Order.count(false)) - .size(size) - .minDocCount(minDocCount)); - } - - protected FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter) { - return buildTopFacetAggregation(fieldName, facetName, facetFilter, FACET_DEFAULT_SIZE, FACET_DEFAULT_MIN_DOC_COUNT); - } - - protected FilterAggregationBuilder addSelectedItemsToFacet(String fieldName, String facetName, FilterAggregationBuilder facetTopAggregation, Object... selected) { - if (selected.length > 0) { - facetTopAggregation.subAggregation( - AggregationBuilders.terms(facetName + "_selected") - .field(fieldName) - .include(Joiner.on('|').join(selected))); - } - return facetTopAggregation; + protected StickyFacetBuilder stickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters) { + return new StickyFacetBuilder(query, filters); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java b/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java new file mode 100644 index 00000000000..09a16598be6 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/search/StickyFacetBuilder.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.search; + +import com.google.common.base.Joiner; +import org.apache.commons.lang.StringUtils; +import org.elasticsearch.index.query.BoolFilterBuilder; +import org.elasticsearch.index.query.FilterBuilder; +import org.elasticsearch.index.query.FilterBuilders; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.search.aggregations.AggregationBuilder; +import org.elasticsearch.search.aggregations.AggregationBuilders; +import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder; +import org.elasticsearch.search.aggregations.bucket.terms.Terms; + +import java.util.Map; + +public class StickyFacetBuilder { + + private static final int FACET_DEFAULT_MIN_DOC_COUNT = 1; + + private static final int FACET_DEFAULT_SIZE = 10; + + private QueryBuilder query; + + private Map<String, FilterBuilder> filters; + + public StickyFacetBuilder(QueryBuilder query, Map<String, FilterBuilder> filters) { + this.query = query; + this.filters = filters; + } + + public QueryBuilder query() { + return query; + } + + public Map<String, FilterBuilder> filters() { + return filters; + } + + public AggregationBuilder buildStickyFacet(String fieldName, String facetName, Object... selected) { + return buildStickyFacet(fieldName, facetName, FACET_DEFAULT_SIZE, FACET_DEFAULT_MIN_DOC_COUNT, selected); + } + + public AggregationBuilder buildStickyFacet(String fieldName, String facetName, int size, int minDocCount, Object... selected) { + BoolFilterBuilder facetFilter = getStickyFacetFilter(fieldName); + FilterAggregationBuilder facetTopAggregation = buildTopFacetAggregation(fieldName, facetName, facetFilter, size, minDocCount); + facetTopAggregation = addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, selected); + + return AggregationBuilders + .global(facetName) + .subAggregation(facetTopAggregation); + } + + public BoolFilterBuilder getStickyFacetFilter(String fieldName) { + BoolFilterBuilder facetFilter = FilterBuilders.boolFilter().must(FilterBuilders.queryFilter(query)); + for (Map.Entry<String, FilterBuilder> filter : filters.entrySet()) { + if (filter.getValue() != null && !StringUtils.equals(filter.getKey(), fieldName)) { + facetFilter.must(filter.getValue()); + } + } + return facetFilter; + } + + public FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter, int size, int minDocCount) { + return AggregationBuilders + .filter(facetName + "_filter") + .filter(facetFilter) + .subAggregation( + AggregationBuilders.terms(facetName) + .field(fieldName) + .order(Terms.Order.count(false)) + .size(size) + .minDocCount(minDocCount)); + } + + protected FilterAggregationBuilder buildTopFacetAggregation(String fieldName, String facetName, BoolFilterBuilder facetFilter) { + return buildTopFacetAggregation(fieldName, facetName, facetFilter, FACET_DEFAULT_SIZE, FACET_DEFAULT_MIN_DOC_COUNT); + } + + public FilterAggregationBuilder addSelectedItemsToFacet(String fieldName, String facetName, FilterAggregationBuilder facetTopAggregation, Object... selected) { + if (selected.length > 0) { + facetTopAggregation.subAggregation( + AggregationBuilders.terms(facetName + "_selected") + .field(fieldName) + .include(Joiner.on('|').join(selected))); + } + return facetTopAggregation; + } +} |