Geo Spatial

Starting with the mass-market availability of smartphones and continuing with IoT devices, self-driving cars ever more data is generated with geo information attached to it. Analyzing this data in real-time requires the use of clever indexing data-structures.

The GeoJSON functionalities in GDN are based on Google’s S2 geospatial index. We support indexing on a subset of the GeoJSON standard, as well as simple latitude-longitude pairs (Non-GeoJSON mode).

Calculating e.g. the distance between two coordinate tuples or checking whether a coordinate pair is located inside a polygon was possible, but those functions could not benefit by using the geo index optimizations. Those operations need to be as fast as possible to prevent them from being a show stopper.

Of course, speed is not everything, so we also want to provide a broader set of geo functionality by integrating full GeoJSON support including Polygons, Multi-Polygons and other geometry primitives.

With these functionalities, one can do more complex queries and build e.g. location-aware recommendation engines by combining the graph data model with geo-location aspects or use multiple data models.

For instance, in the age of self-driving cars, one can find the nearest available maintenance team (geo query) with the right permission (graph model) to repair a given problem (sent automatically to the DB as e.g. a JSON document or key/value pair).

Pre-requisite

Let's assume your

  • Tenant name is guest@macrometa.io and
  • User password is guest.

Driver download


pyC8 requires Python 3.5+. Python 3.6 or higher is recommended

To install pyC8, simply run

    $ pip3 install pyC8

or, if you prefer to use conda:

    conda install -c conda-forge pyC8

or pipenv:

    pipenv install --pre pyC8

Once the installation process is finished, you can begin developing applications in Python.

With Yarn or NPM

    yarn add jsc8
    (or)
    npm install jsc8

If you want to use the driver outside of the current directory, you can also install it globally using the `--global` flag:

    npm install --global jsc8

From source,

    git clone https://github.com/macrometacorp/jsc8.git
    cd jsC8
    npm install
    npm run dist

Code Sample


from c8 import C8Client
import pprint

