drill-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject [34/50] [abbrv] drill git commit: MD-726: Add support for `read_numbers_as_double` and `all_text_mode` options
Date Tue, 13 Sep 2016 01:32:21 GMT
MD-726: Add support for `read_numbers_as_double` and `all_text_mode` options

+ MD-773: Add support to push-down filters on Date, Time and Timestamp
+ Fix the offsets in Date and Time data types in returned values
+ Updated support for DATE, TIME, and TIMESTAMP types
+ Modified unit-tests to check for operation push-down


Project: http://git-wip-us.apache.org/repos/asf/drill/repo
Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/c327f113
Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/c327f113
Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/c327f113

Branch: refs/heads/master
Commit: c327f113b7c32bbe210b3047591f4f3a2339edd1
Parents: b1218f3
Author: Smidth Panchamia <spanchamia@mapr.com>
Authored: Wed Mar 2 22:32:37 2016 -0800
Committer: Aditya Kishore <adi@apache.org>
Committed: Fri Sep 9 10:08:37 2016 -0700

----------------------------------------------------------------------
 .../store/maprdb/MapRDBFormatPluginConfig.java  |  52 ++++-
 .../exec/store/maprdb/MapRDBGroupScan.java      |   4 +
 .../store/maprdb/MapRDBPushFilterIntoScan.java  |  11 +-
 .../store/maprdb/MapRDBScanBatchCreator.java    |   2 +-
 .../drill/exec/store/maprdb/MapRDBSubScan.java  |  11 +-
 .../maprdb/binary/BinaryTableGroupScan.java     |   2 +-
 .../maprdb/binary/MapRDBFilterBuilder.java      |   1 -
 .../maprdb/json/CompareFunctionsProcessor.java  |  21 +-
 .../store/maprdb/json/JsonConditionBuilder.java |   6 +-
 .../exec/store/maprdb/json/JsonSubScanSpec.java |  21 +-
 .../store/maprdb/json/JsonTableGroupScan.java   |   2 +-
 .../maprdb/json/MaprDBJsonRecordReader.java     | 197 ++++++++++++++++---
 .../drill/maprdb/tests/json/TestSimpleJson.java |  26 ++-
 .../src/test/resources/json/business.json       |  18 +-
 14 files changed, 297 insertions(+), 77 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBFormatPluginConfig.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBFormatPluginConfig.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBFormatPluginConfig.java
index 7eff4e4..eb341d9 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBFormatPluginConfig.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBFormatPluginConfig.java
@@ -17,12 +17,19 @@
  */
 package org.apache.drill.exec.store.maprdb;
 
-import com.fasterxml.jackson.annotation.JsonTypeName;
 import org.apache.drill.common.logical.FormatPluginConfig;
 
