http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchIndexingIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchIndexingIntegrationTest.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchIndexingIntegrationTest.java
index 4c03526..1efcc39 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchIndexingIntegrationTest.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchIndexingIntegrationTest.java
@@ -17,6 +17,7 @@
  */
 package org.apache.metron.elasticsearch.integration;
 
+import org.adrianwalker.multilinestring.Multiline;
 import org.apache.metron.common.interfaces.FieldNameConverter;
 import 
org.apache.metron.elasticsearch.integration.components.ElasticSearchComponent;
 import org.apache.metron.elasticsearch.writer.ElasticsearchFieldNameConverter;
@@ -35,6 +36,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTest {
 
@@ -42,6 +44,20 @@ public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTes
   private String dateFormat = "yyyy.MM.dd.HH";
   private String index = "yaf_index_" + new 
SimpleDateFormat(dateFormat).format(new Date());
   private FieldNameConverter fieldNameConverter = new 
ElasticsearchFieldNameConverter();
+  /**
+   * {
+   * "yaf_doc": {
+   *   "properties": {
+   *     "source:type": { "type": "keyword" },
+   *     "guid": { "type": "keyword" },
+   *     "isn": { "type": "text" }
+   *   }
+   * }
+   * }
+   */
+  @Multiline
+  private static String mapping;
+
 
   @Override
   public FieldNameConverter getFieldNameConverter() {
@@ -53,6 +69,7 @@ public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTes
     return new ElasticSearchComponent.Builder()
             .withHttpPort(9211)
             .withIndexDir(new File(indexDir))
+            .withMapping(index, "yaf_doc", mapping)
             .build();
   }
 
@@ -61,6 +78,7 @@ public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTes
     return new Processor<List<Map<String, Object>>>() {
       List<Map<String, Object>> docs = null;
       List<byte[]> errors = null;
+      final AtomicInteger missCount = new AtomicInteger(0);
       @Override
       public ReadinessState process(ComponentRunner runner) {
         ElasticSearchComponent elasticSearchComponent = 
runner.getComponent("search", ElasticSearchComponent.class);
@@ -70,7 +88,9 @@ public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTes
           try {
             docs = elasticSearchComponent.getAllIndexedDocs(index, 
testSensorType + "_doc");
             docsFromDisk = readDocsFromDisk(hdfsDir);
-            System.out.println(docs.size() + " vs " + inputMessages.size() + " 
vs " + docsFromDisk.size());
+            if(missCount.incrementAndGet() >= NUM_RETRIES/2) {
+              System.out.println(missCount.get() + ": " + docs.size() + " vs " 
+ inputMessages.size() + " vs " + docsFromDisk.size());
+            }
           } catch (IOException e) {
             throw new IllegalStateException("Unable to retrieve indexed 
documents.", e);
           }
@@ -84,7 +104,6 @@ public class ElasticsearchIndexingIntegrationTest extends 
IndexingIntegrationTes
             return ReadinessState.READY;
           }
         } else {
-          System.out.println("Missed index...");
           return ReadinessState.NOT_READY;
         }
       }

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchMetaAlertIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchMetaAlertIntegrationTest.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchMetaAlertIntegrationTest.java
index 35f40ca..9e74fb6 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchMetaAlertIntegrationTest.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchMetaAlertIntegrationTest.java
@@ -23,9 +23,10 @@ import static 
org.apache.metron.indexing.dao.MetaAlertDao.METAALERTS_INDEX;
 import static org.apache.metron.indexing.dao.MetaAlertDao.METAALERT_FIELD;
 import static org.apache.metron.indexing.dao.MetaAlertDao.METAALERT_TYPE;
 import static org.apache.metron.indexing.dao.MetaAlertDao.STATUS_FIELD;
-import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
 import java.io.File;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
@@ -34,9 +35,11 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 import org.adrianwalker.multilinestring.Multiline;
 import org.apache.metron.common.Constants;
@@ -159,6 +162,29 @@ public class ElasticsearchMetaAlertIntegrationTest {
   @Multiline
   public static String statusPatchRequest;
 
+  /**
+   * {
+       "%MAPPING_NAME%_doc" : {
+         "properties" : {
+           "guid" : {
+             "type" : "keyword"
+           },
+           "ip_src_addr" : {
+             "type" : "keyword"
+           },
+           "score" : {
+             "type" : "integer"
+           },
+           "alert" : {
+             "type" : "nested"
+           }
+         }
+       }
+   }
+   */
+  @Multiline
+  public static String template;
+
   @BeforeClass
   public static void setupBefore() throws Exception {
     // setup the client
@@ -188,8 +214,8 @@ public class ElasticsearchMetaAlertIntegrationTest {
 
   @Before
   public void setup() throws IOException {
-    es.createIndexWithMapping(METAALERTS_INDEX, MetaAlertDao.METAALERT_DOC,
-        buildMetaMappingSource());
+    es.createIndexWithMapping(METAALERTS_INDEX, MetaAlertDao.METAALERT_DOC, 
template.replace("%MAPPING_NAME%", "metaalert"));
+    es.createIndexWithMapping(INDEX, "index_doc", 
template.replace("%MAPPING_NAME%", "index"));
   }
 
   @AfterClass
@@ -204,27 +230,6 @@ public class ElasticsearchMetaAlertIntegrationTest {
     es.reset();
   }
 
-  protected static String buildMetaMappingSource() throws IOException {
-    return jsonBuilder().prettyPrint()
-        .startObject()
-        .startObject(MetaAlertDao.METAALERT_DOC)
-        .startObject("properties")
-        .startObject("guid")
-        .field("type", "string")
-        .field("index", "not_analyzed")
-        .endObject()
-        .startObject("score")
-        .field("type", "integer")
-        .field("index", "not_analyzed")
-        .endObject()
-        .startObject("alert")
-        .field("type", "nested")
-        .endObject()
-        .endObject()
-        .endObject()
-        .endObject()
-        .string();
-  }
 
   @Test
   public void shouldGetAllMetaAlertsForAlert() throws Exception {
@@ -259,7 +264,11 @@ public class ElasticsearchMetaAlertIntegrationTest {
       SearchResponse searchResponse0 = 
metaDao.getAllMetaAlertsForAlert("message_0");
       List<SearchResult> searchResults0 = searchResponse0.getResults();
       Assert.assertEquals(13, searchResults0.size());
-      Assert.assertEquals(metaAlerts.get(0), 
searchResults0.get(0).getSource());
+      Set<Map<String, Object>> resultSet = new HashSet<>();
+      Iterables.addAll(resultSet, Iterables.transform(searchResults0, r -> 
r.getSource()));
+      StringBuffer reason = new StringBuffer("Unable to find " + 
metaAlerts.get(0) + "\n");
+      reason.append(Joiner.on("\n").join(resultSet));
+      Assert.assertTrue(reason.toString(), 
resultSet.contains(metaAlerts.get(0)));
 
       // Verify no meta alerts are returned because message_1 was not added to 
any
       SearchResponse searchResponse1 = 
metaDao.getAllMetaAlertsForAlert("message_1");
@@ -760,14 +769,14 @@ public class ElasticsearchMetaAlertIntegrationTest {
 
     // Query against all indices. The child alert has no actual attached meta 
alerts, and should
     // be returned on its own.
-    searchResponse = metaDao.search(new SearchRequest() {
+   searchResponse = metaDao.search(new SearchRequest() {
       {
         setQuery(
             "(ip_src_addr:192.168.1.3 AND ip_src_port:8008)"
                 + " OR (alert.ip_src_addr:192.168.1.3 AND 
alert.ip_src_port:8008)");
         setIndices(Collections.singletonList("*"));
         setFrom(0);
-        setSize(5);
+        setSize(1);
         setSort(Collections.singletonList(new SortField() {
           {
             setField(Constants.GUID);

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
index eac4851..3949c6d 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
@@ -17,17 +17,24 @@
  */
 package org.apache.metron.elasticsearch.integration;
 
+
+import java.io.File;
+import java.util.HashMap;
+import java.io.IOException;
+import java.util.concurrent.ExecutionException;
 import org.adrianwalker.multilinestring.Multiline;
 import org.apache.metron.elasticsearch.dao.ElasticsearchDao;
 import 
org.apache.metron.elasticsearch.integration.components.ElasticSearchComponent;
 import org.apache.metron.indexing.dao.AccessConfig;
 import org.apache.metron.indexing.dao.IndexDao;
+import org.apache.metron.indexing.dao.MetaAlertDao;
 import org.apache.metron.indexing.dao.SearchIntegrationTest;
 import org.apache.metron.integration.InMemoryComponent;
 import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.index.IndexRequestBuilder;
+import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
@@ -53,8 +60,11 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
    * "bro_doc": {
    *   "properties": {
    *     "source:type": {
-   *        "type": "string",
-   *        "index": "not_analyzed"
+   *        "type": "text",
+   *        "fielddata" : "true"
+   *     },
+   *     "guid" : {
+   *        "type" : "keyword"
    *     },
    *     "ip_src_addr": {
    *        "type": "ip"
@@ -82,10 +92,12 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
    *        "type": "geo_point"
    *     },
    *     "bro_field": {
-   *        "type": "string"
+   *        "type": "text",
+   *        "fielddata" : "true"
    *     },
    *     "duplicate_name_field": {
-   *        "type": "string"
+   *        "type": "text",
+   *        "fielddata" : "true"
    *     },
    *     "alert": {
    *         "type": "nested"
@@ -102,8 +114,11 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
    *  "snort_doc": {
    *     "properties": {
    *        "source:type": {
-   *          "type": "string",
-   *          "index": "not_analyzed"
+   *          "type": "text",
+   *          "fielddata" : "true"
+   *        },
+   *        "guid" : {
+   *          "type" : "keyword"
    *        },
    *        "ip_src_addr": {
    *          "type": "ip"
@@ -170,8 +185,23 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
    * {
    * "metaalert_doc": {
    *   "properties": {
-   *     "source:type": { "type": "string" },
-   *     "alert": { "type": "nested"}
+   *     "guid": { "type": "keyword" },
+   *     "alert": {
+   *        "type": "nested",
+   *        "properties": {
+   *          "guid": { "type": "keyword" }
+   *        }
+   *     },
+   *     "average": { "type": "keyword" },
+   *     "min" : { "type": "keyword" },
+   *     "median" : { "type": "keyword" },
+   *     "max": { "type": "keyword" },
+   *     "count": { "type": "keyword" },
+   *     "sum": { "type": "keyword" },
+   *     "source:type": {
+   *       "type": "text",
+   *       "fielddata" : "true"
+   *                    }
    *   }
    * }
    * }
@@ -216,10 +246,10 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
             .addMapping("bro_doc", 
broTypeMappings).addMapping("bro_doc_default", broDefaultStringMappings).get();
     es.getClient().admin().indices().prepareCreate("snort_index_2017.01.01.02")
             .addMapping("snort_doc", snortTypeMappings).get();
-    es.getClient().admin().indices().prepareCreate("metaalert_index")
-        .addMapping("metaalert_doc", metaAlertTypeMappings).get();
+    
es.getClient().admin().indices().prepareCreate(MetaAlertDao.METAALERTS_INDEX)
+        .addMapping(MetaAlertDao.METAALERT_DOC, metaAlertTypeMappings).get();
 
-    BulkRequestBuilder bulkRequest = 
es.getClient().prepareBulk().setRefresh(true);
+    BulkRequestBuilder bulkRequest = 
es.getClient().prepareBulk().setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);
     JSONArray broArray = (JSONArray) new JSONParser().parse(broData);
     for(Object o: broArray) {
       JSONObject jsonObject = (JSONObject) o;

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
index 3ef9379..f95ef21 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
@@ -17,7 +17,18 @@
  */
 package org.apache.metron.elasticsearch.integration.components;
 
+import static java.util.Arrays.asList;
+
 import com.fasterxml.jackson.core.type.TypeReference;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import org.apache.commons.io.FileUtils;
 import org.apache.metron.common.Constants;
 import org.apache.metron.common.utils.JSONUtils;
@@ -29,210 +40,251 @@ import 
org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
 import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
-import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
+import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
 import org.elasticsearch.action.bulk.BulkRequestBuilder;
 import org.elasticsearch.action.bulk.BulkResponse;
 import org.elasticsearch.action.index.IndexRequestBuilder;
-import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
-import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.client.Client;
-import org.elasticsearch.client.ElasticsearchClient;
+import org.elasticsearch.cluster.health.ClusterHealthStatus;
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.node.InternalSettingsPreparer;
 import org.elasticsearch.node.Node;
-import org.elasticsearch.node.NodeBuilder;
+import org.elasticsearch.node.NodeValidationException;
+import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.search.SearchHit;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import org.elasticsearch.transport.Netty4Plugin;
 
 public class ElasticSearchComponent implements InMemoryComponent {
 
-    public static class Builder{
-        private int httpPort;
-        private File indexDir;
-        private Map<String, String> extraElasticSearchSettings = null;
-        public Builder withHttpPort(int httpPort) {
-            this.httpPort = httpPort;
-            return this;
-        }
-        public Builder withIndexDir(File indexDir) {
-            this.indexDir = indexDir;
-            return this;
-        }
-        public Builder withExtraElasticSearchSettings(Map<String, String> 
extraElasticSearchSettings) {
-            this.extraElasticSearchSettings = extraElasticSearchSettings;
-            return this;
-        }
-        public ElasticSearchComponent build() {
-            return new ElasticSearchComponent(httpPort, indexDir, 
extraElasticSearchSettings);
-        }
-    }
-
-    private Client client;
-    private Node node;
+  private static class Mapping {
+    String index;
+    String docType;
+    String mapping;
+
+    public Mapping(String index, String docType, String mapping) {
+      this.index = index;
+      this.docType = docType;
+      this.mapping = mapping;
+    }
+  }
+
+  public static class Builder {
+
     private int httpPort;
     private File indexDir;
-    private Map<String, String> extraElasticSearchSettings;
+    private Map<String, String> extraElasticSearchSettings = null;
+    private List<Mapping> mappings = new ArrayList<>();
 
-    public ElasticSearchComponent(int httpPort, File indexDir) {
-        this(httpPort, indexDir, null);
+    public Builder withMapping(String index, String docType, String mapping) {
+      mappings.add(new Mapping(index, docType, mapping));
+      return this;
     }
-    public ElasticSearchComponent(int httpPort, File indexDir, Map<String, 
String> extraElasticSearchSettings) {
-        this.httpPort = httpPort;
-        this.indexDir = indexDir;
-        this.extraElasticSearchSettings = extraElasticSearchSettings;
+
+    public Builder withHttpPort(int httpPort) {
+      this.httpPort = httpPort;
+      return this;
     }
-    public Client getClient() {
-        return client;
+
+    public Builder withIndexDir(File indexDir) {
+      this.indexDir = indexDir;
+      return this;
     }
 
-    private void cleanDir(File dir) throws IOException {
-        if(dir.exists()) {
-            FileUtils.deleteDirectory(dir);
-        }
-        dir.mkdirs();
+    public Builder withExtraElasticSearchSettings(
+        Map<String, String> extraElasticSearchSettings) {
+      this.extraElasticSearchSettings = extraElasticSearchSettings;
+      return this;
     }
 
-    public BulkResponse add(String indexName, String sensorType, String... 
docs) throws IOException {
-        List<String> d = new ArrayList<>();
-        Collections.addAll(d, docs);
-        return add(indexName, sensorType, d);
+    public ElasticSearchComponent build() {
+      return new ElasticSearchComponent(httpPort, indexDir, 
extraElasticSearchSettings, mappings);
     }
+  }
 
-    public BulkResponse add(String indexName, String sensorType, 
Iterable<String> docs) throws IOException {
-        BulkRequestBuilder bulkRequest = getClient().prepareBulk();
-        for(String doc : docs) {
-            IndexRequestBuilder indexRequestBuilder = 
getClient().prepareIndex(indexName,
-                    sensorType + "_doc");
+  private static final String STARTUP_TIMEOUT = "60s";
+  private Client client;
+  private Node node;
+  private int httpPort;
+  private File indexDir;
+  private Map<String, String> extraElasticSearchSettings;
+  private List<Mapping> mappings;
 
-            indexRequestBuilder = indexRequestBuilder.setSource(doc);
-            Map<String, Object> esDoc = JSONUtils.INSTANCE.load(doc, new 
TypeReference<Map<String, Object>>() {
-            });
-            indexRequestBuilder.setId((String) esDoc.get(Constants.GUID));
-            Object ts = esDoc.get("timestamp");
-            if(ts != null) {
-                indexRequestBuilder = 
indexRequestBuilder.setTimestamp(ts.toString());
-            }
-            bulkRequest.add(indexRequestBuilder);
-        }
+  public ElasticSearchComponent(int httpPort, File indexDir,
+      Map<String, String> extraElasticSearchSettings, List<Mapping> mappings) {
+    this.httpPort = httpPort;
+    this.indexDir = indexDir;
+    this.extraElasticSearchSettings = extraElasticSearchSettings;
+    this.mappings = mappings;
+  }
 
-        BulkResponse response = bulkRequest.execute().actionGet();
-        if(response.hasFailures()) {
-            throw new IOException(response.buildFailureMessage());
-        }
-        return response;
+  @Override
+  public void start() throws UnableToStartException {
+    File logDir = new File(indexDir, "/logs");
+    File dataDir = new File(indexDir, "/data");
+    try {
+      cleanDir(logDir);
+      cleanDir(dataDir);
+    } catch (IOException e) {
+      throw new UnableToStartException("Unable to clean log or data 
directories", e);
     }
 
-    public void createIndexWithMapping(String indexName, String mappingType, 
String mappingSource)
-        throws IOException {
-        CreateIndexResponse cir = 
client.admin().indices().prepareCreate(indexName)
-            .addMapping(mappingType, mappingSource)
-            .get();
+    Settings.Builder settingsBuilder = Settings.builder()
+        .put("cluster.name", "metron")
+        .put("path.logs",logDir.getAbsolutePath())
+        .put("path.data",dataDir.getAbsolutePath())
+        .put("path.home", indexDir.getAbsoluteFile())
+        .put("transport.type", "netty4")
+        .put("http.enabled", "false");
 
-        if (!cir.isAcknowledged()) {
-            throw new IOException("Create index was not acknowledged");
-        }
+    if (extraElasticSearchSettings != null) {
+      settingsBuilder = settingsBuilder.put(extraElasticSearchSettings);
     }
 
-    @Override
-    public void start() throws UnableToStartException {
-        File logDir= new File(indexDir, "/logs");
-        File dataDir= new File(indexDir, "/data");
-        try {
-            cleanDir(logDir);
-            cleanDir(dataDir);
-
-        } catch (IOException e) {
-            throw new UnableToStartException("Unable to clean log or data 
directories", e);
-        }
-
-        Settings.Builder settingsBuilder = Settings.settingsBuilder()
-                .put("node.http.enabled", true)
-                .put("http.port", httpPort)
-                .put("path.logs",logDir.getAbsolutePath())
-                .put("path.data",dataDir.getAbsolutePath())
-                .put("path.home", indexDir.getAbsoluteFile())
-                .put("index.number_of_shards", 1)
-                .put("node.mode", "network")
-                .put("index.number_of_replicas", 1);
-
-        if(extraElasticSearchSettings != null) {
-
-            settingsBuilder = settingsBuilder.put(extraElasticSearchSettings);
-
-        }
-
-        node = 
NodeBuilder.nodeBuilder().settings(settingsBuilder).clusterName("metron").node();
-        node.start();
-
-        client = node.client();
-
-        waitForCluster(client, ClusterHealthStatus.YELLOW, new 
TimeValue(60000));
-
-    }
-
-    public static void waitForCluster(ElasticsearchClient client, 
ClusterHealthStatus status, TimeValue timeout) throws UnableToStartException {
-        try {
-            ClusterHealthResponse healthResponse =
-                    
(ClusterHealthResponse)client.execute(ClusterHealthAction.INSTANCE, new 
ClusterHealthRequest().waitForStatus(status).timeout(timeout)).actionGet();
-            if (healthResponse != null && healthResponse.isTimedOut()) {
-                throw new UnableToStartException("cluster state is " + 
healthResponse.getStatus().name()
-                        + " and not " + status.name()
-                        + ", from here on, everything will fail!");
-            }
-        } catch (ElasticsearchTimeoutException e) {
-            throw new UnableToStartException("timeout, cluster does not 
respond to health request, cowardly refusing to continue with operations");
-        }
-    }
-
-    public List<Map<String, Object>> getAllIndexedDocs(String index, String 
sourceType) throws IOException {
-       return getAllIndexedDocs(index, sourceType, null);
-    }
-    public List<Map<String, Object>> getAllIndexedDocs(String index, String 
sourceType, String subMessage) throws IOException {
-        getClient().admin().indices().refresh(new RefreshRequest());
-        SearchResponse response = getClient().prepareSearch(index)
-                .setTypes(sourceType)
-                .setSource("message")
-                .setFrom(0)
-                .setSize(1000)
-                .execute().actionGet();
-        List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
-        for (SearchHit hit : response.getHits()) {
-            Object o = null;
-            if(subMessage == null) {
-                o = hit.getSource();
-            }
-            else {
-                o = hit.getSource().get(subMessage);
-            }
-            ret.add((Map<String, Object>)(o));
-        }
-        return ret;
-    }
-    public boolean hasIndex(String indexName) {
-        Set<String> indices = getClient().admin()
-                                    .indices()
-                                    .stats(new IndicesStatsRequest())
-                                    .actionGet()
-                                    .getIndices()
-                                    .keySet();
-        return indices.contains(indexName);
+    node = new TestNode(settingsBuilder.build(), asList(Netty4Plugin.class));
+    client = node.client();
+    try {
+      node.start();
+    } catch (NodeValidationException e) {
+      throw new UnableToStartException("Error starting ES node.", e);
+    }
+    waitForCluster(client, ClusterHealthStatus.YELLOW, STARTUP_TIMEOUT);
+    for(Mapping m : Optional.ofNullable(mappings).orElse(new ArrayList<>())) {
+          client.admin().indices().prepareCreate(m.index)
+            .addMapping(m.docType, m.mapping).get();
+    }
+  }
+
+  private void cleanDir(File dir) throws IOException {
+    if (dir.exists()) {
+      FileUtils.deleteDirectory(dir);
+    }
+    dir.mkdirs();
+  }
+
+  // ES 5.x+ needs this to startup a node without using their test framework
+  private static class TestNode extends Node {
+
+    private TestNode(Settings preparedSettings,
+        Collection<Class<? extends Plugin>> classpathPlugins) {
+      super(InternalSettingsPreparer.prepareEnvironment(preparedSettings, 
null), classpathPlugins);
+    }
+
+  }
+
+  public static void waitForCluster(Client client, ClusterHealthStatus 
statusThreshold,
+      String timeout) throws UnableToStartException {
+    try {
+      ClusterHealthResponse healthResponse = (ClusterHealthResponse) client
+          .execute(ClusterHealthAction.INSTANCE,
+              new 
ClusterHealthRequest().waitForStatus(statusThreshold).timeout(timeout))
+          .actionGet();
+      if (healthResponse != null && healthResponse.isTimedOut()) {
+        throw new UnableToStartException("cluster state is " + 
healthResponse.getStatus().name()
+            + " and not " + statusThreshold.name()
+            + ", from here on, everything will fail!");
+      }
+    } catch (ElasticsearchTimeoutException e) {
+      throw new UnableToStartException(
+          "timeout, cluster does not respond to health request, cowardly 
refusing to continue with operations");
+    }
+  }
 
+  public Client getClient() {
+    return client;
+  }
+
+  public BulkResponse add(String indexName, String sensorType, String... docs) 
throws IOException {
+    List<String> d = new ArrayList<>();
+    Collections.addAll(d, docs);
+    return add(indexName, sensorType, d);
+  }
+
+  public BulkResponse add(String indexName, String sensorType, 
Iterable<String> docs)
+      throws IOException {
+    BulkRequestBuilder bulkRequest = getClient().prepareBulk();
+    for (String doc : docs) {
+      IndexRequestBuilder indexRequestBuilder = getClient()
+          .prepareIndex(indexName, sensorType + "_doc");
+
+      indexRequestBuilder = indexRequestBuilder.setSource(doc);
+      Map<String, Object> esDoc = JSONUtils.INSTANCE
+          .load(doc, new TypeReference<Map<String, Object>>() {
+          });
+      indexRequestBuilder.setId((String) esDoc.get(Constants.GUID));
+      Object ts = esDoc.get("timestamp");
+      if (ts != null) {
+        indexRequestBuilder = indexRequestBuilder.setTimestamp(ts.toString());
+      }
+      bulkRequest.add(indexRequestBuilder);
     }
 
+    BulkResponse response = bulkRequest.execute().actionGet();
+    if (response.hasFailures()) {
+      throw new IOException(response.buildFailureMessage());
+    }
+    return response;
+  }
+
+  public void createIndexWithMapping(String indexName, String mappingType, 
String mappingSource)
+      throws IOException {
+    CreateIndexResponse cir = client.admin().indices().prepareCreate(indexName)
+        .addMapping(mappingType, mappingSource)
+        .get();
+
+    if (!cir.isAcknowledged()) {
+      throw new IOException("Create index was not acknowledged");
+    }
+  }
+
+  public List<Map<String, Object>> getAllIndexedDocs(String index, String 
sourceType)
+      throws IOException {
+    return getAllIndexedDocs(index, sourceType, null);
+  }
+
+  public List<Map<String, Object>> getAllIndexedDocs(String index, String 
sourceType,
+      String subMessage) throws IOException {
+    getClient().admin().indices().refresh(new RefreshRequest());
+    SearchResponse response = getClient().prepareSearch(index)
+        .setTypes(sourceType)
+//                .setSource("message") ??
+        .setFrom(0)
+        .setSize(1000)
+        .execute().actionGet();
+    List<Map<String, Object>> ret = new ArrayList<Map<String, Object>>();
+    for (SearchHit hit : response.getHits()) {
+      Object o = null;
+      if (subMessage == null) {
+        o = hit.getSource();
+      } else {
+        o = hit.getSource().get(subMessage);
+      }
+      ret.add((Map<String, Object>) (o));
+    }
+    return ret;
+  }
+
+  public boolean hasIndex(String indexName) {
+    Set<String> indices = getClient().admin()
+        .indices()
+        .stats(new IndicesStatsRequest())
+        .actionGet()
+        .getIndices()
+        .keySet();
+    return indices.contains(indexName);
+
+  }
+
     @Override
     public void stop() {
+      try {
         node.close();
-        node = null;
-        client = null;
+      } catch (IOException e) {
+        throw new RuntimeException("Unable to stop node." , e);
+      }
+      node = null;
+      client = null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-enrichment/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-enrichment/pom.xml 
b/metron-platform/metron-enrichment/pom.xml
index aab1826..e82b86b 100644
--- a/metron-platform/metron-enrichment/pom.xml
+++ b/metron-platform/metron-enrichment/pom.xml
@@ -200,6 +200,14 @@
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>
@@ -213,7 +221,18 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-hbase/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-hbase/pom.xml 
b/metron-platform/metron-hbase/pom.xml
index 98d7a36..746a610 100644
--- a/metron-platform/metron-hbase/pom.xml
+++ b/metron-platform/metron-hbase/pom.xml
@@ -140,6 +140,14 @@
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-indexing/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-indexing/pom.xml 
b/metron-platform/metron-indexing/pom.xml
index ea88154..e9fe43e 100644
--- a/metron-platform/metron-indexing/pom.xml
+++ b/metron-platform/metron-indexing/pom.xml
@@ -32,6 +32,12 @@
     </properties>
     <dependencies>
         <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.8.2</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.metron</groupId>
             <artifactId>metron-common</artifactId>
             <version>${project.parent.version}</version>
@@ -93,6 +99,10 @@
                     <artifactId>log4j-slf4j-impl</artifactId>
                     <groupId>org.apache.logging.log4j</groupId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <dependency>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/FieldType.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/FieldType.java
 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/FieldType.java
index 1f00cf5..2abd997 100644
--- 
a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/FieldType.java
+++ 
b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/search/FieldType.java
@@ -20,8 +20,10 @@ package org.apache.metron.indexing.dao.search;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 public enum FieldType {
-  @JsonProperty("string")
-  STRING("string"),
+  @JsonProperty("text")
+  TEXT("text"),
+  @JsonProperty("keyword")
+  KEYWORD("keyword"),
   @JsonProperty("ip")
   IP("ip"),
   @JsonProperty("integer")

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/SearchIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/SearchIntegrationTest.java
 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/SearchIntegrationTest.java
index 4d3ff9b..72e632f 100644
--- 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/SearchIntegrationTest.java
+++ 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/dao/SearchIntegrationTest.java
@@ -1,3 +1,4 @@
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -18,6 +19,13 @@
 package org.apache.metron.indexing.dao;
 
 import com.fasterxml.jackson.core.type.TypeReference;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import org.adrianwalker.multilinestring.Multiline;
 import org.apache.metron.common.utils.JSONUtils;
 import org.apache.metron.indexing.dao.search.FieldType;
@@ -34,7 +42,9 @@ import org.apache.metron.integration.InMemoryComponent;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -439,8 +449,21 @@ public abstract class SearchIntegrationTest {
     }
   }
 
+  @Rule
+  public ExpectedException thrown = ExpectedException.none();
+
   @Test
-  public void test() throws Exception {
+  public void find_one_guid() throws Exception {
+    GetRequest request = JSONUtils.INSTANCE.load(findOneGuidQuery, 
GetRequest.class);
+    Optional<Map<String, Object>> response = dao.getLatestResult(request);
+    Assert.assertTrue(response.isPresent());
+    Map<String, Object> doc = response.get();
+    Assert.assertEquals("bro", doc.get("source:type"));
+    Assert.assertEquals(3, doc.get("timestamp"));
+  }
+
+  @Test
+  public void all_query_returns_all_results() throws Exception {
     //All Query Testcase
     {
       SearchRequest request = JSONUtils.INSTANCE.load(allQuery, 
SearchRequest.class);
@@ -450,34 +473,29 @@ public abstract class SearchIntegrationTest {
       Assert.assertEquals(10, results.size());
       for(int i = 0;i < 5;++i) {
         Assert.assertEquals("snort", 
results.get(i).getSource().get("source:type"));
-        Assert.assertEquals(10-i, results.get(i).getSource().get("timestamp"));
+        Assert.assertEquals(10 - i, 
results.get(i).getSource().get("timestamp"));
       }
-      for(int i = 5;i < 10;++i) {
+      for (int i = 5; i < 10; ++i) {
         Assert.assertEquals("bro", 
results.get(i).getSource().get("source:type"));
-        Assert.assertEquals(10-i, results.get(i).getSource().get("timestamp"));
+        Assert.assertEquals(10 - i, 
results.get(i).getSource().get("timestamp"));
       }
     }
-    //Find One Guid Testcase
-    {
-      GetRequest request = JSONUtils.INSTANCE.load(findOneGuidQuery, 
GetRequest.class);
-      Optional<Map<String, Object>> response = dao.getLatestResult(request);
-      Assert.assertTrue(response.isPresent());
-      Map<String, Object> doc = response.get();
-      Assert.assertEquals("bro", doc.get("source:type"));
-      Assert.assertEquals(3, doc.get("timestamp"));
-    }
     //Get All Latest Guid Testcase
     {
       List<GetRequest> request = JSONUtils.INSTANCE.load(getAllLatestQuery, 
new TypeReference<List<GetRequest>>() {
       });
-      Iterator<Document> response = dao.getAllLatest(request).iterator();
-      Document bro2 = response.next();
-      Assert.assertEquals("bro_1", bro2.getDocument().get("guid"));
-      Assert.assertEquals("bro", bro2.getDocument().get("source:type"));
-      Document snort2 = response.next();
-      Assert.assertEquals("bro_2", snort2.getDocument().get("guid"));
-      Assert.assertEquals("bro", snort2.getDocument().get("source:type"));
-      Assert.assertFalse(response.hasNext());
+      Map<String, Document> docs = new HashMap<>();
+
+      for(Document doc : dao.getAllLatest(request)) {
+        docs.put(doc.getGuid(), doc);
+      }
+      Assert.assertEquals(2, docs.size());
+      Assert.assertTrue(docs.keySet().contains("bro-1"));
+      Assert.assertTrue(docs.keySet().contains("bro-2"));
+      for(Map.Entry<String, Document> kv : docs.entrySet()) {
+        Document d = kv.getValue();
+        Assert.assertEquals("bro", d.getDocument().get("source:type"));
+      }
     }
     //Filter test case
     {
@@ -679,43 +697,190 @@ public abstract class SearchIntegrationTest {
       SearchResponse response = dao.search(request);
       Assert.assertNull(response.getFacetCounts());
     }
-    //Exceeded maximum results query
-    {
-      SearchRequest request = JSONUtils.INSTANCE.load(exceededMaxResultsQuery, 
SearchRequest.class);
-      try {
-        dao.search(request);
-        Assert.fail("Exception expected, but did not come.");
-      }
-      catch(InvalidSearchException ise) {
-        Assert.assertEquals("Search result size must be less than 100", 
ise.getMessage());
-      }
+  }
+
+  @Test
+  public void filter_query_filters_results() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(filterQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(3, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    Assert.assertEquals("snort", 
results.get(0).getSource().get("source:type"));
+    Assert.assertEquals(9, results.get(0).getSource().get("timestamp"));
+    Assert.assertEquals("snort", 
results.get(1).getSource().get("source:type"));
+    Assert.assertEquals(7, results.get(1).getSource().get("timestamp"));
+    Assert.assertEquals("bro", results.get(2).getSource().get("source:type"));
+    Assert.assertEquals(1, results.get(2).getSource().get("timestamp"));
+  }
+
+  @Test
+  public void sort_query_sorts_results_ascending() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(sortQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(10, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    for (int i = 8001; i < 8011; ++i) {
+      Assert.assertEquals(i, results.get(i - 
8001).getSource().get("ip_src_port"));
     }
-    // getColumnMetadata with multiple indices
-    {
-      Map<String, FieldType> fieldTypes = 
dao.getColumnMetadata(Arrays.asList("bro", "snort"));
-      Assert.assertEquals(15, fieldTypes.size());
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("guid"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("source:type"));
-      Assert.assertEquals(FieldType.IP, fieldTypes.get("ip_src_addr"));
-      Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("ip_src_port"));
-      Assert.assertEquals(FieldType.LONG, fieldTypes.get("long_field"));
-      Assert.assertEquals(FieldType.DATE, fieldTypes.get("timestamp"));
-      Assert.assertEquals(FieldType.FLOAT, fieldTypes.get("latitude"));
-      Assert.assertEquals(FieldType.DOUBLE, fieldTypes.get("score"));
-      Assert.assertEquals(FieldType.BOOLEAN, fieldTypes.get("is_alert"));
-      Assert.assertEquals(FieldType.OTHER, fieldTypes.get("location_point"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("bro_field"));
-      Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("snort_field"));
-      Assert.assertEquals(FieldType.OTHER, 
fieldTypes.get("duplicate_name_field"));
-      Assert.assertEquals(FieldType.FLOAT, 
fieldTypes.get("threat:triage:score"));
-      Assert.assertEquals(FieldType.OTHER, fieldTypes.get("alert"));
+  }
+
+  @Test
+  public void results_are_paginated() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(paginationQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(10, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    Assert.assertEquals(3, results.size());
+    Assert.assertEquals("snort", 
results.get(0).getSource().get("source:type"));
+    Assert.assertEquals(6, results.get(0).getSource().get("timestamp"));
+    Assert.assertEquals("bro", results.get(1).getSource().get("source:type"));
+    Assert.assertEquals(5, results.get(1).getSource().get("timestamp"));
+    Assert.assertEquals("bro", results.get(2).getSource().get("source:type"));
+    Assert.assertEquals(4, results.get(2).getSource().get("timestamp"));
+  }
+
+  @Test
+  public void returns_results_only_for_specified_indices() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(indexQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(5, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    for (int i = 5, j = 0; i > 0; i--, j++) {
+      Assert.assertEquals("bro", 
results.get(j).getSource().get("source:type"));
+      Assert.assertEquals(i, results.get(j).getSource().get("timestamp"));
     }
+  }
+
+  @Test
+  public void facet_query_yields_field_types() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(facetQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(12, response.getTotal());
+    Map<String, Map<String, Long>> facetCounts = response.getFacetCounts();
+    Assert.assertEquals(8, facetCounts.size());
+    Map<String, Long> sourceTypeCounts = facetCounts.get("source:type");
+    Assert.assertEquals(2, sourceTypeCounts.size());
+    Assert.assertEquals(new Long(5), sourceTypeCounts.get("bro"));
+    Assert.assertEquals(new Long(5), sourceTypeCounts.get("snort"));
+    Map<String, Long> ipSrcAddrCounts = facetCounts.get("ip_src_addr");
+    Assert.assertEquals(8, ipSrcAddrCounts.size());
+    Assert.assertEquals(new Long(3), ipSrcAddrCounts.get("192.168.1.1"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.2"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.3"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.4"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.5"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.6"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.7"));
+    Assert.assertEquals(new Long(1), ipSrcAddrCounts.get("192.168.1.8"));
+    Map<String, Long> ipSrcPortCounts = facetCounts.get("ip_src_port");
+    Assert.assertEquals(10, ipSrcPortCounts.size());
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8001"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8002"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8003"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8004"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8005"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8006"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8007"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8008"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8009"));
+    Assert.assertEquals(new Long(1), ipSrcPortCounts.get("8010"));
+    Map<String, Long> longFieldCounts = facetCounts.get("long_field");
+    Assert.assertEquals(2, longFieldCounts.size());
+    Assert.assertEquals(new Long(8), longFieldCounts.get("10000"));
+    Assert.assertEquals(new Long(2), longFieldCounts.get("20000"));
+    Map<String, Long> timestampCounts = facetCounts.get("timestamp");
+    Assert.assertEquals(10, timestampCounts.size());
+    Assert.assertEquals(new Long(1), timestampCounts.get("1"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("2"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("3"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("4"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("5"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("6"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("7"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("8"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("9"));
+    Assert.assertEquals(new Long(1), timestampCounts.get("10"));
+    Map<String, Long> latitudeCounts = facetCounts.get("latitude");
+    Assert.assertEquals(2, latitudeCounts.size());
+    List<String> latitudeKeys = new ArrayList<>(latitudeCounts.keySet());
+    Collections.sort(latitudeKeys);
+    Assert.assertEquals(48.0001, Double.parseDouble(latitudeKeys.get(0)), 
0.00001);
+    Assert.assertEquals(48.5839, Double.parseDouble(latitudeKeys.get(1)), 
0.00001);
+    Assert.assertEquals(new Long(2), latitudeCounts.get(latitudeKeys.get(0)));
+    Assert.assertEquals(new Long(8), latitudeCounts.get(latitudeKeys.get(1)));
+    Map<String, Long> scoreFieldCounts = facetCounts.get("score");
+    Assert.assertEquals(4, scoreFieldCounts.size());
+    List<String> scoreFieldKeys = new ArrayList<>(scoreFieldCounts.keySet());
+    Collections.sort(scoreFieldKeys);
+    Assert.assertEquals(10.0, Double.parseDouble(scoreFieldKeys.get(0)), 
0.00001);
+    Assert.assertEquals(20.0, Double.parseDouble(scoreFieldKeys.get(1)), 
0.00001);
+    Assert.assertEquals(50.0, Double.parseDouble(scoreFieldKeys.get(2)), 
0.00001);
+    Assert.assertEquals(98.0, Double.parseDouble(scoreFieldKeys.get(3)), 
0.00001);
+    Assert.assertEquals(new Long(4), 
scoreFieldCounts.get(scoreFieldKeys.get(0)));
+    Assert.assertEquals(new Long(2), 
scoreFieldCounts.get(scoreFieldKeys.get(1)));
+    Assert.assertEquals(new Long(3), 
scoreFieldCounts.get(scoreFieldKeys.get(2)));
+    Assert.assertEquals(new Long(1), 
scoreFieldCounts.get(scoreFieldKeys.get(3)));
+    Map<String, Long> isAlertCounts = facetCounts.get("is_alert");
+    Assert.assertEquals(2, isAlertCounts.size());
+    Assert.assertEquals(new Long(6), isAlertCounts.get("true"));
+    Assert.assertEquals(new Long(4), isAlertCounts.get("false"));
+  }
+
+  @Test
+  public void bad_facet_query_throws_exception() throws Exception {
+    thrown.expect(InvalidSearchException.class);
+    thrown.expectMessage("Failed to execute search");
+    SearchRequest request = JSONUtils.INSTANCE.load(badFacetQuery, 
SearchRequest.class);
+    dao.search(request);
+  }
+
+  @Test
+  public void disabled_facet_query_returns_null_count() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(disabledFacetQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertNull(response.getFacetCounts());
+  }
+
+  @Test
+  public void exceeding_max_resulsts_throws_exception() throws Exception {
+    thrown.expect(InvalidSearchException.class);
+    thrown.expectMessage("Search result size must be less than 100");
+    SearchRequest request = JSONUtils.INSTANCE.load(exceededMaxResultsQuery, 
SearchRequest.class);
+    dao.search(request);
+  }
+
+  @Test
+  public void returns_column_data_for_multiple_indices() throws Exception {
+    Map<String, FieldType> fieldTypes = 
dao.getColumnMetadata(Arrays.asList("bro", "snort"));
+    Assert.assertEquals(15, fieldTypes.size());
+    Assert.assertEquals(FieldType.KEYWORD, fieldTypes.get("guid"));
+    Assert.assertEquals(FieldType.TEXT, fieldTypes.get("source:type"));
+    Assert.assertEquals(FieldType.IP, fieldTypes.get("ip_src_addr"));
+    Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("ip_src_port"));
+    Assert.assertEquals(FieldType.LONG, fieldTypes.get("long_field"));
+    Assert.assertEquals(FieldType.DATE, fieldTypes.get("timestamp"));
+    Assert.assertEquals(FieldType.FLOAT, fieldTypes.get("latitude"));
+    Assert.assertEquals(FieldType.DOUBLE, fieldTypes.get("score"));
+    Assert.assertEquals(FieldType.BOOLEAN, fieldTypes.get("is_alert"));
+    Assert.assertEquals(FieldType.OTHER, fieldTypes.get("location_point"));
+    Assert.assertEquals(FieldType.TEXT, fieldTypes.get("bro_field"));
+    Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("snort_field"));
+    //NOTE: This is because the field is in both bro and snort and they have 
different types.
+    Assert.assertEquals(FieldType.OTHER, 
fieldTypes.get("duplicate_name_field"));
+    Assert.assertEquals(FieldType.FLOAT, 
fieldTypes.get("threat:triage:score"));
+    Assert.assertEquals(FieldType.OTHER, fieldTypes.get("alert"));
+  }
+
+  @Test
+  public void returns_column_metadata_for_specified_indices() throws Exception 
{
     // getColumnMetadata with only bro
     {
       Map<String, FieldType> fieldTypes = 
dao.getColumnMetadata(Collections.singletonList("bro"));
       Assert.assertEquals(13, fieldTypes.size());
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("guid"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("source:type"));
+      Assert.assertEquals(FieldType.TEXT, fieldTypes.get("bro_field"));
+      Assert.assertEquals(FieldType.TEXT, 
fieldTypes.get("duplicate_name_field"));
+      Assert.assertEquals(FieldType.KEYWORD, fieldTypes.get("guid"));
+      Assert.assertEquals(FieldType.TEXT, fieldTypes.get("source:type"));
       Assert.assertEquals(FieldType.IP, fieldTypes.get("ip_src_addr"));
       Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("ip_src_port"));
       Assert.assertEquals(FieldType.LONG, fieldTypes.get("long_field"));
@@ -724,8 +889,8 @@ public abstract class SearchIntegrationTest {
       Assert.assertEquals(FieldType.DOUBLE, fieldTypes.get("score"));
       Assert.assertEquals(FieldType.BOOLEAN, fieldTypes.get("is_alert"));
       Assert.assertEquals(FieldType.OTHER, fieldTypes.get("location_point"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("bro_field"));
-      Assert.assertEquals(FieldType.STRING, 
fieldTypes.get("duplicate_name_field"));
+      Assert.assertEquals(FieldType.TEXT, fieldTypes.get("bro_field"));
+      Assert.assertEquals(FieldType.TEXT, 
fieldTypes.get("duplicate_name_field"));
       Assert.assertEquals(FieldType.OTHER, fieldTypes.get("alert"));
     }
     // getColumnMetadata with only snort
@@ -733,8 +898,9 @@ public abstract class SearchIntegrationTest {
       Map<String, FieldType> fieldTypes = 
dao.getColumnMetadata(Collections.singletonList("snort"));
       Assert.assertEquals(14, fieldTypes.size());
       Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("snort_field"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("guid"));
-      Assert.assertEquals(FieldType.STRING, fieldTypes.get("source:type"));
+      Assert.assertEquals(FieldType.INTEGER, 
fieldTypes.get("duplicate_name_field"));
+      Assert.assertEquals(FieldType.KEYWORD, fieldTypes.get("guid"));
+      Assert.assertEquals(FieldType.TEXT, fieldTypes.get("source:type"));
       Assert.assertEquals(FieldType.IP, fieldTypes.get("ip_src_addr"));
       Assert.assertEquals(FieldType.INTEGER, fieldTypes.get("ip_src_port"));
       Assert.assertEquals(FieldType.LONG, fieldTypes.get("long_field"));
@@ -751,204 +917,208 @@ public abstract class SearchIntegrationTest {
       Map<String, FieldType> fieldTypes = 
dao.getColumnMetadata(Collections.singletonList("someindex"));
       Assert.assertEquals(0, fieldTypes.size());
     }
-     //Fields query
-    {
-      SearchRequest request = JSONUtils.INSTANCE.load(fieldsQuery, 
SearchRequest.class);
-      SearchResponse response = dao.search(request);
-      Assert.assertEquals(10, response.getTotal());
-      List<SearchResult> results = response.getResults();
-      for(int i = 0;i < 5;++i) {
-        Map<String, Object> source = results.get(i).getSource();
-        Assert.assertEquals(1, source.size());
-        Assert.assertNotNull(source.get("ip_src_addr"));
-      }
-      for(int i = 5;i < 10;++i) {
-        Map<String, Object> source = results.get(i).getSource();
-        Assert.assertEquals(1, source.size());
-        Assert.assertNotNull(source.get("ip_src_addr"));
-      }
-    }
-    //Meta Alerts Fields query
-    {
-      SearchRequest request = JSONUtils.INSTANCE.load(metaAlertsFieldQuery, 
SearchRequest.class);
-      SearchResponse response = dao.search(request);
-      Assert.assertEquals(2, response.getTotal());
-      List<SearchResult> results = response.getResults();
-      for (int i = 0;i < 2;++i) {
-        Map<String, Object> source = results.get(i).getSource();
-        Assert.assertEquals(1, source.size());
-        Assert.assertEquals(source.get("guid"), "meta_" + (i + 1));
-      }
-    }
-    //No results fields query
-    {
-      SearchRequest request = JSONUtils.INSTANCE.load(noResultsFieldsQuery, 
SearchRequest.class);
-      SearchResponse response = dao.search(request);
-      Assert.assertEquals(0, response.getTotal());
-    }
+  }
+
+
+  @Test
+  public void group_by_ip_query() throws Exception {
+    GroupRequest request = JSONUtils.INSTANCE.load(groupByIpQuery, 
GroupRequest.class);
+    GroupResponse response = dao.group(request);
+
+    // expect only 1 group for 'ip_src_addr'
+    Assert.assertEquals("ip_src_addr", response.getGroupedBy());
+
+    // there are 8 different 'ip_src_addr' values
+    List<GroupResult> groups = response.getGroupResults();
+    Assert.assertEquals(8, groups.size());
+
+    // expect dotted-decimal notation in descending order
+    Assert.assertEquals("192.168.1.8", groups.get(0).getKey());
+    Assert.assertEquals("192.168.1.7", groups.get(1).getKey());
+    Assert.assertEquals("192.168.1.6", groups.get(2).getKey());
+    Assert.assertEquals("192.168.1.5", groups.get(3).getKey());
+    Assert.assertEquals("192.168.1.4", groups.get(4).getKey());
+    Assert.assertEquals("192.168.1.3", groups.get(5).getKey());
+    Assert.assertEquals("192.168.1.2", groups.get(6).getKey());
+    Assert.assertEquals("192.168.1.1", groups.get(7).getKey());
+  }
+
+  @Test
+  public void no_results_returned_when_query_does_not_match() throws Exception 
{
+    SearchRequest request = JSONUtils.INSTANCE.load(noResultsFieldsQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(0, response.getTotal());
+  }
+
+  @Test
+  public void group_by_returns_results_in_groups() throws Exception {
     // Group by test case, default order is count descending
-    {
-      GroupRequest request = JSONUtils.INSTANCE.load(groupByQuery, 
GroupRequest.class);
-      GroupResponse response = dao.group(request);
-      Assert.assertEquals("is_alert", response.getGroupedBy());
-      List<GroupResult> isAlertGroups = response.getGroupResults();
-      Assert.assertEquals(2, isAlertGroups.size());
-
-      // isAlert == true group
-      GroupResult trueGroup = isAlertGroups.get(0);
-      Assert.assertEquals("true", trueGroup.getKey());
-      Assert.assertEquals(6, trueGroup.getTotal());
-      Assert.assertEquals("latitude", trueGroup.getGroupedBy());
-      Assert.assertEquals(198.0, trueGroup.getScore(), 0.00001);
-      List<GroupResult> trueLatitudeGroups = trueGroup.getGroupResults();
-      Assert.assertEquals(2, trueLatitudeGroups.size());
-
-      // isAlert == true && latitude == 48.5839 group
-      GroupResult trueLatitudeGroup2 = trueLatitudeGroups.get(0);
-      Assert.assertEquals(48.5839, 
Double.parseDouble(trueLatitudeGroup2.getKey()), 0.00001);
-      Assert.assertEquals(5, trueLatitudeGroup2.getTotal());
-      Assert.assertEquals(148.0, trueLatitudeGroup2.getScore(), 0.00001);
-
-      // isAlert == true && latitude == 48.0001 group
-      GroupResult trueLatitudeGroup1 = trueLatitudeGroups.get(1);
-      Assert.assertEquals(48.0001, 
Double.parseDouble(trueLatitudeGroup1.getKey()), 0.00001);
-      Assert.assertEquals(1, trueLatitudeGroup1.getTotal());
-      Assert.assertEquals(50.0, trueLatitudeGroup1.getScore(), 0.00001);
-
-      // isAlert == false group
-      GroupResult falseGroup = isAlertGroups.get(1);
-      Assert.assertEquals("false", falseGroup.getKey());
-      Assert.assertEquals("latitude", falseGroup.getGroupedBy());
-      Assert.assertEquals(130.0, falseGroup.getScore(), 0.00001);
-      List<GroupResult> falseLatitudeGroups = falseGroup.getGroupResults();
-      Assert.assertEquals(2, falseLatitudeGroups.size());
-
-      // isAlert == false && latitude == 48.5839 group
-      GroupResult falseLatitudeGroup2 = falseLatitudeGroups.get(0);
-      Assert.assertEquals(48.5839, 
Double.parseDouble(falseLatitudeGroup2.getKey()), 0.00001);
-      Assert.assertEquals(3, falseLatitudeGroup2.getTotal());
-      Assert.assertEquals(80.0, falseLatitudeGroup2.getScore(), 0.00001);
-
-      // isAlert == false && latitude == 48.0001 group
-      GroupResult falseLatitudeGroup1 = falseLatitudeGroups.get(1);
-      Assert.assertEquals(48.0001, 
Double.parseDouble(falseLatitudeGroup1.getKey()), 0.00001);
-      Assert.assertEquals(1, falseLatitudeGroup1.getTotal());
-      Assert.assertEquals(50.0, falseLatitudeGroup1.getScore(), 0.00001);
-    }
+    GroupRequest request = JSONUtils.INSTANCE.load(groupByQuery, 
GroupRequest.class);
+    GroupResponse response = dao.group(request);
+    Assert.assertEquals("is_alert", response.getGroupedBy());
+    List<GroupResult> isAlertGroups = response.getGroupResults();
+    Assert.assertEquals(2, isAlertGroups.size());
+
+    // isAlert == true group
+    GroupResult trueGroup = isAlertGroups.get(0);
+    Assert.assertEquals("true", trueGroup.getKey());
+    Assert.assertEquals(6, trueGroup.getTotal());
+    Assert.assertEquals("latitude", trueGroup.getGroupedBy());
+    Assert.assertEquals(198.0, trueGroup.getScore(), 0.00001);
+    List<GroupResult> trueLatitudeGroups = trueGroup.getGroupResults();
+    Assert.assertEquals(2, trueLatitudeGroups.size());
+
+
+    // isAlert == true && latitude == 48.5839 group
+    GroupResult trueLatitudeGroup2 = trueLatitudeGroups.get(0);
+    Assert.assertEquals(48.5839, 
Double.parseDouble(trueLatitudeGroup2.getKey()), 0.00001);
+    Assert.assertEquals(5, trueLatitudeGroup2.getTotal());
+    Assert.assertEquals(148.0, trueLatitudeGroup2.getScore(), 0.00001);
+
+    // isAlert == true && latitude == 48.0001 group
+    GroupResult trueLatitudeGroup1 = trueLatitudeGroups.get(1);
+    Assert.assertEquals(48.0001, 
Double.parseDouble(trueLatitudeGroup1.getKey()), 0.00001);
+    Assert.assertEquals(1, trueLatitudeGroup1.getTotal());
+    Assert.assertEquals(50.0, trueLatitudeGroup1.getScore(), 0.00001);
+
+    // isAlert == false group
+    GroupResult falseGroup = isAlertGroups.get(1);
+    Assert.assertEquals("false", falseGroup.getKey());
+    Assert.assertEquals("latitude", falseGroup.getGroupedBy());
+    Assert.assertEquals(130.0, falseGroup.getScore(), 0.00001);
+    List<GroupResult> falseLatitudeGroups = falseGroup.getGroupResults();
+    Assert.assertEquals(2, falseLatitudeGroups.size());
+
+    // isAlert == false && latitude == 48.5839 group
+    GroupResult falseLatitudeGroup2 = falseLatitudeGroups.get(0);
+    Assert.assertEquals(48.5839, 
Double.parseDouble(falseLatitudeGroup2.getKey()), 0.00001);
+    Assert.assertEquals(3, falseLatitudeGroup2.getTotal());
+    Assert.assertEquals(80.0, falseLatitudeGroup2.getScore(), 0.00001);
+
+    // isAlert == false && latitude == 48.0001 group
+    GroupResult falseLatitudeGroup1 = falseLatitudeGroups.get(1);
+    Assert.assertEquals(48.0001, 
Double.parseDouble(falseLatitudeGroup1.getKey()), 0.00001);
+    Assert.assertEquals(1, falseLatitudeGroup1.getTotal());
+    Assert.assertEquals(50.0, falseLatitudeGroup1.getScore(), 0.00001);
+  }
+
+  @Test
+  public void group_by_returns_results_in_sorted_groups() throws Exception {
     // Group by with sorting test case where is_alert is sorted by count 
ascending and ip_src_addr is sorted by term descending
-    {
-      GroupRequest request = JSONUtils.INSTANCE.load(sortedGroupByQuery, 
GroupRequest.class);
-      GroupResponse response = dao.group(request);
-      Assert.assertEquals("is_alert", response.getGroupedBy());
-      List<GroupResult> isAlertGroups = response.getGroupResults();
-      Assert.assertEquals(2, isAlertGroups.size());
-
-      // isAlert == false group
-      GroupResult falseGroup = isAlertGroups.get(0);
-      Assert.assertEquals(4, falseGroup.getTotal());
-      Assert.assertEquals("ip_src_addr", falseGroup.getGroupedBy());
-      List<GroupResult> falseIpSrcAddrGroups = falseGroup.getGroupResults();
-      Assert.assertEquals(4, falseIpSrcAddrGroups.size());
-
-      // isAlert == false && ip_src_addr == 192.168.1.8 group
-      GroupResult falseIpSrcAddrGroup1 = falseIpSrcAddrGroups.get(0);
-      Assert.assertEquals("192.168.1.8", falseIpSrcAddrGroup1.getKey());
-      Assert.assertEquals(1, falseIpSrcAddrGroup1.getTotal());
-      Assert.assertNull(falseIpSrcAddrGroup1.getGroupedBy());
-      Assert.assertNull(falseIpSrcAddrGroup1.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.7 group
-      GroupResult falseIpSrcAddrGroup2 = falseIpSrcAddrGroups.get(1);
-      Assert.assertEquals("192.168.1.7", falseIpSrcAddrGroup2.getKey());
-      Assert.assertEquals(1, falseIpSrcAddrGroup2.getTotal());
-      Assert.assertNull(falseIpSrcAddrGroup2.getGroupedBy());
-      Assert.assertNull(falseIpSrcAddrGroup2.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.6 group
-      GroupResult falseIpSrcAddrGroup3 = falseIpSrcAddrGroups.get(2);
-      Assert.assertEquals("192.168.1.6", falseIpSrcAddrGroup3.getKey());
-      Assert.assertEquals(1, falseIpSrcAddrGroup3.getTotal());
-      Assert.assertNull(falseIpSrcAddrGroup3.getGroupedBy());
-      Assert.assertNull(falseIpSrcAddrGroup3.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.2 group
-      GroupResult falseIpSrcAddrGroup4 = falseIpSrcAddrGroups.get(3);
-      Assert.assertEquals("192.168.1.2", falseIpSrcAddrGroup4.getKey());
-      Assert.assertEquals(1, falseIpSrcAddrGroup4.getTotal());
-      Assert.assertNull(falseIpSrcAddrGroup4.getGroupedBy());
-      Assert.assertNull(falseIpSrcAddrGroup4.getGroupResults());
-
-      // isAlert == false group
-      GroupResult trueGroup = isAlertGroups.get(1);
-      Assert.assertEquals(6, trueGroup.getTotal());
-      Assert.assertEquals("ip_src_addr", trueGroup.getGroupedBy());
-      List<GroupResult> trueIpSrcAddrGroups = trueGroup.getGroupResults();
-      Assert.assertEquals(4, trueIpSrcAddrGroups.size());
-
-      // isAlert == false && ip_src_addr == 192.168.1.5 group
-      GroupResult trueIpSrcAddrGroup1 = trueIpSrcAddrGroups.get(0);
-      Assert.assertEquals("192.168.1.5", trueIpSrcAddrGroup1.getKey());
-      Assert.assertEquals(1, trueIpSrcAddrGroup1.getTotal());
-      Assert.assertNull(trueIpSrcAddrGroup1.getGroupedBy());
-      Assert.assertNull(trueIpSrcAddrGroup1.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.4 group
-      GroupResult trueIpSrcAddrGroup2 = trueIpSrcAddrGroups.get(1);
-      Assert.assertEquals("192.168.1.4", trueIpSrcAddrGroup2.getKey());
-      Assert.assertEquals(1, trueIpSrcAddrGroup2.getTotal());
-      Assert.assertNull(trueIpSrcAddrGroup2.getGroupedBy());
-      Assert.assertNull(trueIpSrcAddrGroup2.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.3 group
-      GroupResult trueIpSrcAddrGroup3 = trueIpSrcAddrGroups.get(2);
-      Assert.assertEquals("192.168.1.3", trueIpSrcAddrGroup3.getKey());
-      Assert.assertEquals(1, trueIpSrcAddrGroup3.getTotal());
-      Assert.assertNull(trueIpSrcAddrGroup3.getGroupedBy());
-      Assert.assertNull(trueIpSrcAddrGroup3.getGroupResults());
-
-      // isAlert == false && ip_src_addr == 192.168.1.1 group
-      GroupResult trueIpSrcAddrGroup4 = trueIpSrcAddrGroups.get(3);
-      Assert.assertEquals("192.168.1.1", trueIpSrcAddrGroup4.getKey());
-      Assert.assertEquals(3, trueIpSrcAddrGroup4.getTotal());
-      Assert.assertNull(trueIpSrcAddrGroup4.getGroupedBy());
-      Assert.assertNull(trueIpSrcAddrGroup4.getGroupResults());
+    GroupRequest request = JSONUtils.INSTANCE.load(sortedGroupByQuery, 
GroupRequest.class);
+    GroupResponse response = dao.group(request);
+    Assert.assertEquals("is_alert", response.getGroupedBy());
+    List<GroupResult> isAlertGroups = response.getGroupResults();
+    Assert.assertEquals(2, isAlertGroups.size());
+
+    // isAlert == false group
+    GroupResult falseGroup = isAlertGroups.get(0);
+    Assert.assertEquals(4, falseGroup.getTotal());
+    Assert.assertEquals("ip_src_addr", falseGroup.getGroupedBy());
+    List<GroupResult> falseIpSrcAddrGroups = falseGroup.getGroupResults();
+    Assert.assertEquals(4, falseIpSrcAddrGroups.size());
+
+    // isAlert == false && ip_src_addr == 192.168.1.8 group
+    GroupResult falseIpSrcAddrGroup1 = falseIpSrcAddrGroups.get(0);
+    Assert.assertEquals("192.168.1.8", falseIpSrcAddrGroup1.getKey());
+    Assert.assertEquals(1, falseIpSrcAddrGroup1.getTotal());
+    Assert.assertNull(falseIpSrcAddrGroup1.getGroupedBy());
+    Assert.assertNull(falseIpSrcAddrGroup1.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.7 group
+    GroupResult falseIpSrcAddrGroup2 = falseIpSrcAddrGroups.get(1);
+    Assert.assertEquals("192.168.1.7", falseIpSrcAddrGroup2.getKey());
+    Assert.assertEquals(1, falseIpSrcAddrGroup2.getTotal());
+    Assert.assertNull(falseIpSrcAddrGroup2.getGroupedBy());
+    Assert.assertNull(falseIpSrcAddrGroup2.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.6 group
+    GroupResult falseIpSrcAddrGroup3 = falseIpSrcAddrGroups.get(2);
+    Assert.assertEquals("192.168.1.6", falseIpSrcAddrGroup3.getKey());
+    Assert.assertEquals(1, falseIpSrcAddrGroup3.getTotal());
+    Assert.assertNull(falseIpSrcAddrGroup3.getGroupedBy());
+    Assert.assertNull(falseIpSrcAddrGroup3.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.2 group
+    GroupResult falseIpSrcAddrGroup4 = falseIpSrcAddrGroups.get(3);
+    Assert.assertEquals("192.168.1.2", falseIpSrcAddrGroup4.getKey());
+    Assert.assertEquals(1, falseIpSrcAddrGroup4.getTotal());
+    Assert.assertNull(falseIpSrcAddrGroup4.getGroupedBy());
+    Assert.assertNull(falseIpSrcAddrGroup4.getGroupResults());
+
+    // isAlert == false group
+    GroupResult trueGroup = isAlertGroups.get(1);
+    Assert.assertEquals(6, trueGroup.getTotal());
+    Assert.assertEquals("ip_src_addr", trueGroup.getGroupedBy());
+    List<GroupResult> trueIpSrcAddrGroups = trueGroup.getGroupResults();
+    Assert.assertEquals(4, trueIpSrcAddrGroups.size());
+
+    // isAlert == false && ip_src_addr == 192.168.1.5 group
+    GroupResult trueIpSrcAddrGroup1 = trueIpSrcAddrGroups.get(0);
+    Assert.assertEquals("192.168.1.5", trueIpSrcAddrGroup1.getKey());
+    Assert.assertEquals(1, trueIpSrcAddrGroup1.getTotal());
+    Assert.assertNull(trueIpSrcAddrGroup1.getGroupedBy());
+    Assert.assertNull(trueIpSrcAddrGroup1.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.4 group
+    GroupResult trueIpSrcAddrGroup2 = trueIpSrcAddrGroups.get(1);
+    Assert.assertEquals("192.168.1.4", trueIpSrcAddrGroup2.getKey());
+    Assert.assertEquals(1, trueIpSrcAddrGroup2.getTotal());
+    Assert.assertNull(trueIpSrcAddrGroup2.getGroupedBy());
+    Assert.assertNull(trueIpSrcAddrGroup2.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.3 group
+    GroupResult trueIpSrcAddrGroup3 = trueIpSrcAddrGroups.get(2);
+    Assert.assertEquals("192.168.1.3", trueIpSrcAddrGroup3.getKey());
+    Assert.assertEquals(1, trueIpSrcAddrGroup3.getTotal());
+    Assert.assertNull(trueIpSrcAddrGroup3.getGroupedBy());
+    Assert.assertNull(trueIpSrcAddrGroup3.getGroupResults());
+
+    // isAlert == false && ip_src_addr == 192.168.1.1 group
+    GroupResult trueIpSrcAddrGroup4 = trueIpSrcAddrGroups.get(3);
+    Assert.assertEquals("192.168.1.1", trueIpSrcAddrGroup4.getKey());
+    Assert.assertEquals(3, trueIpSrcAddrGroup4.getTotal());
+    Assert.assertNull(trueIpSrcAddrGroup4.getGroupedBy());
+    Assert.assertNull(trueIpSrcAddrGroup4.getGroupResults());
+  }
+
+  @Test
+  public void 
throws_exception_on_aggregation_queries_on_non_string_non_numeric_fields()
+          throws Exception {
+    thrown.expect(InvalidSearchException.class);
+    thrown.expectMessage("Failed to execute search");
+    GroupRequest request = JSONUtils.INSTANCE.load(badGroupQuery, 
GroupRequest.class);
+    dao.group(request);
+  }
+
+  @Test
+  public void queries_fields() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(fieldsQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(10, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    for (int i = 0; i < 5; ++i) {
+      Map<String, Object> source = results.get(i).getSource();
+      Assert.assertEquals(1, source.size());
+      Assert.assertNotNull(source.get("ip_src_addr"));
     }
-    //Bad group query
-    {
-      GroupRequest request = JSONUtils.INSTANCE.load(badGroupQuery, 
GroupRequest.class);
-      try {
-        dao.group(request);
-        Assert.fail("Exception expected, but did not come.");
-      }
-      catch(InvalidSearchException ise) {
-        // success
-      }
+    for (int i = 5; i < 10; ++i) {
+      Map<String, Object> source = results.get(i).getSource();
+      Assert.assertEquals(1, source.size());
+      Assert.assertNotNull(source.get("ip_src_addr"));
     }
-    //Group by IP query
-    {
-      {
-        GroupRequest request = JSONUtils.INSTANCE.load(groupByIpQuery, 
GroupRequest.class);
-        GroupResponse response = dao.group(request);
-
-        // expect only 1 group for 'ip_src_addr'
-        Assert.assertEquals("ip_src_addr", response.getGroupedBy());
-
-        // there are 8 different 'ip_src_addr' values
-        List<GroupResult> groups = response.getGroupResults();
-        Assert.assertEquals(8, groups.size());
-
-        // expect dotted-decimal notation in descending order
-        Assert.assertEquals("192.168.1.8", groups.get(0).getKey());
-        Assert.assertEquals("192.168.1.7", groups.get(1).getKey());
-        Assert.assertEquals("192.168.1.6", groups.get(2).getKey());
-        Assert.assertEquals("192.168.1.5", groups.get(3).getKey());
-        Assert.assertEquals("192.168.1.4", groups.get(4).getKey());
-        Assert.assertEquals("192.168.1.3", groups.get(5).getKey());
-        Assert.assertEquals("192.168.1.2", groups.get(6).getKey());
-        Assert.assertEquals("192.168.1.1", groups.get(7).getKey());
-      }
-
+  }
 
+  @Test
+  public void searches_metaalerts_fields() throws Exception {
+    SearchRequest request = JSONUtils.INSTANCE.load(metaAlertsFieldQuery, 
SearchRequest.class);
+    SearchResponse response = dao.search(request);
+    Assert.assertEquals(2, response.getTotal());
+    List<SearchResult> results = response.getResults();
+    for (int i = 0; i < 2; ++i) {
+      Map<String, Object> source = results.get(i).getSource();
+      Assert.assertEquals(1, source.size());
+      Assert.assertEquals(source.get("guid"), "meta_" + (i + 1));
     }
   }
 
@@ -960,4 +1130,4 @@ public abstract class SearchIntegrationTest {
   protected abstract IndexDao createDao() throws Exception;
   protected abstract InMemoryComponent startIndex() throws Exception;
   protected abstract void loadTestData() throws Exception;
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/integration/IndexingIntegrationTest.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/integration/IndexingIntegrationTest.java
 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/integration/IndexingIntegrationTest.java
index c0f9919..ac6f90a 100644
--- 
a/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/integration/IndexingIntegrationTest.java
+++ 
b/metron-platform/metron-indexing/src/test/java/org/apache/metron/indexing/integration/IndexingIntegrationTest.java
@@ -56,8 +56,8 @@ public abstract class IndexingIntegrationTest extends 
BaseIntegrationTest {
   protected String sampleParsedPath = TestConstants.SAMPLE_DATA_PARSED_PATH + 
"TestExampleParsed";
   protected String fluxPath = 
"../metron-indexing/src/main/flux/indexing/remote.yaml";
   protected String testSensorType = "test";
-
-
+  protected final int NUM_RETRIES = 100;
+  protected final long TOTAL_TIME_MS = 150000L;
   public static List<Map<String, Object>> readDocsFromDisk(String hdfsDirStr) 
throws IOException {
     List<Map<String, Object>> ret = new ArrayList<>();
     File hdfsDir = new File(hdfsDirStr);
@@ -180,8 +180,8 @@ public abstract class IndexingIntegrationTest extends 
BaseIntegrationTest {
             .withComponent("storm", fluxComponent)
             .withComponent("search", getSearchComponent(topologyProperties))
             .withMillisecondsBetweenAttempts(1500)
-            .withNumRetries(100)
-            .withMaxTimeMS(150000)
+            .withNumRetries(NUM_RETRIES)
+            .withMaxTimeMS(TOTAL_TIME_MS)
             .withCustomShutdownOrder(new String[] 
{"search","storm","config","kafka","zk"})
             .build();
 
@@ -198,8 +198,6 @@ public abstract class IndexingIntegrationTest extends 
BaseIntegrationTest {
       // on the field name converter
       assertInputDocsMatchOutputs(inputDocs, docs, getFieldNameConverter());
       assertInputDocsMatchOutputs(inputDocs, readDocsFromDisk(hdfsDir), x -> 
x);
-    } catch(Throwable e) {
-      e.printStackTrace();
     }
     finally {
       if(runner != null) {

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-integration-test/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-integration-test/pom.xml 
b/metron-platform/metron-integration-test/pom.xml
index 72a785c..cc72849 100644
--- a/metron-platform/metron-integration-test/pom.xml
+++ b/metron-platform/metron-integration-test/pom.xml
@@ -53,6 +53,14 @@
           <artifactId>log4j-slf4j-impl</artifactId>
           <groupId>org.apache.logging.log4j</groupId>
         </exclusion>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-api</artifactId>
+        </exclusion>
       </exclusions>
     </dependency>
     <dependency>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-integration-test/src/main/java/org/apache/metron/integration/utils/TestUtils.java
----------------------------------------------------------------------
diff --git 
a/metron-platform/metron-integration-test/src/main/java/org/apache/metron/integration/utils/TestUtils.java
 
b/metron-platform/metron-integration-test/src/main/java/org/apache/metron/integration/utils/TestUtils.java
index 9577a43..0c37a35 100644
--- 
a/metron-platform/metron-integration-test/src/main/java/org/apache/metron/integration/utils/TestUtils.java
+++ 
b/metron-platform/metron-integration-test/src/main/java/org/apache/metron/integration/utils/TestUtils.java
@@ -21,10 +21,12 @@ import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
@@ -32,6 +34,7 @@ import java.util.List;
 
 public class TestUtils {
   public static long MAX_ASSERT_WAIT_MS = 30000L;
+
   public interface Assertion {
     void apply() throws Exception;
   }
@@ -88,6 +91,30 @@ public class TestUtils {
   }
 
   /**
+   * Reads file contents into a String. Uses UTF-8 as default charset.
+   *
+   * @param in Input file
+   * @return contents of input file
+   * @throws IOException
+   */
+  public static String read(File in) throws IOException {
+    return read(in, StandardCharsets.UTF_8);
+  }
+
+  /**
+   * Reads file contents into a String
+   *
+   * @param in Input file
+   * @param charset charset to use for reading
+   * @return contents of input file
+   * @throws IOException
+   */
+  public static String read(File in, Charset charset) throws IOException {
+    byte[] bytes = Files.readAllBytes(Paths.get(in.getPath()));
+    return new String(bytes, charset);
+  }
+
+  /**
    * Cleans up after test run via runtime shutdown hooks
    */
   public static File createTempDir(String prefix) throws IOException {

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-parsers/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-parsers/pom.xml 
b/metron-platform/metron-parsers/pom.xml
index c27ad62..18377d3 100644
--- a/metron-platform/metron-parsers/pom.xml
+++ b/metron-platform/metron-parsers/pom.xml
@@ -130,6 +130,14 @@
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>
@@ -144,6 +152,18 @@
             </exclusions>
         </dependency>
         <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <version>${global_junit_version}</version>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-pcap-backend/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-pcap-backend/pom.xml 
b/metron-platform/metron-pcap-backend/pom.xml
index bcd7e7c..6db7d29 100644
--- a/metron-platform/metron-pcap-backend/pom.xml
+++ b/metron-platform/metron-pcap-backend/pom.xml
@@ -174,6 +174,14 @@
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>
@@ -188,6 +196,18 @@
             </exclusions>
         </dependency>
         <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.metron</groupId>
             <artifactId>metron-pcap</artifactId>
             <version>${project.parent.version}</version>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-pcap/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-pcap/pom.xml 
b/metron-platform/metron-pcap/pom.xml
index 3a83174..574e99b 100644
--- a/metron-platform/metron-pcap/pom.xml
+++ b/metron-platform/metron-pcap/pom.xml
@@ -92,6 +92,14 @@
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>

http://git-wip-us.apache.org/repos/asf/metron/blob/e8213918/metron-platform/metron-solr/pom.xml
----------------------------------------------------------------------
diff --git a/metron-platform/metron-solr/pom.xml 
b/metron-platform/metron-solr/pom.xml
index 6da67b8..a2eee71 100644
--- a/metron-platform/metron-solr/pom.xml
+++ b/metron-platform/metron-solr/pom.xml
@@ -66,12 +66,32 @@
             </exclusions>
         </dependency>
         <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>${global_log4j_core_version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.storm</groupId>
             <artifactId>storm-core</artifactId>
             <version>${global_storm_version}</version>
             <scope>provided</scope>
             <exclusions>
                 <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+                <exclusion>
                     <artifactId>servlet-api</artifactId>
                     <groupId>javax.servlet</groupId>
                 </exclusion>

Reply via email to