if __name__ == '__main__':

  # Variables - URLs
  global_url = "gdn1.macrometa.io"


  # Variables - DB
  email = "guest@macrometa.io"
  password = "guest"
  geo_fabric = "_system"
  collection_transit = "transit"
  collection_shops = "shops"

  # Variable - Requests locations

  latitude2 = 37.3972452334285 # Sunnyvale Elementary School
  longitude2 = -121.99073796514953 # Sunnyvale Elementary School

  # Variables - Data
  shops_data = [
    { "shop": "Walgreens", "address": "San Jose, CA", "coordinate": [ 37.2333253, -121.6846349 ] },
    { "shop": "Costco", "address": "San Jose, CA", "coordinate": [ 37.4282724, -121.9066238 ] },
    { "shop":"Walmart", "address": "San Jose, CA", "coordinate": [ 37.3361905, -121.8905833 ] },
    { "shop": "Bed Bath & Beyond", "address": "Mountain View, CA", "coordinate": [ 37.4443293, -122.1598465] },
    { "shop":"Best Buy", "address": "Mountain View, CA", "coordinate": [ 37.35992431640625,-122.06830596923828 ] },
    { "shop": "Target", "address": "Mountain View, CA", "coordinate": [ 37.4443293, -122.1598465] },
    { "shop": "Walgreens", "address": "Fremont, CA", "coordinate": [ 37.48849288005677, -121.94342916254486 ] },
    { "shop": "Costco", "address": "Almeda, CA", "coordinate": [ 37.766039418486855, -122.2430211806723 ] },
    { "shop": "Sweet Greens", "address": "San Francisco, CA", "coordinate": [ 38.621725, -92.571271 ] }
  ]

  transit_data = [
    { "bus": "CA123", "stop": "Santa Clara, CA", "coordinate": [ 37.2333253, -121.6846349 ] },
    { "bus": "CA233", "stop": "Milpitas, CA", "coordinate": [ 37.4282724, -121.9066238 ] },
    { "bus": "CA433", "stop": "San Jose, CA", "coordinate": [ 37.3361905, -121.8905833 ] },
    { "bus": "CA323", "stop": "Palo Alto, CA", "coordinate": [ 37.4443293, -122.1598465] },
    { "bus": "CA523", "stop": "Mountain View, CA", "coordinate": [ 37.35992431640625,-122.06830596923828 ] },
    { "bus": "CA143", "stop": "Fremont, CA", "coordinate": [ 37.48849288005677, -121.94342916254486 ] },
    { "bus": "CA423", "stop": "Almeda, CA", "coordinate": [ 37.766039418486855, -122.2430211806723 ] },
    { "bus": "CA129", "stop": "San Francisco, CA", "coordinate": [ 38.621725, -92.571271 ] }
  ]

  pp = pprint.PrettyPrinter(indent=4)

  # Step1: Open connection to GDN. You will be routed to closest region.
  print("\n1. CONNECT: federation: {},  user: {}".format(global_url, email))
  client = C8Client(protocol='https', host=global_url, port=443)
  tenant = client.tenant(email, password)
  fabric = tenant.useFabric(geo_fabric)

  # Step2: Create a collection & geoindex if not exists
  print("\n2. CREATE_COLLECTION: region: {},  collection: {}".format(global_url, collection_shops))
  if fabric.has_collection(collection_shops):
      shopCol = fabric.collection(collection_shops)
  else:
      shopCol = fabric.create_collection(collection_shops)
      shopCol.add_geo_index(fields=["coordinate"], ordered=False)

  # Step3: Insert data into collection.
  print("\n3. INSERT_SHOP_DATA: in region: {}".format(global_url))
  shopCol.insert_many(shops_data)

 # Step3a: Find shops closer to given location
  lat1 = 37.43007055731992 # McCarthy Blvd, Milpitas
  long1 = -121.92344167914754 # McCarthy Blvd, Milpitas
  radius = 10 * 1000 # meters
  print("\n3a. FIND_NEAR_BY_SHOPS for request: ({}, {})".format(lat1, long1))
  within_query = "FOR loc IN WITHIN ({}, {}, {}, {}) SORT loc._distance ASC RETURN loc".format(collection_shops, lat1, long1, radius)
  cursor = fabric.c8ql.execute(within_query)
  docs = [document for document in cursor]
  pp.pprint(docs)

 # Step3b: Find shop closest to given location
  print("\n3b. FIND_NEAREST_SHOP for request: ({}, {})".format(lat1, long1))
  near_query = "FOR loc IN NEAR ({}, {}, {}, 1) RETURN loc".format(collection_shops, lat1, long1)
  cursor = fabric.c8ql.execute(near_query)
  docs = [document for document in cursor]
  pp.pprint(docs)

 #-------------------------------------------------------------------#

  # Step2: Create a collection & geoindex if not exists
  print("\n4. CREATE_COLLECTION: region: {},  collection: {}".format(global_url, collection_transit))
  if fabric.has_collection(collection_transit):
      transitCol = fabric.collection(collection_transit)
  else:
      transitCol = fabric.create_collection(collection_transit)
      transitCol.add_geo_index(fields=["coordinate"], ordered=False)

  # Step5: Insert data into collection.
  print("\n5. INSERT_TRANSIT_DATA: in region: {}".format(global_url))
  transitCol.insert_many(transit_data)

 # Step6a: Find buses currently within given rectangular fence
  lat1 = 37.38905593900322 
  long1 = -122.14426630984782 
  lat2 = 37.332401582858324 
  long2 = -121.80235913612003 

  print("\n6a. FIND_BUSES available within RECTANGULAR fence: ({}, {}, {}, {}) sorted by distance".format(lat1, long1, lat2, long2))
  within_query = "FOR loc IN WITHIN_RECTANGLE ({}, {}, {}, {}, {}) SORT loc._distance ASC RETURN loc".format(collection_transit, lat1, long1, lat2, long2)
  cursor = fabric.c8ql.execute(within_query)
  docs = [document for document in cursor]
  pp.pprint(docs)

 # Step6b: Find shop closest to given location
  print("\n6b. FIND_NEAREST_BUS for given location: ({}, {})".format(lat1, long1))
  near_query = "FOR loc IN NEAR ({}, {}, {}, 1) RETURN loc".format(collection_transit, lat1, long1)
  cursor = fabric.c8ql.execute(near_query)
  docs = [document for document in cursor]
  pp.pprint(docs)

 #-------------------------------------------------------------------#

  # # Step7: Delete Data
  print("\n7. DELETE_DATA: region: {}, collections: {}, {}".format(global_url, collection_shops, collection_transit))
  shopCol.truncate()
  transitCol.truncate()
  # # fabric.delete_collection(collection_name)
'use strict'

const jsc8 = require('jsc8')

// Variables - DB
const global_url = "https://gdn1.macrometa.io"
const client = new jsc8(global_url)
const guest_password = "guest"
const geo_fabric = "_system"
const guest_email = "guest@macrometa.io"
const collection_shops = "shops"
const collection_transit = "transit"

let shops = null
let transit = null

// Variable - Requests locations
const latitude2 = 37.3972452334285 // Sunnyvale Elementary School
const longitude2 = -121.99073796514953 // Sunnyvale Elementary School

// Variables - Data
const shops_data = [
  { "shop": "Walgreens", "address": "San Jose, CA", "coordinate": [37.2333253, -121.6846349 ] },
  { "shop": "Costco", "address": "San Jose, CA", "coordinate": [ 37.4282724,-121.9066238 ] },
  { "shop":"Walmart", "address": "San Jose, CA", "coordinate": [ 37.3361905,-121.8905833 ] },
  { "shop": "Bed Bath & Beyond", "address": "Mountain View, CA","coordinate": [ 37.4443293, -122.1598465] },
  { "shop":"Best Buy", "address": "Mountain View, CA", "coordinate": [37.35992431640625,-122.06830596923828 ] },
  { "shop": "Target", "address": "Mountain View, CA", "coordinate": [37.4443293, -122.1598465] },
  { "shop": "Walgreens", "address": "Fremont, CA", "coordinate": [37.48849288005677, -121.94342916254486 ] },
  { "shop": "Costco", "address": "Almeda, CA", "coordinate": [37.766039418486855, -122.2430211806723 ] },
  { "shop": "Sweet Greens", "address": "San Francisco, CA", "coordinate": [38.621725, -92.571271 ] }
  ]

