MD-741: Cannot select array elements by index in MapR-DB JSON Tables

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

Branch: refs/heads/master
Commit: 8844a73eff13115dc0a6b7a01720ace99e06797c
Parents: 6988254
Author: Aditya <adi...@mapr.com>
Authored: Thu Feb 25 02:34:30 2016 -0800
Committer: Aditya Kishore <a...@apache.org>
Committed: Fri Sep 9 10:08:37 2016 -0700

----------------------------------------------------------------------
 .../maprdb/json/MaprDBJsonRecordReader.java     | 34 ++++++++++--
 .../drill/maprdb/tests/json/BaseJsonTest.java   | 23 ++++++++
 .../drill/maprdb/tests/json/TestSimpleJson.java | 58 +++++++++++++-------
 .../src/test/resources/json/business.json       | 20 +++----
 4 files changed, 99 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/drill/blob/8844a73e/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 42944f5..0f01662 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
@@ -24,10 +24,12 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.Stack;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.drill.common.exceptions.ExecutionSetupException;
 import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.common.expression.PathSegment;
 import org.apache.drill.common.expression.SchemaPath;
 import org.apache.drill.exec.ops.FragmentContext;
 import org.apache.drill.exec.ops.OperatorContext;
@@ -45,8 +47,9 @@ import org.ojai.DocumentReader;
 import org.ojai.DocumentReader.EventType;
 import org.ojai.DocumentStream;
 import org.ojai.FieldPath;
-import org.ojai.store.QueryCondition;
+import org.ojai.FieldSegment;
 import org.ojai.Value;
+import org.ojai.store.QueryCondition;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Stopwatch;
@@ -111,18 +114,17 @@ public class MaprDBJsonRecordReader extends 
AbstractRecordReader {
            * document when only _id is requested.
            */
           // projectedFieldsList.add(ID_FIELD);
-          transformed.add(ID_PATH);
           includeId = true;
         } else {
-          
transformed.add(SchemaPath.getSimplePath(column.getRootSegment().getPath()));
-          
projectedFieldsSet.add(FieldPath.parseFrom(column.getAsUnescapedPath()));
+          projectedFieldsSet.add(getFieldPathForProjection(column));
         }
+        transformed.add(column);
       }
       if (projectedFieldsSet.size() > 0) {
         projectedFields = projectedFieldsSet.toArray(new 
FieldPath[projectedFieldsSet.size()]);
       }
     } else {
-      transformed.add(ID_PATH);
+      transformed.add(AbstractRecordReader.STAR_COLUMN);
       includeId = true;
     }
 
@@ -388,6 +390,28 @@ public class MaprDBJsonRecordReader extends 
AbstractRecordReader {
     }
   }
 