-@JsonTypeName("maprdb")
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+
+@JsonTypeName("maprdb")  @JsonInclude(Include.NON_DEFAULT)
 public class MapRDBFormatPluginConfig implements FormatPluginConfig {
 
+  private boolean allTextMode = false;
+  private boolean readAllNumbersAsDouble = false;
+
   @Override
   public int hashCode() {
     return 53;
@@ -30,7 +37,46 @@ public class MapRDBFormatPluginConfig implements FormatPluginConfig {
 
   @Override
   public boolean equals(Object obj) {
-    return obj instanceof MapRDBFormatPluginConfig;
+    if (this == obj) {
+      return true;
+    }
+
+    if (obj == null) {
+      return false;
+    }
+
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    MapRDBFormatPluginConfig other = (MapRDBFormatPluginConfig)obj;
+
+    if (readAllNumbersAsDouble != other.readAllNumbersAsDouble) {
+      return false;
+    }
+
+    if (allTextMode != other.allTextMode) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public boolean isReadAllNumbersAsDouble() {
+    return readAllNumbersAsDouble;
+  }
+
+  public boolean isAllTextMode() {
+    return allTextMode;
+  }
+
+  @JsonProperty("allTextMode")
+  public void setAllTextMode(boolean mode) {
+    allTextMode = mode;
   }
 
+  @JsonProperty("readAllNumbersAsDouble")
+  public void setReadAllNumbersAsDouble(boolean read) {
+    readAllNumbersAsDouble = read;
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBGroupScan.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBGroupScan.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBGroupScan.java
index 4d30399..393bfe5 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBGroupScan.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBGroupScan.java
@@ -53,6 +53,8 @@ public abstract class MapRDBGroupScan extends AbstractGroupScan {
 
   private MapRDBFormatPlugin formatPlugin;
 
+  protected MapRDBFormatPluginConfig formatPluginConfig;
+
   protected List<SchemaPath> columns;
 
   protected Map<Integer, List<MapRDBSubScanSpec>> endpointFragmentMapping;
@@ -76,6 +78,7 @@ public abstract class MapRDBGroupScan extends AbstractGroupScan {
     super(that);
     this.columns = that.columns;
     this.formatPlugin = that.formatPlugin;
+    this.formatPluginConfig = that.formatPluginConfig;
     this.storagePlugin = that.storagePlugin;
     this.regionsToScan = that.regionsToScan;
     this.filterPushedDown = that.filterPushedDown;
@@ -86,6 +89,7 @@ public abstract class MapRDBGroupScan extends AbstractGroupScan {
     super(userName);
     this.storagePlugin = storagePlugin;
     this.formatPlugin = formatPlugin;
+    this.formatPluginConfig = (MapRDBFormatPluginConfig)formatPlugin.getConfig();
     this.columns = columns;
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBPushFilterIntoScan.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBPushFilterIntoScan.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBPushFilterIntoScan.java
index 8a0902e..634bf9a 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBPushFilterIntoScan.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBPushFilterIntoScan.java
@@ -17,6 +17,11 @@
  */
 package org.apache.drill.exec.store.maprdb;
 
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelOptRuleOperand;
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rex.RexNode;
 import org.apache.drill.common.expression.LogicalExpression;
 import org.apache.drill.exec.planner.logical.DrillOptiq;
 import org.apache.drill.exec.planner.logical.DrillParseContext;
@@ -32,12 +37,6 @@ import org.apache.drill.exec.store.maprdb.binary.MapRDBFilterBuilder;
 import org.apache.drill.exec.store.maprdb.json.JsonConditionBuilder;
 import org.apache.drill.exec.store.maprdb.json.JsonScanSpec;
 import org.apache.drill.exec.store.maprdb.json.JsonTableGroupScan;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.plan.RelOptRuleCall;
-import org.apache.calcite.plan.RelOptRuleOperand;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rex.RexNode;
-import org.ojai.store.QueryCondition;
 
 import com.google.common.collect.ImmutableList;
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBScanBatchCreator.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBScanBatchCreator.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBScanBatchCreator.java
index 058de61..1cd33ca 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBScanBatchCreator.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBScanBatchCreator.java
@@ -48,7 +48,7 @@ public class MapRDBScanBatchCreator implements BatchCreator<MapRDBSubScan>{
         if (BinaryTableGroupScan.TABLE_BINARY.equals(subScan.getTableType())) {
           readers.add(new HBaseRecordReader(conf, getHBaseSubScanSpec(scanSpec), subScan.getColumns(), context));
         } else {
-          readers.add(new MaprDBJsonRecordReader(scanSpec, subScan.getColumns(), context));
+          readers.add(new MaprDBJsonRecordReader(scanSpec, subScan.getFormatPluginConfig(), subScan.getColumns(), context));
         }
       } catch (Exception e1) {
         throw new ExecutionSetupException(e1);

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBSubScan.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBSubScan.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBSubScan.java
index 39e45f5..7ea4cbf 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBSubScan.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/MapRDBSubScan.java
@@ -46,6 +46,7 @@ public class MapRDBSubScan extends AbstractBase implements SubScan {
   @JsonProperty
   public final StoragePluginConfig storage;
   @JsonIgnore
+  private final MapRDBFormatPluginConfig fsFormatPluginConfig;
   private final FileSystemPlugin fsStoragePlugin;
   private final List<MapRDBSubScanSpec> regionScanSpecList;
   private final List<SchemaPath> columns;
@@ -54,11 +55,13 @@ public class MapRDBSubScan extends AbstractBase implements SubScan {
   @JsonCreator
   public MapRDBSubScan(@JacksonInject StoragePluginRegistry registry,
                        @JsonProperty("userName") String userName,
+                       @JsonProperty("formatPluginConfig") MapRDBFormatPluginConfig formatPluginConfig,
                        @JsonProperty("storage") StoragePluginConfig storage,
                        @JsonProperty("regionScanSpecList") List<MapRDBSubScanSpec> regionScanSpecList,
                        @JsonProperty("columns") List<SchemaPath> columns,
                        @JsonProperty("tableType") String tableType) throws ExecutionSetupException {
     super(userName);
+    this.fsFormatPluginConfig = formatPluginConfig;
     this.fsStoragePlugin = (FileSystemPlugin) registry.getPlugin(storage);
     this.regionScanSpecList = regionScanSpecList;
     this.storage = storage;
@@ -66,9 +69,10 @@ public class MapRDBSubScan extends AbstractBase implements SubScan {
     this.tableType = tableType;
   }
 
-  public MapRDBSubScan(String userName, FileSystemPlugin storagePlugin, StoragePluginConfig config,
+  public MapRDBSubScan(String userName, MapRDBFormatPluginConfig formatPluginConfig, FileSystemPlugin storagePlugin, StoragePluginConfig config,
       List<MapRDBSubScanSpec> maprSubScanSpecs, List<SchemaPath> columns, String tableType) {
     super(userName);
+    fsFormatPluginConfig = formatPluginConfig;
     fsStoragePlugin = storagePlugin;
     storage = config;
     this.regionScanSpecList = maprSubScanSpecs;
@@ -97,7 +101,7 @@ public class MapRDBSubScan extends AbstractBase implements SubScan {
   @Override
   public PhysicalOperator getNewWithChildren(List<PhysicalOperator> children) {
     Preconditions.checkArgument(children.isEmpty());
-    return new MapRDBSubScan(getUserName(), fsStoragePlugin, storage, regionScanSpecList, columns, tableType);
+    return new MapRDBSubScan(getUserName(), fsFormatPluginConfig, fsStoragePlugin, storage, regionScanSpecList, columns, tableType);
   }
 
   @Override
@@ -114,4 +118,7 @@ public class MapRDBSubScan extends AbstractBase implements SubScan {
     return tableType;
   }
 
+  public MapRDBFormatPluginConfig getFormatPluginConfig() {
+    return fsFormatPluginConfig;
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/BinaryTableGroupScan.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/BinaryTableGroupScan.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/BinaryTableGroupScan.java
index 69fda9c..59d0d01 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/BinaryTableGroupScan.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/BinaryTableGroupScan.java
@@ -171,7 +171,7 @@ public class BinaryTableGroupScan extends MapRDBGroupScan implements DrillHBaseC
     assert minorFragmentId < endpointFragmentMapping.size() : String.format(
         "Mappings length [%d] should be greater than minor fragment id [%d] but it isn't.", endpointFragmentMapping.size(),
         minorFragmentId);
-    return new MapRDBSubScan(getUserName(), getStoragePlugin(), getStoragePlugin().getConfig(),
+    return new MapRDBSubScan(getUserName(), formatPluginConfig, getStoragePlugin(), getStoragePlugin().getConfig(),
         endpointFragmentMapping.get(minorFragmentId), columns, TABLE_BINARY);
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/MapRDBFilterBuilder.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/MapRDBFilterBuilder.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/MapRDBFilterBuilder.java
index 07c3364..c4de6bb 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/MapRDBFilterBuilder.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/binary/MapRDBFilterBuilder.java
@@ -34,7 +34,6 @@ import org.apache.hadoop.hbase.filter.ByteArrayComparable;
 import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
 import org.apache.hadoop.hbase.filter.Filter;
 import org.apache.hadoop.hbase.filter.NullComparator;
-import org.apache.hadoop.hbase.filter.PrefixFilter;
 import org.apache.hadoop.hbase.filter.RegexStringComparator;
 import org.apache.hadoop.hbase.filter.RowFilter;
 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/CompareFunctionsProcessor.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/CompareFunctionsProcessor.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/CompareFunctionsProcessor.java
index ba44145..dc5c2b7 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/CompareFunctionsProcessor.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/CompareFunctionsProcessor.java
@@ -17,7 +17,6 @@
  */
 package org.apache.drill.exec.store.maprdb.json;
 
-import org.apache.drill.common.expression.CastExpression;
 import org.apache.drill.common.expression.FunctionCall;
 import org.apache.drill.common.expression.LogicalExpression;
 import org.apache.drill.common.expression.SchemaPath;
@@ -31,8 +30,13 @@ import org.apache.drill.common.expression.ValueExpressions.IntExpression;
 import org.apache.drill.common.expression.ValueExpressions.LongExpression;
 import org.apache.drill.common.expression.ValueExpressions.QuotedString;
 import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
+import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
 import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
+import org.joda.time.LocalTime;
 import org.ojai.Value;
+import org.ojai.types.ODate;
+import org.ojai.types.OTime;
+import org.ojai.types.OTimestamp;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -59,7 +63,7 @@ class CompareFunctionsProcessor extends AbstractExprVisitor<Boolean, LogicalExpr
   public Boolean visitUnknown(LogicalExpression e, LogicalExpression valueArg) throws RuntimeException {
     return false;
   }
- 
+
   public static CompareFunctionsProcessor process(FunctionCall call) {
     String functionName = call.getName();
     LogicalExpression nameArg = call.args.get(0);
@@ -151,15 +155,20 @@ class CompareFunctionsProcessor extends AbstractExprVisitor<Boolean, LogicalExpr
       this.path = path;
       return true;
     }
-/*
+
     if (valueArg instanceof DateExpression) {
-      this.value = KeyValueBuilder.initFrom(new ODate(((DateExpression)valueArg).getDate()));
+      long d = ((DateExpression)valueArg).getDate();
+      final long MILLISECONDS_IN_A_DAY  = (long)1000 * 60 * 60 * 24;
+      int daysSinceEpoch = (int)(d / MILLISECONDS_IN_A_DAY);
+      this.value = KeyValueBuilder.initFrom(ODate.fromDaysSinceEpoch(daysSinceEpoch));
       this.path = path;
       return true;
     }
 
     if (valueArg instanceof TimeExpression) {
-      this.value = KeyValueBuilder.initFrom(new OTime(((TimeExpression)valueArg).getTime()));
+      int t = ((TimeExpression)valueArg).getTime();
+      LocalTime lT = LocalTime.fromMillisOfDay(t);
+      this.value = KeyValueBuilder.initFrom(new OTime(lT.getHourOfDay(), lT.getMinuteOfHour(), lT.getSecondOfMinute(), lT.getMillisOfSecond()));
       this.path = path;
       return true;
     }
@@ -169,7 +178,7 @@ class CompareFunctionsProcessor extends AbstractExprVisitor<Boolean, LogicalExpr
       this.path = path;
       return true;
     }
-*/
+
     return false;
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonConditionBuilder.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonConditionBuilder.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonConditionBuilder.java
index ef32436..889f5a9 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonConditionBuilder.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonConditionBuilder.java
@@ -17,8 +17,6 @@
  */
 package org.apache.drill.exec.store.maprdb.json;
 
-import static org.ojai.DocumentConstants.ID_KEY;
-
 import org.apache.drill.common.expression.BooleanOperator;
 import org.apache.drill.common.expression.FunctionCall;
 import org.apache.drill.common.expression.LogicalExpression;
@@ -164,8 +162,6 @@ public class JsonConditionBuilder extends AbstractExprVisitor<JsonScanSpec, Void
     SchemaPath field = processor.getPath();
     Value fieldValue = processor.getValue();
 
-    boolean isRowKey = field.getAsUnescapedPath().equals(ID_KEY);
-
     QueryCondition cond = null;
     switch (functionName) {
     case "equal":
@@ -231,7 +227,7 @@ public class JsonConditionBuilder extends AbstractExprVisitor<JsonScanSpec, Void
     case "like":
       cond = MapRDB.newCondition().like(field.getAsUnescapedPath(), fieldValue.getString()).build();
       break;
-      
+
     default:
     }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonSubScanSpec.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonSubScanSpec.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonSubScanSpec.java
index 996f658..aa5375a 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonSubScanSpec.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonSubScanSpec.java
@@ -18,10 +18,10 @@
 package org.apache.drill.exec.store.maprdb.json;
 
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 
 import org.apache.drill.exec.store.maprdb.MapRDBSubScanSpec;
 import org.apache.hadoop.hbase.HConstants;
-import org.bouncycastle.util.Arrays;
 import org.ojai.DocumentConstants;
 import org.ojai.Value;
 import org.ojai.store.QueryCondition;
@@ -45,17 +45,17 @@ public class JsonSubScanSpec extends MapRDBSubScanSpec {
                          @JsonProperty("stopRow") byte[] stopRow,
                          @JsonProperty("cond") QueryCondition cond) {
     super(tableName, regionServer, null, null, null, null);
-    
+
     this.condition = MapRDB.newCondition().and();
-    
+
     if (cond != null) {
       this.condition.condition(cond);
     }
-    
+
     if (startRow != null &&
-        Arrays.areEqual(startRow, HConstants.EMPTY_START_ROW) == false) {
+        Arrays.equals(startRow, HConstants.EMPTY_START_ROW) == false) {
       Value startVal = IdCodec.decode(startRow);
-      
+
       switch(startVal.getType()) {
       case BINARY:
         this.condition.is(DocumentConstants.ID_FIELD, Op.GREATER_OR_EQUAL, startVal.getBinary());
@@ -68,11 +68,11 @@ public class JsonSubScanSpec extends MapRDBSubScanSpec {
                                         + " for _id");
       }
     }
-    
+
     if (stopRow != null &&
-        Arrays.areEqual(stopRow, HConstants.EMPTY_END_ROW) == false) {
+        Arrays.equals(stopRow, HConstants.EMPTY_END_ROW) == false) {
       Value stopVal = IdCodec.decode(stopRow);
-      
+
       switch(stopVal.getType()) {
       case BINARY:
         this.condition.is(DocumentConstants.ID_FIELD, Op.LESS, stopVal.getBinary());
@@ -85,7 +85,7 @@ public class JsonSubScanSpec extends MapRDBSubScanSpec {
                                         + " for _id");
       }
     }
-    
+
     this.condition.close().build();
   }
 
@@ -98,6 +98,7 @@ public class JsonSubScanSpec extends MapRDBSubScanSpec {
     return this.condition;
   }
 
+  @Override
   public byte[] getSerializedFilter() {
     if (this.condition != null) {
       ByteBuffer bbuf = ((ConditionImpl)this.condition).getDescriptor().getSerialized();

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonTableGroupScan.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonTableGroupScan.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonTableGroupScan.java
index db27137..6d896aa 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonTableGroupScan.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/JsonTableGroupScan.java
@@ -146,7 +146,7 @@ public class JsonTableGroupScan extends MapRDBGroupScan {
     assert minorFragmentId < endpointFragmentMapping.size() : String.format(
         "Mappings length [%d] should be greater than minor fragment id [%d] but it isn't.", endpointFragmentMapping.size(),
         minorFragmentId);
-    return new MapRDBSubScan(getUserName(), getStoragePlugin(), getStoragePlugin().getConfig(),
+    return new MapRDBSubScan(getUserName(), formatPluginConfig, getStoragePlugin(), getStoragePlugin().getConfig(),
         endpointFragmentMapping.get(minorFragmentId), columns, TABLE_JSON);
   }
 

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/MaprDBJsonRecordReader.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/MaprDBJsonRecordReader.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/MaprDBJsonRecordReader.java
index 1d1ef44..8f22a2a 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/MaprDBJsonRecordReader.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/maprdb/json/MaprDBJsonRecordReader.java
@@ -18,8 +18,10 @@
 package org.apache.drill.exec.store.maprdb.json;
 
 import static org.ojai.DocumentConstants.ID_KEY;
+import io.netty.buffer.DrillBuf;
 
 import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -37,6 +39,7 @@ import org.apache.drill.exec.ops.OperatorContext;
 import org.apache.drill.exec.ops.OperatorStats;
 import org.apache.drill.exec.physical.impl.OutputMutator;
 import org.apache.drill.exec.store.AbstractRecordReader;
+import org.apache.drill.exec.store.maprdb.MapRDBFormatPluginConfig;
 import org.apache.drill.exec.store.maprdb.MapRDBSubScanSpec;
 import org.apache.drill.exec.vector.BaseValueVector;
 import org.apache.drill.exec.vector.complex.impl.VectorContainerWriter;
@@ -51,6 +54,7 @@ import org.ojai.FieldPath;
 import org.ojai.FieldSegment;
 import org.ojai.Value;
 import org.ojai.store.QueryCondition;
+import org.ojai.types.OTime;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
@@ -64,8 +68,6 @@ import com.mapr.db.ojai.DBDocumentReaderBase;
 import com.mapr.db.util.ByteBufs;
 import com.mapr.org.apache.hadoop.hbase.util.Bytes;
 
-import io.netty.buffer.DrillBuf;
-
 public class MaprDBJsonRecordReader extends AbstractRecordReader {
   private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MaprDBJsonRecordReader.class);
 
@@ -75,7 +77,7 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
   private QueryCondition condition;
   private FieldPath[] projectedFields;
 
-  private String tableName;
+  private final String tableName;
   private OperatorContext operatorContext;
   private VectorContainerWriter writer;
 
@@ -87,9 +89,13 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
 
   private boolean includeId;
   private boolean idOnly;
-  private boolean unionEnabled;
+  private final boolean unionEnabled;
+  private final boolean readNumbersAsDouble;
+  private final boolean allTextMode;
+  private final long MILLISECONDS_IN_A_DAY  = (long)1000 * 60 * 60 * 24;
 
   public MaprDBJsonRecordReader(MapRDBSubScanSpec subScanSpec,
+      MapRDBFormatPluginConfig formatPluginConfig,
       List<SchemaPath> projectedColumns, FragmentContext context) {
     buffer = context.getManagedBuffer();
     projectedFields = null;
@@ -97,9 +103,17 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
     documentReaderIterators = null;
     includeId = false;
     idOnly    = false;
-    condition = com.mapr.db.impl.ConditionImpl.parseFrom(ByteBufs.wrap(subScanSpec.getSerializedFilter()));
+    byte[] serializedFilter = subScanSpec.getSerializedFilter();
+    condition = null;
+
+    if (serializedFilter != null) {
+      condition = com.mapr.db.impl.ConditionImpl.parseFrom(ByteBufs.wrap(serializedFilter));
+    }
+
     setColumns(projectedColumns);
     unionEnabled = context.getOptions().getOption(ExecConstants.ENABLE_UNION_TYPE);
+    readNumbersAsDouble = formatPluginConfig.isReadAllNumbersAsDouble();
+    allTextMode = formatPluginConfig.isAllTextMode();
   }
 
   @Override
@@ -180,7 +194,11 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
               recordCount++;
               break;
             case BINARY:
-              writeBinary(map.varBinary(ID_KEY), id.getBinary());
+              if (allTextMode) {
+                writeString(map.varChar(ID_KEY), new String(id.getBinary().array(), Charset.forName("UTF-8")));
+              } else {
+                writeBinary(map.varBinary(ID_KEY), id.getBinary());
+              }
               recordCount++;
               break;
             default:
@@ -224,42 +242,104 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
         case NULL:
           break; // not setting the field will leave it as null
         case BINARY:
-          writeBinary(map.varBinary(fieldName), reader.getBinary());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), new String(reader.getBinary().array(), Charset.forName("UTF-8")));
+          } else {
+            writeBinary(map.varBinary(fieldName), reader.getBinary());
+          }
           break;
         case BOOLEAN:
-          map.bit(fieldName).writeBit(reader.getBoolean() ? 1 : 0);
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getBoolean()));
+          } else {
+            map.bit(fieldName).writeBit(reader.getBoolean() ? 1 : 0);
+          }
           break;
         case STRING:
           writeString(map.varChar(fieldName), reader.getString());
           break;
         case BYTE:
-          map.tinyInt(fieldName).writeTinyInt(reader.getByte());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getByte()));
+          } else if (readNumbersAsDouble) {
+            map.float8(fieldName).writeFloat8(reader.getByte());
+          } else {
+            map.tinyInt(fieldName).writeTinyInt(reader.getByte());
+          }
           break;
         case SHORT:
-          map.smallInt(fieldName).writeSmallInt(reader.getShort());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getShort()));
+          } else if (readNumbersAsDouble) {
+            map.float8(fieldName).writeFloat8(reader.getShort());
+          } else {
+            map.smallInt(fieldName).writeSmallInt(reader.getShort());
+          }
           break;
         case INT:
-          map.integer(fieldName).writeInt(reader.getInt());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getInt()));
+          } else if (readNumbersAsDouble) {
+            map.float8(fieldName).writeFloat8(reader.getInt());
+          } else {
+            map.integer(fieldName).writeInt(reader.getInt());
+          }
           break;
         case LONG:
-          map.bigInt(fieldName).writeBigInt(reader.getLong());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getLong()));
+          } else if (readNumbersAsDouble) {
+            map.float8(fieldName).writeFloat8(reader.getLong());
+          } else {
+            map.bigInt(fieldName).writeBigInt(reader.getLong());
+          }
           break;
         case FLOAT:
-          map.float4(fieldName).writeFloat4(reader.getFloat());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getFloat()));
+          } else if (readNumbersAsDouble) {
+            map.float8(fieldName).writeFloat8(reader.getFloat());
+          } else {
+            map.float4(fieldName).writeFloat4(reader.getFloat());
+          }
           break;
         case DOUBLE:
-          map.float8(fieldName).writeFloat8(reader.getDouble());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), String.valueOf(reader.getDouble()));
+          } else {
+            map.float8(fieldName).writeFloat8(reader.getDouble());
+          }
           break;
         case DECIMAL:
           throw unsupportedError("Decimal type is currently not supported.");
         case DATE:
-          map.date(fieldName).writeDate(reader.getDate().toDate().getTime());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), reader.getDate().toString());
+          } else {
+
+            long milliSecondsSinceEpoch = reader.getDate().toDaysSinceEpoch() * MILLISECONDS_IN_A_DAY;
+            map.date(fieldName).writeDate(milliSecondsSinceEpoch);
+          }
           break;
         case TIME:
-          map.time(fieldName).writeTime(reader.getTimeInt());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), reader.getTime().toString());
+          } else {
+            OTime t = reader.getTime();
+            int h = t.getHour();
+            int m = t.getMinute();
+            int s = t.getSecond();
+            int ms = t.getMilliSecond();
+            int millisOfDay = ms + (s + ((m + (h * 60)) * 60)) * 1000;
+            map.time(fieldName).writeTime(millisOfDay);
+          }
           break;
         case TIMESTAMP:
-          map.timeStamp(fieldName).writeTimeStamp(reader.getTimestampLong());
+          if (allTextMode) {
+            writeString(map.varChar(fieldName), reader.getTimestamp().toString());
+          } else {
+            map.timeStamp(fieldName).writeTimeStamp(reader.getTimestampLong());
+          }
           break;
         case INTERVAL:
           throw unsupportedError("Interval type is currently not supported.");
