Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions api/src/main/java/io/druid/data/input/MapBasedRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Function;
import com.google.common.collect.Lists;

import io.druid.java.util.common.logger.Logger;
import io.druid.java.util.common.parsers.ParseException;

import org.joda.time.DateTime;

import java.util.Collections;
Expand All @@ -38,14 +35,7 @@
*/
public class MapBasedRow implements Row
{
private static final Logger log = new Logger(MapBasedRow.class);
private static final Function<Object, String> TO_STRING_INCLUDING_NULL = new Function<Object, String>() {
@Override
public String apply(final Object o)
{
return String.valueOf(o);
}
};
private static final Function<Object, String> TO_STRING_INCLUDING_NULL = String::valueOf;

private final DateTime timestamp;
private final Map<String, Object> event;
Expand Down Expand Up @@ -159,6 +149,29 @@ public long getLongMetric(String metric)
}
}

@Override
public double getDoubleMetric(String metric)
{
Object metricValue = event.get(metric);

if (metricValue == null) {
return 0.0d;
}

if (metricValue instanceof Number) {
return ((Number) metricValue).doubleValue();
} else if (metricValue instanceof String) {
try {
return Double.valueOf(((String) metricValue).replace(",", ""));
}
catch (Exception e) {
throw new ParseException(e, "Unable to parse metrics[%s], value[%s]", metric, metricValue);
}
} else {
throw new ParseException("Unknown type[%s]", metricValue.getClass());
}
}

@Override
public String toString()
{
Expand Down
10 changes: 10 additions & 0 deletions api/src/main/java/io/druid/data/input/Row.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,14 @@ public interface Row extends Comparable<Row>
* @return the long value for the provided column name.
*/
public long getLongMetric(String metric);

/**
* Returns the double value of the given metric column.
* <p/>
*
* @param metric the column name of the metric requested
*
* @return the double value for the provided column name.
*/
public double getDoubleMetric(String metric);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
@JsonSubTypes.Type(name = DimensionSchema.STRING_TYPE_NAME, value = StringDimensionSchema.class),
@JsonSubTypes.Type(name = DimensionSchema.LONG_TYPE_NAME, value = LongDimensionSchema.class),
@JsonSubTypes.Type(name = DimensionSchema.FLOAT_TYPE_NAME, value = FloatDimensionSchema.class),
@JsonSubTypes.Type(name = DimensionSchema.DOUBLE_TYPE_NAME, value = DoubleDimensionSchema.class),
@JsonSubTypes.Type(name = DimensionSchema.SPATIAL_TYPE_NAME, value = NewSpatialDimensionSchema.class),
})
public abstract class DimensionSchema
Expand All @@ -43,6 +44,7 @@ public abstract class DimensionSchema
public static final String LONG_TYPE_NAME = "long";
public static final String FLOAT_TYPE_NAME = "float";
public static final String SPATIAL_TYPE_NAME = "spatial";
public static final String DOUBLE_TYPE_NAME = "double";


// main druid and druid-api should really use the same ValueType enum.
Expand All @@ -52,6 +54,7 @@ public enum ValueType
FLOAT,
LONG,
STRING,
DOUBLE,
COMPLEX;

@JsonValue
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you 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 io.druid.data.input.impl;


import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class DoubleDimensionSchema extends DimensionSchema
{
@JsonCreator
public DoubleDimensionSchema(@JsonProperty("name") String name)
{
super(name, null);
}

@Override
public String getTypeName()
{
return DimensionSchema.DOUBLE_TYPE_NAME;
}

@Override
public ValueType getValueType()
{
return ValueType.DOUBLE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.druid.collections.bitmap.RoaringBitmapFactory;
import io.druid.collections.spatial.ImmutableRTree;
import io.druid.query.filter.BitmapIndexSelector;
import io.druid.query.filter.DruidDoublePredicate;
import io.druid.query.filter.DruidFloatPredicate;
import io.druid.query.filter.DruidLongPredicate;
import io.druid.query.filter.DruidPredicateFactory;
Expand Down Expand Up @@ -95,6 +96,12 @@ public DruidFloatPredicate makeFloatPredicate()
{
return DruidFloatPredicate.ALWAYS_FALSE;
}

@Override
public DruidDoublePredicate makeDoublePredicate()
{
return DruidDoublePredicate.ALWAYS_FALSE;
}
},
null
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ public long getLong(final ByteBuffer buf, final int position)
throw new UnsupportedOperationException();
}

@Override
public double getDouble(ByteBuffer buf, int position)
{
throw new UnsupportedOperationException();
}
@Override
public void close()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import io.druid.query.filter.BitmapIndexSelector;
import io.druid.query.filter.BoundDimFilter;
import io.druid.query.filter.DimFilter;
import io.druid.query.filter.DruidDoublePredicate;
import io.druid.query.filter.DruidFloatPredicate;
import io.druid.query.filter.DruidLongPredicate;
import io.druid.query.filter.DruidPredicateFactory;
Expand Down Expand Up @@ -633,6 +634,12 @@ public DruidFloatPredicate makeFloatPredicate()
{
return DruidFloatPredicate.ALWAYS_FALSE;
}

@Override
public DruidDoublePredicate makeDoublePredicate()
{
return DruidDoublePredicate.ALWAYS_FALSE;
}
};

return new NoBitmapDimensionPredicateFilter(dimension, predicateFactory, extractionFn);
Expand Down
4 changes: 2 additions & 2 deletions docs/content/ingestion/schema-design.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ of OLAP data.
For more detailed information:

* Every row in Druid must have a timestamp. Data is always partitioned by time, and every query has a time filter. Query results can also be broken down by time buckets like minutes, hours, days, and so on.
* Dimensions are fields that can be filtered on or grouped by. They are always single Strings, arrays of Strings, single Longs, or single Floats.
* Dimensions are fields that can be filtered on or grouped by. They are always single Strings, arrays of Strings, single Longs, single Doubles or single Floats.
* Metrics are fields that can be aggregated. They are often stored as numbers (integers or floats) but can also be stored as complex objects like HyperLogLog sketches or approximate histogram sketches.

Typical production tables (or datasources as they are known in Druid) have fewer than 100 dimensions and fewer
Expand All @@ -22,7 +22,7 @@ Below, we outline some best practices with schema design:

## Numeric dimensions

If the user wishes to ingest a column as a numeric-typed dimension (Long or Float), it is necessary to specify the type of the column in the `dimensions` section of the `dimensionsSpec`. If the type is omitted, Druid will ingest a column as the default String type.
If the user wishes to ingest a column as a numeric-typed dimension (Long, Double or Float), it is necessary to specify the type of the column in the `dimensions` section of the `dimensionsSpec`. If the type is omitted, Druid will ingest a column as the default String type.

There are performance tradeoffs between string and numeric columns. Numeric columns are generally faster to group on
than string columns. But unlike string columns, numeric columns don't have indexes, so they are generally slower to
Expand Down
50 changes: 49 additions & 1 deletion docs/content/querying/aggregations.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,20 @@ computes the sum of values as a 64-bit, signed integer

#### `doubleSum` aggregator

Computes the sum of values as 64-bit floating point value. Similar to `longSum`
Computes and stores the sum of values as 64-bit floating point value. Similar to `longSum`

```json
{ "type" : "doubleSum", "name" : <output_name>, "fieldName" : <metric_name> }
```

#### `floatSum` aggregator

Computes and stores the sum of values as 32-bit floating point value. Similar to `longSum` and `doubleSum`

```json
{ "type" : "floatSum", "name" : <output_name>, "fieldName" : <metric_name> }
```

### Min / Max aggregators

#### `doubleMin` aggregator
Expand All @@ -60,6 +68,22 @@ Computes the sum of values as 64-bit floating point value. Similar to `longSum`
{ "type" : "doubleMax", "name" : <output_name>, "fieldName" : <metric_name> }
```

#### `floatMin` aggregator

`floatMin` computes the minimum of all metric values and Float.POSITIVE_INFINITY

```json
{ "type" : "floatMin", "name" : <output_name>, "fieldName" : <metric_name> }
```

#### `floatMax` aggregator

`floatMax` computes the maximum of all metric values and Float.NEGATIVE_INFINITY

```json
{ "type" : "floatMax", "name" : <output_name>, "fieldName" : <metric_name> }
```

#### `longMin` aggregator

`longMin` computes the minimum of all metric values and Long.MAX_VALUE
Expand Down Expand Up @@ -106,6 +130,30 @@ Note that queries with first/last aggregators on a segment created with rollup e
}
```

#### `floatFirst` aggregator

`floatFirst` computes the metric value with the minimum timestamp or 0 if no row exist

```json
{
"type" : "floatFirst",
"name" : <output_name>,
"fieldName" : <metric_name>
}
```

#### `floatLast` aggregator

`floatLast` computes the metric value with the maximum timestamp or 0 if no row exist

```json
{
"type" : "floatLast",
"name" : <output_name>,
"fieldName" : <metric_name>
}
```

#### `longFirst` aggregator

`longFirst` computes the metric value with the minimum timestamp or 0 if no row exist
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,10 @@ public long getLong()
{
return (long) mutableBitmap.size();
}

@Override
public double getDouble()
{
return (double) mutableBitmap.size();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.primitives.Longs;

import io.druid.java.util.common.StringUtils;
import io.druid.java.util.common.logger.Logger;
import io.druid.query.aggregation.Aggregator;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.aggregation.AggregatorUtil;
Expand All @@ -43,8 +41,6 @@

public class DistinctCountAggregatorFactory extends AggregatorFactory
{
private static final Logger log = new Logger(DistinctCountAggregatorFactory.class);
private static final byte CACHE_TYPE_ID = 20;
private static final BitMapFactory DEFAULT_BITMAP_FACTORY = new RoaringBitMapFactory();

private final String name;
Expand Down Expand Up @@ -178,7 +174,7 @@ public byte[] getCacheKey()
byte[] fieldNameBytes = StringUtils.toUtf8(fieldName);
byte[] bitMapFactoryCacheKey = StringUtils.toUtf8(bitMapFactory.toString());
return ByteBuffer.allocate(2 + fieldNameBytes.length + bitMapFactoryCacheKey.length)
.put(CACHE_TYPE_ID)
.put(AggregatorUtil.DISTINCT_COUNT_CACHE_KEY)
.put(fieldNameBytes)
.put(AggregatorUtil.STRING_SEPARATOR)
.put(bitMapFactoryCacheKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public long getLong(ByteBuffer buf, int position)
return buf.getLong(position);
}

@Override
public double getDouble(ByteBuffer buf, int position)
{
return (double) buf.getLong(position);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be buf.getDouble instead ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, we put as log so same for read

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets add a comment in code, to avoid confusion

}

@Override
public void close()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,23 @@ public Object get()
@Override
public float getFloat()
{
return (float) 0;
return 0.0f;
}

@Override
public void close()
public long getLong()
{
return 0L;
}

@Override
public long getLong()
public double getDouble()
{
return 0.0;
}

@Override
public void close()
{
return (long) 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ public long getLong(ByteBuffer buf, int position)
return (long) 0;
}

@Override
public double getDouble(ByteBuffer buf, int position)
{
return 0;
}

@Override
public void close()
{
Expand Down
Loading