+  /*
+   * Extracts contiguous named segments from the SchemaPath, starting from the
+   * root segment and build the FieldPath from it for projection.
+   *
+   * This is due to bug 22726 and 22727, which cause DB's DocumentReaders to
+   * behave incorrectly for sparse lists, hence we avoid projecting beyond the
+   * first encountered ARRAY field and let Drill handle the projection.
+   */
+  private static FieldPath getFieldPathForProjection(SchemaPath column) {
+    Stack<PathSegment.NameSegment> pathSegments = new 
Stack<PathSegment.NameSegment>();
+    PathSegment seg = column.getRootSegment();
+    while (seg != null && seg.isNamed()) {
+      pathSegments.push((PathSegment.NameSegment) seg);
+      seg = seg.getChild();
+    }
+    FieldSegment.NameSegment child = null;
+    while (!pathSegments.isEmpty()) {
+      child = new FieldSegment.NameSegment(pathSegments.pop().getPath(), 
child, false);
+    }
+    return new FieldPath(child);
+  }
+
   @Override
   public void close() {
     if (documentStream != null) {

http://git-wip-us.apache.org/repos/asf/drill/blob/8844a73e/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/BaseJsonTest.java
----------------------------------------------------------------------
diff --git 
a/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/BaseJsonTest.java
 
b/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/BaseJsonTest.java
index 5e10528..6aafed3 100644
--- 
a/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/BaseJsonTest.java
+++ 
b/contrib/format-maprdb/src/test/java/com/mapr/drill/maprdb/tests/json/BaseJsonTest.java
@@ -17,9 +17,14 @@
  */
 package com.mapr.drill.maprdb.tests.json;
 
+import java.util.List;
+
 import org.apache.drill.BaseTestQuery;
+import org.apache.drill.exec.exception.SchemaChangeException;
+import org.apache.drill.exec.rpc.user.QueryDataBatch;
 import org.apache.drill.hbase.GuavaPatcher;
 import org.junit.AfterClass;
+import org.junit.Assert;
 import org.junit.BeforeClass;
 
 import com.mapr.drill.maprdb.tests.MaprDBTestsSuite;
@@ -44,4 +49,22 @@ public class BaseJsonTest extends BaseTestQuery {
     MaprDBTestsSuite.cleanupTests();
   }
 
+
+  protected List<QueryDataBatch> runHBaseSQLlWithResults(String sql) throws 
Exception {
+    System.out.println("Running query:\n" + sql);
+    return testSqlWithResults(sql);
+  }
+
+  protected void runSQLAndVerifyCount(String sql, int expectedRowCount) throws 
Exception{
+    List<QueryDataBatch> results = runHBaseSQLlWithResults(sql);
+    printResultAndVerifyRowCount(results, expectedRowCount);
+  }
+
+  private void printResultAndVerifyRowCount(List<QueryDataBatch> results, int 
expectedRowCount) throws SchemaChangeException {
+    int rowCount = printResult(results);
+    if (expectedRowCount != -1) {
+      Assert.assertEquals(expectedRowCount, rowCount);
+    }
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/8844a73e/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 84a73ce..b74b1c5 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
@@ -17,15 +17,22 @@
  */
 package com.mapr.drill.maprdb.tests.json;
 
-import java.util.List;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import org.apache.drill.PlanTestBase;
+import org.apache.drill.SingleRowListener;
 import org.apache.drill.exec.exception.SchemaChangeException;
+import org.apache.drill.exec.proto.UserBitShared.QueryType;
+import org.apache.drill.exec.record.RecordBatchLoader;
 import org.apache.drill.exec.rpc.user.QueryDataBatch;
-import org.junit.Assert;
+import org.apache.drill.exec.util.VectorUtil;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.ojai.Document;
 
+import com.mapr.db.MapRDB;
 import com.mapr.tests.annotations.ClusterTest;
 
 @Category(ClusterTest.class)
@@ -45,13 +52,39 @@ public class TestSimpleJson extends BaseJsonTest {
   public void testPushdownStringEqual() throws Exception {
     setColumnWidths(new int[] {25, 40, 40, 40});
     final String sql = "SELECT\n"
-        + "  _id, name, categories, full_address\n"
+        + "  _id, name, business.hours.Monday.`open`, categories[1], years[2], 
full_address\n"
         + "FROM\n"
         + "  hbase.`business` business\n"
         + "WHERE\n"
         + " name = 'Sprint'"
         ;
-    runSQLAndVerifyCount(sql, 1);
+
+    final Document queryResult = MapRDB.newDocument();
+    SingleRowListener listener = new SingleRowListener() {
+      @Override
+      protected void rowArrived(QueryDataBatch result) {
+        try {
+          final RecordBatchLoader loader = new 
RecordBatchLoader(getAllocator());
+          loader.load(result.getHeader().getDef(), result.getData());
+          StringBuilder sb = new StringBuilder();
+          VectorUtil.appendVectorAccessibleContent(loader, sb, "|", false);
+          loader.clear();
+          queryResult.set("result", sb.toString());
+        } catch (SchemaChangeException e) {
+          queryResult.set("error", "true");
+        }
+      }
+    };
+    testWithListener(QueryType.SQL, sql, listener);
+    listener.waitForCompletion();
+
+    assertNull(queryResult.getString("error"));
+    assertNotNull(queryResult.getString("result"));
+
+    String[] fields = queryResult.getString("result").split("\\|");
+    assertEquals("1970-01-01T11:00:00.000", fields[2]);
+    assertEquals("Mobile Phones", fields[3]);
+    assertEquals("2016.0", fields[4]);
 
     final String[] expectedPlan = {"condition=\\(name = \"Sprint\"\\)"};
     final String[] excludedPlan = {};
@@ -349,21 +382,4 @@ public class TestSimpleJson extends BaseJsonTest {
   }
   */
 
-  protected List<QueryDataBatch> runHBaseSQLlWithResults(String sql) throws 
Exception {
-    System.out.println("Running query:\n" + sql);
-    return testSqlWithResults(sql);
-  }
-
-  protected void runSQLAndVerifyCount(String sql, int expectedRowCount) throws 
Exception{
-    List<QueryDataBatch> results = runHBaseSQLlWithResults(sql);
-    printResultAndVerifyRowCount(results, expectedRowCount);
-  }
-
-  private void printResultAndVerifyRowCount(List<QueryDataBatch> results, int 
expectedRowCount) throws SchemaChangeException {
-    int rowCount = printResult(results);
-    if (expectedRowCount != -1) {
-      Assert.assertEquals(expectedRowCount, rowCount);
-    }
-  }
-
 }

http://git-wip-us.apache.org/repos/asf/drill/blob/8844a73e/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 1121aa3..0010ea1 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"}
-{"_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":"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":"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":"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"}

Reply via email to