@@ -292,42 +372,103 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
       case NULL:
         throw unsupportedError("Null values are not supported in lists.");
       case BINARY:
-        writeBinary(list.varBinary(), reader.getBinary());
+        if (allTextMode) {
+          writeString(list.varChar(), new String(reader.getBinary().array(), Charset.forName("UTF-8")));
+        } else {
+          writeBinary(list.varBinary(), reader.getBinary());
+        }
         break;
       case BOOLEAN:
-        list.bit().writeBit(reader.getBoolean() ? 1 : 0);
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getBoolean()));
+        } else {
+          list.bit().writeBit(reader.getBoolean() ? 1 : 0);
+        }
         break;
       case STRING:
         writeString(list.varChar(), reader.getString());
         break;
       case BYTE:
-        list.tinyInt().writeTinyInt(reader.getByte());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getByte()));
+        } else if (readNumbersAsDouble) {
+          list.float8().writeFloat8(reader.getByte());
+        } else {
+          list.tinyInt().writeTinyInt(reader.getByte());
+        }
         break;
       case SHORT:
-        list.smallInt().writeSmallInt(reader.getShort());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getShort()));
+        } else if (readNumbersAsDouble) {
+          list.float8().writeFloat8(reader.getShort());
+        } else {
+          list.smallInt().writeSmallInt(reader.getShort());
+        }
         break;
       case INT:
-        list.integer().writeInt(reader.getInt());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getInt()));
+        } else if (readNumbersAsDouble) {
+          list.float8().writeFloat8(reader.getInt());
+        } else {
+          list.integer().writeInt(reader.getInt());
+        }
         break;
       case LONG:
-        list.bigInt().writeBigInt(reader.getLong());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getLong()));
+        } else if (readNumbersAsDouble) {
+          list.float8().writeFloat8(reader.getLong());
+        } else {
+          list.bigInt().writeBigInt(reader.getLong());
+        }
         break;
       case FLOAT:
-        list.float4().writeFloat4(reader.getFloat());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getFloat()));
+        } else if (readNumbersAsDouble) {
+          list.float8().writeFloat8(reader.getFloat());
+        } else {
+          list.float4().writeFloat4(reader.getFloat());
+        }
         break;
       case DOUBLE:
-        list.float8().writeFloat8(reader.getDouble());
+        if (allTextMode) {
+          writeString(list.varChar(), String.valueOf(reader.getDouble()));
+        } else {
+          list.float8().writeFloat8(reader.getDouble());
+        }
         break;
       case DECIMAL:
         throw unsupportedError("Decimals are currently not supported.");
       case DATE:
-        list.date().writeDate(reader.getDate().toDate().getTime());
+        if (allTextMode) {
+          writeString(list.varChar(), reader.getDate().toString());
+        } else {
+          long milliSecondsSinceEpoch = reader.getDate().toDaysSinceEpoch() * MILLISECONDS_IN_A_DAY;
+          list.date().writeDate(milliSecondsSinceEpoch);
+        }
         break;
       case TIME:
-        list.time().writeTime(reader.getTimeInt());
+        if (allTextMode) {
+          writeString(list.varChar(), reader.getTime().toString());
+        } else {
+          OTime t = reader.getTime();
+          int h = t.getHour();
+          int m = t.getMinute();
+          int s = t.getSecond();
+          int ms = t.getMilliSecond();
+          int millisOfDay = ms + (s + ((m + (h * 60)) * 60)) * 1000;
+          list.time().writeTime(millisOfDay);
+        }
         break;
       case TIMESTAMP:
-        list.timeStamp().writeTimeStamp(reader.getTimestampLong());
+        if (allTextMode) {
+          writeString(list.varChar(), reader.getTimestamp().toString());
+        } else {
+          list.timeStamp().writeTimeStamp(reader.getTimestampLong());
+        }
         break;
       case INTERVAL:
         throw unsupportedError("Interval is currently not supported.");

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/TestSimpleJson.java
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/TestSimpleJson.java b/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/TestSimpleJson.java
index b74b1c5..f8d4ac4 100644
--- a/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/TestSimpleJson.java
+++ b/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/TestSimpleJson.java
@@ -330,7 +330,7 @@ public class TestSimpleJson extends BaseJsonTest {
     PlanTestBase.testPlanMatchingPatterns(sql, expectedPlan, excludedPlan);
   }
 
