/* * Copyright 2014, Tuplejump Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.tuplejump.stargate.cassandra; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.Row; import com.tuplejump.stargate.util.CQLUnitD; import junit.framework.Assert; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Test; /** * User: satya */ public class AggregatesTest extends IndexTestBase { String keyspace = "dummyksAggr"; public AggregatesTest() throws Exception { cassandraCQLUnit = CQLUnitD.getCQLUnit(null); } @Test public void shouldCalculateAggregates() throws Exception { //hack to always create new Index during testing try { createKS(keyspace); createTableAndIndexForRow(); countResults("TAG2", "", false, true); //Assert.assertEquals(12000, countResults("TAG2", "magic = '" + q("tags", "tags:hello* AND state:CA") + "'", true)); countResults("TAG2", "magic = '" + funWithFilter(fun("state", "state-values", "values", true), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("segment", "segment-values", "values", true), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("segment", "distinct-segment", "count", true), "tags", "tags:hello* AND state:CA") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "sum-value", "sum", false), "tags", "tags:hello* AND state:CA") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "min-value", "min", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "max-value", "max", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("state", "distinct-state", "count", true, "segment"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "values", "values", true, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "sum-value", "sum", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "min-value", "min", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "max-value", "max", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + "{" + fun(null, "count-star", "count", false) + "}" + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun(null, "count-star", "count", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "sum-value", "sum", false, "key"), "tags", "tags:hello*") + "'", true); } finally { dropTable(keyspace, "TAG2"); dropKS(keyspace); } } private void createTableAndIndexForRow() { String options = "{\n" + "\t\"numShards\":1024,\n" + "\t\"metaColumn\":true,\n" + "\t\"fields\":{\n" + "\t\t\"key\":{},\n" + "\t\t\"tags\":{\"type\":\"text\"},\n" + "\t\t\"state\":{}\n" + "\t}\n" + "}\n"; getSession().execute("USE " + keyspace + ";"); getSession().execute("CREATE TABLE TAG2(key int, tags varchar, state varchar, segment int, value int, magic text, PRIMARY KEY(key))"); int i = 0; while (i < 40) { if (i == 20) { getSession().execute("CREATE CUSTOM INDEX tagsandstate ON TAG2(magic) USING 'com.tuplejump.stargate.RowIndex' WITH options ={'sg_options':'" + options + "'}"); } getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 1) + ",'hello1 tag1 lol1', 'CA'," + i + "," + (i * 1) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 2) + ",'hello1 tag1 lol2', 'LA'," + i + "," + (i * 2) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 3) + ",'hello1 tag2 lol1', 'NY'," + i + "," + (i * 3) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 4) + ",'hello1 tag2 lol2', 'TX'," + i + "," + (i * 4) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 5) + ",'hllo3 tag3 lol3', 'TX'," + i + "," + (i * 5) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 6) + ",'hello2 tag1 lol1', 'CA'," + i + "," + (i * 6) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 7) + ",'hello2 tag1 lol2', 'NY'," + i + "," + (i * 7) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 8) + ",'hello2 tag2 lol1', 'CA'," + i + "," + (i * 8) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 9) + ",'hello2 tag2 lol2', 'TX'," + i + "," + (i * 9) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 10) + ",'hllo3 tag3 lol3', 'TX'," + i + "," + (i * 10) + ")"); i = i + 10; } } // @Test public void shouldCalculateAggregatesOnStriped() throws Exception { //hack to always create new Index during testing try { createKS(keyspace); createTableAndIndexForRowStriped(); countResults("TAG2", "", false, true); countResults("TAG2", "magic = '" + funWithFilter(gFun("state", "distinct-state", "count", true, "segment"), "tags", "tags:hello*") + "'", true); //Assert.assertEquals(12000, countResults("TAG2", "magic = '" + q("tags", "tags:hello* AND state:CA") + "'", true)); countResults("TAG2", "magic = '" + funWithFilter(fun("state", "state-values", "values", true), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "sum-value", "sum", false), "tags", "tags:hello* AND state:CA") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "min-value", "min", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun("value", "max-value", "max", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("state", "distinct-state", "count", true, "segment"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "values", "values", true, "return StringUtils.lowerCase(state);"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "sum-value", "sum", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gQuantile("value", "quantile-value", false, "state", 10), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "quantile-value", "quantile", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "min-value", "min", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "max-value", "max", false, "state"), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + "{" + fun(null, "count-star", "count", false) + "}" + "'", true); countResults("TAG2", "magic = '" + funWithFilter(fun(null, "count-star", "count", false), "tags", "tags:hello*") + "'", true); countResults("TAG2", "magic = '" + funWithFilter(gFun("value", "sum-value", "sum", false, "key"), "tags", "tags:hello*") + "'", true); } finally { dropTable(keyspace, "TAG2"); dropKS(keyspace); } } // @Test public void shouldCalculateQuantileAggregate() throws Exception { try { createEventStoreSchema(keyspace); String quantileQuery = "SELECT stargate FROM " + keyspace + ".event_store WHERE stargate = '{ function:{ type:\"aggregate\", aggregates:[{type:\"quantile\",field:\"measures.connection\"}], groupBy:[\"dimensions._browser\"] }}' ;"; ResultSet rows = getSession().execute(quantileQuery); printResultSet(true, rows); String quantileQuery2 = "SELECT stargate FROM " + keyspace + ".event_store WHERE stargate = '{ function:{ type:\"aggregate\", aggregates:[{type:\"sum\",field:\"measures.connection\"}]}}' ;"; ResultSet rows2 = getSession().execute(quantileQuery2); printResultSet(true, rows2); } finally { dropKS(keyspace); } } // @Test public void shouldReturnJSONString() throws Exception { try { createEventStoreSchema(keyspace); ObjectMapper jsonMapper = new ObjectMapper(); String quantileQuery = "SELECT stargate FROM " + keyspace + ".event_store WHERE stargate = '{ function:{ type:\"aggregate\", aggregates:[{type:\"sum\",field:\"measures.connection\"}] }}' ;"; Row row = getSession().execute(quantileQuery).one(); String data = row.getString("stargate"); String expectedResult = "{\"groups\":[{\"group\":{},\"aggregations\":[{\"sum\":695.0}]}]}"; JsonNode result = jsonMapper.readTree(data); JsonNode expected = jsonMapper.readTree(expectedResult); Assert.assertEquals(expected, result); } finally { dropKS(keyspace); } } // @Test public void shouldReturnSumZeroIfNoEntriesFound() throws Exception { try { createEventStoreSchema(keyspace); ObjectMapper jsonMapper = new ObjectMapper(); String quantileQuery = "SELECT stargate FROM " + keyspace + ".event_store WHERE stargate = '{ function:{ type:\"aggregate\", aggregates:[{type:\"sum\",field:\"measures.error\"}] }}' ;"; Row row = getSession().execute(quantileQuery).one(); String data = row.getString("stargate"); String expectedResult = "{\"groups\":[{\"group\":{},\"aggregations\":[{\"sum\":0.0}]}]}"; JsonNode result = jsonMapper.readTree(data); JsonNode expected = jsonMapper.readTree(expectedResult); Assert.assertEquals(expected, result); } finally { dropKS(keyspace); } } private void createTableAndIndexForRowStriped() { String options = "{\n" + "\t\"numShards\":1024,\n" + "\t\"metaColumn\":true,\n" + "\t\"fields\":{\n" + "\t\t\"key\":{ striped: \"also\"},\n" + "\t\t\"tags\":{\"type\":\"text\"},\n" + "\t\t\"state\":{ striped: \"also\"},\n" + "\t\t\"value\":{ striped: \"only\"}\n" + "\t}\n" + "}\n"; getSession().execute("USE " + keyspace + ";"); getSession().execute("CREATE TABLE TAG2(key int, tags varchar, state varchar, segment int, value int, magic text, PRIMARY KEY(key))"); int i = 0; while (i < 40) { if (i == 20) { getSession().execute("CREATE CUSTOM INDEX tagsandstate ON TAG2(magic) USING 'com.tuplejump.stargate.RowIndex' WITH options ={'sg_options':'" + options + "'}"); } getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 1) + ",'hello1 tag1 lol1', 'CA'," + i + "," + (i * 1) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 2) + ",'hello1 tag1 lol2', 'LA'," + i + "," + (i * 2) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 3) + ",'hello1 tag2 lol1', 'NY'," + i + "," + (i * 3) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 4) + ",'hello1 tag2 lol2', 'TX'," + i + "," + (i * 4) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 5) + ",'hllo3 tag3 lol3', 'TX'," + i + "," + (i * 5) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 6) + ",'hello2 tag1 lol1', 'CA'," + i + "," + (i * 6) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 7) + ",'hello2 tag1 lol2', 'NY'," + i + "," + (i * 7) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 8) + ",'hello2 tag2 lol1', 'CA'," + i + "," + (i * 8) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 9) + ",'hello2 tag2 lol2', 'TX'," + i + "," + (i * 9) + ")"); getSession().execute("insert into " + keyspace + ".TAG2 (key,tags,state,segment,value) values (" + (i + 10) + ",'hllo3 tag3 lol3', 'TX'," + i + "," + (i * 10) + ")"); i = i + 10; } } }