]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5531 - Implemented query Filters for IssueIndex
authorStephane Gamard <stephane.gamard@sonarsource.com>
Fri, 5 Sep 2014 10:10:28 +0000 (12:10 +0200)
committerStephane Gamard <stephane.gamard@sonarsource.com>
Fri, 5 Sep 2014 10:10:28 +0000 (12:10 +0200)
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java [new file with mode: 0644]

index 50bf8fa0862adfa77910559f762d50b7fe129b1b..023c5b520fad99fbb455ef864c4cdb56945d666b 100644 (file)
 package org.sonar.server.issue.index;
 
 import com.google.common.base.Preconditions;
+import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.settings.ImmutableSettings;
 import org.elasticsearch.common.settings.Settings;
+import org.elasticsearch.common.unit.TimeValue;
+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.sonar.api.issue.IssueQuery;
 import org.sonar.core.issue.db.IssueDto;
@@ -33,6 +39,7 @@ import org.sonar.server.search.QueryOptions;
 import org.sonar.server.search.SearchClient;
 
 import java.io.IOException;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -107,10 +114,75 @@ public class IssueIndex extends BaseIndex<IssueDoc, IssueDto, String> {
 
   public SearchResponse search(IssueQuery query, QueryOptions options) {
 
-    // TODO implement filters and search
+    SearchRequestBuilder esSearch = getClient()
+      .prepareSearch(this.getIndexName())
+      .setTypes(this.getIndexType())
+      .setIndices(this.getIndexName());
 
-    return getClient().execute(
-      getClient().prepareSearch(getIndexName())
-        .setQuery(QueryBuilders.matchAllQuery()));
+    if (options.isScroll()) {
+      esSearch.setSearchType(SearchType.SCAN);
+      esSearch.setScroll(TimeValue.timeValueMinutes(3));
+    }
+
+    BoolFilterBuilder esFilter = FilterBuilders.boolFilter();
+
+    // Issue is assigned Filter
+    if (query.assigned() != null && query.assigned()) {
+      esFilter.must(FilterBuilders.existsFilter(IssueNormalizer.IssueField.ASSIGNEE.field()));
+    }
+
+    // Issue is planned Filter
+    if (query.planned() != null && query.planned()) {
+      esFilter.must(FilterBuilders.existsFilter(IssueNormalizer.IssueField.ACTION_PLAN.field()));
+    }
+
+    // Issue is Resolved Filter
+    if (query.resolved() != null && query.resolved()) {
+      esFilter.must(FilterBuilders.existsFilter(IssueNormalizer.IssueField.RESOLUTION.field()));
+    }
+
+    // Field Filters
+    matchFilter(esFilter, IssueNormalizer.IssueField.ACTION_PLAN, query.actionPlans());
+    matchFilter(esFilter, IssueNormalizer.IssueField.ASSIGNEE, query.assignees());
+    matchFilter(esFilter, IssueNormalizer.IssueField.PROJECT, query.componentRoots());
+    matchFilter(esFilter, IssueNormalizer.IssueField.COMPONENT, query.components());
+    matchFilter(esFilter, IssueNormalizer.IssueField.KEY, query.issueKeys());
+    // TODO need to either materialize the language or join with rule
+    // query.languages(esFilter, IssueNormalizer.IssueField.L, query.issueKeys());
+    matchFilter(esFilter, IssueNormalizer.IssueField.RESOLUTION, query.resolutions());
+    matchFilter(esFilter, IssueNormalizer.IssueField.REPORTER, query.reporters());
+    matchFilter(esFilter, IssueNormalizer.IssueField.RULE, query.rules());
+    matchFilter(esFilter, IssueNormalizer.IssueField.SEVERITY, query.severities());
+    matchFilter(esFilter, IssueNormalizer.IssueField.STATUS, query.statuses());
+
+    // Date filters
+    if (query.createdAfter() != null) {
+      esFilter.must(FilterBuilders
+        .rangeFilter(IssueNormalizer.IssueField.ISSUE_CREATED_AT.field())
+        .gte(query.createdAfter()));
+    }
+    if (query.createdBefore() != null) {
+      esFilter.must(FilterBuilders
+        .rangeFilter(IssueNormalizer.IssueField.ISSUE_CREATED_AT.field())
+        .lte(query.createdBefore()));
+    }
+    // TODO match day bracket for day on createdAt
+    // query.createdAt();
+
+    QueryBuilder esQuery = QueryBuilders.matchAllQuery();
+
+    if (esFilter.hasClauses()) {
+      esSearch.setQuery(QueryBuilders.filteredQuery(esQuery, esFilter));
+    } else {
+      esSearch.setQuery(esQuery);
+    }
+
+    return getClient().execute(esSearch);
+  }
+
+  private void matchFilter(BoolFilterBuilder filter, IndexField field, Collection<?> values) {
+    if (values != null && !values.isEmpty()) {
+      filter.must(FilterBuilders.termsFilter(field.field(), values));
+    }
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
new file mode 100644 (file)
index 0000000..6e48b4d
--- /dev/null
@@ -0,0 +1,155 @@
+package org.sonar.server.issue.index;
+
+import com.google.common.collect.ImmutableList;
+import org.elasticsearch.action.search.SearchResponse;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.component.persistence.ComponentDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.QueryOptions;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.UUID;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IssueIndexMediumTest {
+
+  @ClassRule
+  public static ServerTester tester = new ServerTester();
+
+  DbClient db;
+  DbSession session;
+  IssueIndex index;
+
+  RuleDto rule;
+  ComponentDto project;
+  ComponentDto resource;
+
+  @Before
+  public void setUp() throws Exception {
+    tester.clearDbAndIndexes();
+    db = tester.get(DbClient.class);
+    session = db.openSession(false);
+    index = tester.get(IssueIndex.class);
+
+    rule = RuleTesting.newXooX1();
+    tester.get(RuleDao.class).insert(session, rule);
+
+    project = new ComponentDto()
+      .setId(1L)
+      .setKey("MyProject")
+      .setProjectId(1L);
+    tester.get(ComponentDao.class).insert(session, project);
+
+    resource = new ComponentDto()
+      .setProjectId(1L)
+      .setKey("MyComponent")
+      .setId(2L);
+    tester.get(ComponentDao.class).insert(session, resource);
+  }
+
+  @After
+  public void after() {
+    session.close();
+  }
+
+  @Test
+  public void filter_by_actionPlan() throws Exception {
+
+    String plan1 = "plan1";
+    String plan2 = "plan2";
+    IssueDto issue1 = getIssue()
+      .setActionPlanKey(plan1);
+    IssueDto issue2 = getIssue()
+      .setActionPlanKey(plan2);
+    db.issueDao().insert(session, issue1, issue2);
+    session.commit();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+    query.actionPlans(ImmutableList.of(plan1));
+    SearchResponse result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
+
+    query = IssueQuery.builder();
+    query.actionPlans(ImmutableList.of(plan2));
+    result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
+
+    query = IssueQuery.builder();
+    query.actionPlans(ImmutableList.of(plan2, plan1));
+    result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
+  }
+
+  @Test
+  public void is_assigned_filter() throws Exception {
+
+    String assignee = "steph";
+    IssueDto issue1 = getIssue()
+      .setAssignee(assignee);
+    IssueDto issue2 = getIssue();
+    db.issueDao().insert(session, issue1, issue2);
+    session.commit();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+    SearchResponse result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
+
+    query = IssueQuery.builder();
+    query.assigned(true);
+    result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
+  }
+
+  @Test
+  public void filter_assignee() throws Exception {
+
+    String assignee1 = "steph";
+    String assignee2 = "simon";
+    IssueDto issue1 = getIssue()
+      .setAssignee(assignee1);
+    IssueDto issue2 = getIssue()
+      .setAssignee(assignee2);
+    IssueDto issue3 = getIssue();
+    db.issueDao().insert(session, issue1, issue2, issue3);
+    session.commit();
+
+    IssueQuery.Builder query = IssueQuery.builder();
+    SearchResponse result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(3L);
+
+    query = IssueQuery.builder();
+    query.assignees(ImmutableList.of(assignee1));
+    result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(1L);
+
+    query = IssueQuery.builder();
+    query.assignees(ImmutableList.of(assignee1, assignee2));
+    result = index.search(query.build(), new QueryOptions());
+    assertThat(result.getHits().getTotalHits()).isEqualTo(2L);
+  }
+
+  private IssueDto getIssue() {
+    return new IssueDto()
+      .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+      .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
+      .setRule(rule)
+      .setDebt(10L)
+      .setRootComponent(project)
+      .setComponent(resource)
+      .setStatus("OPEN").setResolution("OPEN")
+      .setSeverity("MAJOR")
+      .setKee(UUID.randomUUID().toString());
+  }
+}