-  /*
+
   @Test
   public void testPushDownSubField5() throws Exception {
     final String sql = "SELECT\n"
@@ -341,6 +341,11 @@ public class TestSimpleJson extends BaseJsonTest {
         + " business.`hours.Tuesday.open` < TIME '10:30:00'"
         ;
     runSQLAndVerifyCount(sql, 1);
+
+    final String[] expectedPlan = {"condition=\\(hours.Tuesday.open < \\{\"\\$time\":\"10:30:00\"\\}\\)"};
+    final String[] excludedPlan = {};
+
+    PlanTestBase.testPlanMatchingPatterns(sql, expectedPlan, excludedPlan);
   }
 
   @Test
@@ -352,7 +357,12 @@ public class TestSimpleJson extends BaseJsonTest {
         + "WHERE\n"
         + " business.`hours.Sunday.close` > TIME '20:30:00'"
         ;
-    runSQLAndVerifyCount(sql, 4);
+    runSQLAndVerifyCount(sql, 3);
+
+    final String[] expectedPlan = {"condition=\\(hours.Sunday.close > \\{\"\\$time\":\"20:30:00\"\\}\\)"};
+    final String[] excludedPlan = {};
+
+    PlanTestBase.testPlanMatchingPatterns(sql, expectedPlan, excludedPlan);
   }
 
   @Test
@@ -366,6 +376,11 @@ public class TestSimpleJson extends BaseJsonTest {
         + " business.`start_date` = DATE '2012-07-14'"
         ;
     runSQLAndVerifyCount(sql, 1);
+
+    final String[] expectedPlan = {"condition=\\(start_date = \\{\"\\$dateDay\":\"2012-07-14\"\\}\\)"};
+    final String[] excludedPlan = {};
+
+    PlanTestBase.testPlanMatchingPatterns(sql, expectedPlan, excludedPlan);
   }
 
   @Test
@@ -379,7 +394,10 @@ public class TestSimpleJson extends BaseJsonTest {
         + " business.`last_update` = TIMESTAMP '2012-10-20 07:42:46'"
         ;
     runSQLAndVerifyCount(sql, 1);
-  }
-  */
 