const transit_data = [
  { "bus": "CA123", "stop": "Santa Clara, CA", "coordinate": [ 37.2333253,-121.6846349 ] },
  { "bus": "CA233", "stop": "Milpitas, CA", "coordinate": [ 37.4282724,-121.9066238 ] },
  { "bus": "CA433", "stop": "San Jose, CA", "coordinate": [ 37.3361905,-121.8905833 ] },
  { "bus": "CA323", "stop": "Palo Alto, CA", "coordinate": [ 37.4443293,-122.1598465] },
  { "bus": "CA523", "stop": "Mountain View, CA", "coordinate": [37.35992431640625,-122.06830596923828 ] },
  { "bus": "CA143", "stop": "Fremont, CA", "coordinate": [ 37.48849288005677 -121.94342916254486 ] },
  { "bus": "CA423", "stop": "Almeda, CA", "coordinate": [ 37.766039418486855 -122.2430211806723 ] },
  { "bus": "CA129", "stop": "San Francisco, CA", "coordinate": [ 38.621725,-92.571271 ] }
  ]

async function login(){
  console.log(`\n 1. CONNECT: federation: ${global_url}`);
  await client.login(guest_email, guest_password);
  await client.useFabric(geo_fabric);
}

async function createCollection() {
  console.log("\n 2. CREATE_COLLECTIONS")

  try{
     console.log("Creating the collection shops...");
      shops = client.collection(collection_shops)
      let exists_shops = await shops.exists()
      if (exists_shops === false) {
            await shops.create()
            await shops.createGeoIndex(['coordinate'],{geoJson : false});

        }

      console.log("Creating the collection transit...");
      transit = client.collection(collection_transit)
      let exists_transit = await transit.exists()
      if (exists_transit === false) {
            await transit.create()
            await transit.createGeoIndex(['coordinate'],{geoJson : false});
        }
      }
    catch (e) {
    await console.log("Collection creation did not succeed due to " + e)
    }
}

async function insertData(shops_data, transit_data) {
  console.log(`\n 3a. INSERT_SHOP_DATA in region ${global_url}`)
  await shops.save(shops_data)
  console.log(`\n 3b. INSERT_TRANSIT_DATA in region ${global_url}`)
  await transit.save(transit_data)
  shops.closeOnChangeConnection()
  transit.closeOnChangeConnection()
}

async function deleteData(){
  console.log("\n 5. DELETE_DATA")
  await shops.truncate()
  await transit.truncate()
}

async function findData(){
  console.log("\n 4. FIND_DATA")

  // Find shops closer to given location
  let lat1 = 37.43007055731992 // McCarthy Blvd, Milpitas
  let long1 = -121.92344167914754 // McCarthy Blvd, Milpitas
  let radius = 10 * 1000 // meters
  console.log(`\n 4a. FIND_NEAR_BY_SHOPS for request: (${lat1}, ${long1})`)
  let within_query = `FOR loc IN WITHIN (${collection_shops}, ${lat1}, ${long1}, ${radius
  }) SORT loc._distance ASC RETURN loc`
  let cursor = await client.query(within_query);
  let result = await cursor.all()
  console.log(result)

  // Find shop closest to given location
  console.log(`\n 4b. FIND_NEAREST_SHOP for request: (${lat1}, ${long1})`)
  let near_query = `FOR loc IN NEAR (${collection_shops}, ${lat1}, ${long1}, 1) RETURN loc`
  cursor = await client.query(near_query);
  result = await cursor.all()
  console.log(result)

  // Find buses currently within given rectangular fence
  lat1 = 37.38905593900322 
  long1 = -122.14426630984782 
  let lat2 = 37.332401582858324 
  let long2 = -121.80235913612003 

  console.log(`\n 4c. FIND_BUSES available within RECTANGULAR fence: (${lat1}, ${long1}, ${lat2}, ${long2}) sorted by distance`)

  within_query = `FOR loc IN WITHIN_RECTANGLE (${collection_transit}, ${lat1}, ${long1}, ${lat2}, ${long2}) SORT loc._distance ASC RETURN loc`
  cursor = await client.query(within_query);
  result = await cursor.all()
  console.log(result)  

 // Find Bus closest to given location
  console.log(`\n 4d. FIND_NEAREST_BUS for given location: (${lat1}, ${long1})`)
  near_query = `FOR loc IN NEAR (${collection_transit}, ${lat1}, ${long1}, 1) RETURN loc`
  cursor = await client.query(near_query);
  result = await cursor.all()
  console.log(result) 
}

(async function() {
  await login();
  await createCollection();
  await insertData(shops_data, transit_data);
  await findData();
  await deleteData();
})();
Top