+    final String[] expectedPlan = {"condition=\\(last_update = \\{\"\\$date\":\"2012-10-20T07:42:46.000Z\"\\}\\)"};
+    final String[] excludedPlan = {};
+
+    PlanTestBase.testPlanMatchingPatterns(sql, expectedPlan, excludedPlan);
+  }
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/c327f113/contrib/format-maprdb/src/test/resources/json/business.json
----------------------------------------------------------------------
diff --git a/contrib/format-maprdb/src/test/resources/json/business.json b/contrib/format-maprdb/src/test/resources/json/business.json
index 0010ea1..6cc54df 100644
--- a/contrib/format-maprdb/src/test/resources/json/business.json
+++ b/contrib/format-maprdb/src/test/resources/json/business.json
@@ -1,10 +1,10 @@
-{"_version":{"$numberLong":0},"business_id":"1emggGHgoG6ipd_RMb-g","full_address":"3280 S Decatur Blvd\nWestside\nLas Vegas, NV 89102","zip":{"$numberLong":89102},"hours":{},"open":true,"categories":["Food","Convenience Stores"],"city":"Las Vegas","review_count":4,"name":"Sinclair","neighborhoods":["Westside"],"longitude":-115.2072382,"state":"NV","stars":4,"latitude":36.1305306,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":true,"valet":false},"Accepts Credit Cards":true,"Price Range":1},"type":"business", "start_date":"2011-07-14"}
-{"_version":{"$numberLong":0},"business_id":"4Pe8BZ6gj57VFL5mUE8g","full_address":"21001 North Tatum Blvd. #24\nPhoenix, AZ 85050","zip":{"$numberLong":85050},"hours":{},"open":true,"categories":["Shopping","Office Equipment"],"city":"Phoenix","review_count":5,"name":"Office Max","neighborhoods":[],"longitude":-111.9746066,"state":"AZ","stars":3,"latitude":33.678615,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Accepts Credit Cards":true,"Price Range":3},"type":"business", "start_date":"2012-07-14"}
-{"_version":{"$numberLong":0},"business_id":"5jkZ3-nUPZxUvtcbr8Uw","full_address":"1336 N Scottsdale Rd\nScottsdale, AZ 85257","zip":{"$numberLong":85257},"hours":{"Monday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Friday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Wednesday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Thursday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}}},"open":true,"categories":["Greek","Restaurants"],"city":"Scottsdale","review_count":42,"name":"Mika's Greek","neighborhoods":[],"longitude":-111.926908493042,"state":"AZ","stars":4.5,"latitude":33.4633733188117,"attributes":{"Take-out":true,"Wi-Fi":"no","Good For":{"dessert":false,"latenight":false,"lunch":true,"dinner":false,"breakfast":false,"b
 runch":false},"Caters":true,"Noise Level":"quiet","Takes Reservations":false,"Delivery":false,"Ambience":{"romantic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":true},"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Has TV":false,"Outdoor Seating":true,"Attire":"casual","Alcohol":"none","Waiter Service":false,"Accepts Credit Cards":true,"Good for Kids":true,"Good For Groups":true,"Price Range":1},"type":"business", "start_date":"2013-07-14"}
-{"_version":{"$numberLong":0},"business_id":"BlvDO_RG2yElKu9XA1_g","full_address":"14870 N Northsight Blvd\nSte 103\nScottsdale, AZ 85260","zip":{"$numberLong":85260},"hours":{"Monday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Tuesday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Friday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Wednesday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Thursday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"12:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"12:00:00"}}},"open":true,"categories":["Sushi Bars","Hawaiian","Chinese","Restaurants"],"city":"Scottsdale","review_count":65,"name":"Asian Island","neighborhoods":[],"longitude":-111.89783602953,"state":"AZ","stars":4,"latitude":33.6205679923296,"attributes":{"Take-out":true,"Wi-Fi":"free","Good For":{"dessert":false,"latenight":false,"lunch":tru
 e,"dinner":false,"breakfast":false,"brunch":false},"Caters":true,"Noise Level":"average","Takes Reservations":false,"Has TV":false,"Delivery":true,"Ambience":{"romantic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":true},"Parking":{"garage":false,"street":false,"validated":false,"lot":true,"valet":false},"Wheelchair Accessible":true,"Outdoor Seating":true,"Attire":"casual","Alcohol":"none","Waiter Service":true,"Accepts Credit Cards":true,"Good for Kids":true,"Good For Groups":true,"Price Range":1},"type":"business", "start_date":"2014-07-14"}
-{"_version":{"$numberLong":0},"business_id":"Dl2rW_xO8GuYBomlg9zw","full_address":"4505 S Maryland Pkwy\nUniversity\nLas Vegas, NV 89119","zip":{"$numberLong":89119},"hours":{},"open":true,"categories":["Medical Centers","Health & Medical"],"city":"Las Vegas","review_count":6,"name":"UNLV Student Health Center","neighborhoods":["University"],"longitude":-115.1415145,"state":"NV","stars":4,"latitude":36.1109405,"attributes":{"By Appointment Only":true},"type":"business", "start_date":"2011-04-14"}
-{"_version":{"$numberLong":0},"business_id":"Ol5mVSMaW8ExtmWRUmKA","full_address":"7110 E Thomas Rd\nSte D\nScottsdale, AZ 85251","zip":{"$numberLong":85251},"hours":{},"open":true,"categories":["Barbers","Beauty & Spas"],"city":"Scottsdale","review_count":3,"name":"Dave's Barber Shop","neighborhoods":[],"longitude":-111.9289668,"state":"AZ","stars":5,"latitude":33.48051,"attributes":{"By Appointment Only":false,"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Price Range":2},"type":"business", "start_date":"2013-02-15"}
-{"_version":{"$numberLong":0},"business_id":"XBxRlD92RaV6TyUnP8Ow","full_address":"7510 W Thomas Rd Ste 108\nPhoenix, AZ 85033","zip":{"$numberLong":85033},"hours":{"Monday":{"close":{"$time":"19:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Friday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Wednesday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Thursday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"09:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"09:00:00"}}},"open":true,"categories":["Shopping","Mobile Phones"],"city":"Phoenix","review_count":3,"name":"Sprint","neighborhoods":[],"longitude":-112.221054,"state":"AZ","stars":3.5,"latitude":33.480679,"attributes":{},"type":"business", "start_date":"2013-01-21", "years":[2014,2015,2016]}
-{"_version":{"$numberLong":0},"business_id":"Y_2lDOtVDioX5bwF6GIw","full_address":"115 State St\nCapitol\nMadison, WI 53703","zip":{"$numberLong":53703},"hours":{"Monday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Friday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Wednesday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Thursday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Sunday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Saturday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}}},"open":true,"categories":["Bars","Comfort Food","Nightlife","Restaurants"],"city":"Madison","review_count":21,"name":"Buck & Badger","neighborhoods":["Capitol"],"longitude":-89.3871119284652,"state":"WI","stars":3,"latitude":43.0747392865267,"attributes":{"Alcohol":"full_bar","Noise Level":"average","Has TV":true,"Attire":"casual","Ambience":{"roma
 ntic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":false},"Good for Kids":true,"Price Range":2,"Good For Dancing":false,"Delivery":false,"Coat Check":false,"Smoking":"no","Accepts Credit Cards":true,"Take-out":true,"Happy Hour":true,"Outdoor Seating":true,"Takes Reservations":true,"Waiter Service":true,"Wi-Fi":"no","Good For":{"dessert":false,"latenight":false,"lunch":false,"dinner":false,"brunch":false,"breakfast":false},"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Music":{"dj":false,"background_music":true,"jukebox":false,"live":false,"video":false,"karaoke":false},"Good For Groups":true},"type":"business", "start_date":"2015-03-21"}
+{"_version":{"$numberLong":0},"business_id":"1emggGHgoG6ipd_RMb-g","full_address":"3280 S Decatur Blvd\nWestside\nLas Vegas, NV 89102","zip":{"$numberLong":89102},"hours":{},"open":true,"categories":["Food","Convenience Stores"],"city":"Las Vegas","review_count":4,"name":"Sinclair","neighborhoods":["Westside"],"longitude":-115.2072382,"state":"NV","stars":4,"latitude":36.1305306,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":true,"valet":false},"Accepts Credit Cards":true,"Price Range":1},"type":"business", "start_date":{"$dateDay":"2011-07-14"}, "last_update":{"$date":"2012-10-20T07:42:46.000Z"}}
+{"_version":{"$numberLong":0},"business_id":"4Pe8BZ6gj57VFL5mUE8g","full_address":"21001 North Tatum Blvd. #24\nPhoenix, AZ 85050","zip":{"$numberLong":85050},"hours":{},"open":true,"categories":["Shopping","Office Equipment"],"city":"Phoenix","review_count":5,"name":"Office Max","neighborhoods":[],"longitude":-111.9746066,"state":"AZ","stars":3,"latitude":33.678615,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Accepts Credit Cards":true,"Price Range":3},"type":"business", "start_date":{"$dateDay":"2012-07-14"}}
+{"_version":{"$numberLong":0},"business_id":"5jkZ3-nUPZxUvtcbr8Uw","full_address":"1336 N Scottsdale Rd\nScottsdale, AZ 85257","zip":{"$numberLong":85257},"hours":{"Monday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Friday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Wednesday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Thursday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"11:00:00"}}},"open":true,"categories":["Greek","Restaurants"],"city":"Scottsdale","review_count":42,"name":"Mika's Greek","neighborhoods":[],"longitude":-111.926908493042,"state":"AZ","stars":4.5,"latitude":33.4633733188117,"attributes":{"Take-out":true,"Wi-Fi":"no","Good For":{"dessert":false,"latenight":false,"lunch":true,"dinner":false,"breakfast":false,"b
 runch":false},"Caters":true,"Noise Level":"quiet","Takes Reservations":false,"Delivery":false,"Ambience":{"romantic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":true},"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Has TV":false,"Outdoor Seating":true,"Attire":"casual","Alcohol":"none","Waiter Service":false,"Accepts Credit Cards":true,"Good for Kids":true,"Good For Groups":true,"Price Range":1},"type":"business", "start_date":{"$dateDay":"2013-07-14"}}
+{"_version":{"$numberLong":0},"business_id":"BlvDO_RG2yElKu9XA1_g","full_address":"14870 N Northsight Blvd\nSte 103\nScottsdale, AZ 85260","zip":{"$numberLong":85260},"hours":{"Monday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Tuesday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Friday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Wednesday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Thursday":{"close":{"$time":"21:00:00"},"open":{"$time":"10:30:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"12:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"12:00:00"}}},"open":true,"categories":["Sushi Bars","Hawaiian","Chinese","Restaurants"],"city":"Scottsdale","review_count":65,"name":"Asian Island","neighborhoods":[],"longitude":-111.89783602953,"state":"AZ","stars":4,"latitude":33.6205679923296,"attributes":{"Take-out":true,"Wi-Fi":"free","Good For":{"dessert":false,"latenight":false,"lunch":tru
 e,"dinner":false,"breakfast":false,"brunch":false},"Caters":true,"Noise Level":"average","Takes Reservations":false,"Has TV":false,"Delivery":true,"Ambience":{"romantic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":true},"Parking":{"garage":false,"street":false,"validated":false,"lot":true,"valet":false},"Wheelchair Accessible":true,"Outdoor Seating":true,"Attire":"casual","Alcohol":"none","Waiter Service":true,"Accepts Credit Cards":true,"Good for Kids":true,"Good For Groups":true,"Price Range":1},"type":"business", "start_date":{"$dateDay":"2014-07-14"}}
+{"_version":{"$numberLong":0},"business_id":"Dl2rW_xO8GuYBomlg9zw","full_address":"4505 S Maryland Pkwy\nUniversity\nLas Vegas, NV 89119","zip":{"$numberLong":89119},"hours":{},"open":true,"categories":["Medical Centers","Health & Medical"],"city":"Las Vegas","review_count":6,"name":"UNLV Student Health Center","neighborhoods":["University"],"longitude":-115.1415145,"state":"NV","stars":4,"latitude":36.1109405,"attributes":{"By Appointment Only":true},"type":"business", "start_date":{"$dateDay":"2011-04-14"}}
+{"_version":{"$numberLong":0},"business_id":"Ol5mVSMaW8ExtmWRUmKA","full_address":"7110 E Thomas Rd\nSte D\nScottsdale, AZ 85251","zip":{"$numberLong":85251},"hours":{},"open":true,"categories":["Barbers","Beauty & Spas"],"city":"Scottsdale","review_count":3,"name":"Dave's Barber Shop","neighborhoods":[],"longitude":-111.9289668,"state":"AZ","stars":5,"latitude":33.48051,"attributes":{"By Appointment Only":false,"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Price Range":2},"type":"business", "start_date":{"$dateDay":"2013-02-15"}}
+{"_version":{"$numberLong":0},"business_id":"XBxRlD92RaV6TyUnP8Ow","full_address":"7510 W Thomas Rd Ste 108\nPhoenix, AZ 85033","zip":{"$numberLong":85033},"hours":{"Monday":{"close":{"$time":"19:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Friday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Wednesday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Thursday":{"close":{"$time":"20:00:00"},"open":{"$time":"09:00:00"}},"Sunday":{"close":{"$time":"21:00:00"},"open":{"$time":"09:00:00"}},"Saturday":{"close":{"$time":"21:00:00"},"open":{"$time":"09:00:00"}}},"open":true,"categories":["Shopping","Mobile Phones"],"city":"Phoenix","review_count":3,"name":"Sprint","neighborhoods":[],"longitude":-112.221054,"state":"AZ","stars":3.5,"latitude":33.480679,"attributes":{},"type":"business", "start_date":{"$dateDay":"2013-01-21"}, "years":[2014,2015,2016]}
+{"_version":{"$numberLong":0},"business_id":"Y_2lDOtVDioX5bwF6GIw","full_address":"115 State St\nCapitol\nMadison, WI 53703","zip":{"$numberLong":53703},"hours":{"Monday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Tuesday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Friday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Wednesday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Thursday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}},"Sunday":{"close":{"$time":"14:00:00"},"open":{"$time":"11:00:00"}},"Saturday":{"close":{"$time":"02:00:00"},"open":{"$time":"11:00:00"}}},"open":true,"categories":["Bars","Comfort Food","Nightlife","Restaurants"],"city":"Madison","review_count":21,"name":"Buck & Badger","neighborhoods":["Capitol"],"longitude":-89.3871119284652,"state":"WI","stars":3,"latitude":43.0747392865267,"attributes":{"Alcohol":"full_bar","Noise Level":"average","Has TV":true,"Attire":"casual","Ambience":{"roma
 ntic":false,"intimate":false,"touristy":false,"hipster":false,"divey":false,"classy":false,"trendy":false,"upscale":false,"casual":false},"Good for Kids":true,"Price Range":2,"Good For Dancing":false,"Delivery":false,"Coat Check":false,"Smoking":"no","Accepts Credit Cards":true,"Take-out":true,"Happy Hour":true,"Outdoor Seating":true,"Takes Reservations":true,"Waiter Service":true,"Wi-Fi":"no","Good For":{"dessert":false,"latenight":false,"lunch":false,"dinner":false,"brunch":false,"breakfast":false},"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Music":{"dj":false,"background_music":true,"jukebox":false,"live":false,"video":false,"karaoke":false},"Good For Groups":true},"type":"business", "start_date":{"$dateDay":"2015-03-21"}}
 {"_version":{"$numberLong":0},"business_id":"jFTZmywe7StuZ2hEjxyA","full_address":"3991 Dean Martin Dr\nLas Vegas, NV 89103","zip":{"$numberLong":89103},"hours":{},"open":true,"categories":["Sandwiches","Restaurants"],"city":"Las Vegas","review_count":4,"name":"Subway","neighborhoods":[],"longitude":-115.18200516700699,"state":"NV","stars":4,"latitude":36.1188189268328,"attributes":{"Take-out":true,"Good For":{"dessert":false,"latenight":false,"lunch":false,"dinner":false,"brunch":false,"breakfast":false},"Takes Reservations":false,"Delivery":false,"Outdoor Seating":false,"Attire":"casual","Accepts Credit Cards":true,"Good for Kids":true,"Good For Groups":true,"Price Range":1},"type":"business", "start_date":"2014-02-13"}
-{"_version":{"$numberLong":0},"business_id":"m1g9P1wxNblrLANfVqlA","full_address":"6 Waterloo Place\nEdinburgh EH1 3EG","hours":{},"open":true,"categories":["Bridal","Shopping"],"city":"Edinburgh","review_count":5,"name":"Caroline Castigliano","neighborhoods":[],"longitude":-3.1881974,"state":"EDH","stars":4,"latitude":55.9534049,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Accepts Credit Cards":true,"Price Range":3},"type":"business", "start_date":"2014-02-17"}
+{"_version":{"$numberLong":0},"business_id":"m1g9P1wxNblrLANfVqlA","full_address":"6 Waterloo Place\nEdinburgh EH1 3EG","hours":{},"open":true,"categories":["Bridal","Shopping"],"city":"Edinburgh","review_count":5,"name":"Caroline Castigliano","neighborhoods":[],"longitude":-3.1881974,"state":"EDH","stars":4,"latitude":55.9534049,"attributes":{"Parking":{"garage":false,"street":false,"validated":false,"lot":false,"valet":false},"Accepts Credit Cards":true,"Price Range":3},"type":"business", "start_date":{"$dateDay":"2014-02-17"}}


Mime
View raw message