# API version 4 (or API_v4)
We will show the query API_v4 for Nanocubes using the crime50k example.
In order to create such a nanocube and serve it via http, we
run the following script
```shell
#
# (0) go the the $NANOCUBE/data folder
#
# (1) create the nanocube index file 'crime50k.nanocube'
#
nanocube create <(gunzip -c crime50k.csv.gz) crime50k.map crime50k.nanocube -header
#
# (2) serve the index via http on port 51234 using the alias 'crimes'
#
nanocube serve 51234 crimes=crime50k.nanocube
```
## schema
To serve the schemas of all the Nanocube indices being served in port 51234 of
localhost we send a GET request to:
```url
http://localhost:51234/schema()
```
Note that in our case we only have one Nanocube index being served for the
crime50k example. The result of the request above is a `json` array with
one entry: the schema of the crimes index:
```json
[
{
"type":"schema",
"name":"crimes",
"index_dimensions":[
{
"index":0,
"name":"location",
"bits_per_level":2,
"num_levels":25,
"hint":"spatial",
"aliases":{
}
},
{
"index":1,
"name":"type",
"bits_per_level":8,
"num_levels":1,
"hint":"categorical",
"aliases":{
"11":"CRIMINAL TRESPASS",
"8":"ROBBERY",
"24":"NON-CRIMINAL",
"27":"OBSCENITY",
"30":"NON-CRIMINAL (SUBJECT SPECIFIED)",
"3":"BATTERY",
"26":"GAMBLING",
"23":"INTIMIDATION",
"2":"THEFT",
"4":"BURGLARY",
"17":"LIQUOR LAW VIOLATION",
"29":"CONCEALED CARRY LICENSE VIOLATION",
"21":"PROSTITUTION",
"16":"CRIM SEXUAL ASSAULT",
"12":"WEAPONS VIOLATION",
"20":"SEX OFFENSE",
"7":"DECEPTIVE PRACTICE",
"10":"OTHER OFFENSE",
"25":"PUBLIC INDECENCY",
"14":"PUBLIC PEACE VIOLATION",
"15":"INTERFERENCE WITH PUBLIC OFFICER",
"22":"ARSON",
"1":"CRIMINAL DAMAGE",
"13":"KIDNAPPING",
"5":"MOTOR VEHICLE THEFT",
"0":"NARCOTICS",
"18":"HOMICIDE",
"9":"ASSAULT",
"28":"OTHER NARCOTIC VIOLATION",
"6":"OFFENSE INVOLVING CHILDREN",
"19":"STALKING"
}
},
{
"index":2,
"name":"time",
"bits_per_level":1,
"num_levels":16,
"hint":"temporal|2013-12-01T06:00:00Z_3600s",
"aliases":{
}
}
],
"measure_dimensions":[
{
"order":1,
"name":"count",
"type":"u32"
}
]
}
]
```
## total
In order to get the total number of crimes indexed in `crimes` we
send the query `q(crimes)`:
```url
http://localhost:51234/q(crimes)
```
The total is 50k, since we indexed 50k records and the `value` measure
we defined in `crime50k.map` is simply a count of records.
```json
[
{
"type":"table",
"numrows":1,
"index_columns":[
],
"measure_columns":[
{
"name":"count",
"values":[
50000.000000
]
}
]
}
]
```
## location
The quadtree convention we use is the following:
```
0 bottom-left quadrant (in the first split of the mercator projection contains South-America)
1 bottom-right quadrant (in the first split of the mercator projection contains Africa and South Asia)
2 top-left quadrant (in the first split of the mercator projection contains North America)
3 top-right quadrant (in the first split of the mercator projection contains Europe and North Asia)
```
If we want to count the number of crimes in a 256x256 quadtree-aligned grid
of the sub-cell (top-left, bottom-right, top-left) or (2,1,2), we run the query
below. Note that the cell (2,1,2) contains Chicago.
```
http://localhost:51234/q(crimes.b('location',dive(p(2,1,2),8)))
```
The result is
```json
[
{
"type":"table",
"numrows":8,
"index_columns":[
{
"name":"location",
"hint":"none",
"values_per_row":11,
"values":[
2,1,2,0,0,0,0,1,2,3,3,2,1,2,0,0,0,0,1,3,0,2,2,1,2,0,0,0,0,1,3,0,3,2,1,2,0,0,0,0,1,3,1,2,2,1,2,0,0,0,0,1,3,2,0,2,1,2,0,0,0,0,1,3,2,1,2,1,2,0,0,0,0,1,3,2,2,2,1,2,0,0,0,0,1,3,2,3
]
}
],
"measure_columns":[
{
"name":"count",
"values":[
272.000000,416.000000,12268.000000,224.000000,6838.000000,16913.000000,5460.000000,7609.000000
]
}
]
}
]
```
Note that the way the resulting grid cells are described are as paths. Since we
subdivided the cell (2,1,2) at depth 3 more 8 times (the depth of the dive), we
get that each grid cell is described by a path of 11 subdivisions. So the way
to read the result above is to split location 'values' array at every 11-th entry.
The final correspondence can also be better seen by generating the above resul in
text format.
```
http://localhost:51234/format('text');q(crimes.b('location',dive(p(2,1,2),8)))
```
which yields the following text
```
location count
2,1,2,0,0,0,0,1,2,3,3 272.000000
2,1,2,0,0,0,0,1,3,0,2 416.000000
2,1,2,0,0,0,0,1,3,0,3 12268.000000
2,1,2,0,0,0,0,1,3,1,2 224.000000
2,1,2,0,0,0,0,1,3,2,0 6838.000000
2,1,2,0,0,0,0,1,3,2,1 16913.000000
2,1,2,0,0,0,0,1,3,2,2 5460.000000
2,1,2,0,0,0,0,1,3,2,3 7609.000000
```
If instead of the path we just want the local (x,y) coordinate of the 256x256 grid,
we can use the hint `'img8'` as the last parameter of the binding `.b(...)`.
```
http://localhost:51234/format('text');q(crimes.b('location',dive(p(2,1,2),8),'img8'))
```
We now get coordinates `x` and `y` both in {0,1,...,255}
```
location count
11,7 272.000000
12,5 416.000000
13,5 12268.000000
14,5 224.000000
12,6 6838.000000
13,6 16913.000000
12,7 5460.000000
13,7 7609.000000
```
if we want the global coord of the grid we generated we can use the hint `'img11'`:
```
http://localhost:51234/format('text');q(crimes.b('location',dive(p(2,1,2),8),'img11'))
```
We now get coordinates `x` and `y` both in {0,1,...,2047}. Note that the `y`
coordinate of the cells grow bottom-up, Chicago is above the Equator and
{1285,1286,1287} are in the upper half of 2048 or 2^11.
```
location count
523,1287 272.000000
524,1285 416.000000
525,1285 12268.000000
526,1285 224.000000
524,1286 6838.000000
525,1286 16913.000000
524,1287 5460.000000
525,1287 7609.000000
```
A path on a quadtree can also be specified using `tile2d(z,x,y)` or `img2d(z,x,y)`.
The path `p(2,1,2)` is equivalent to `tile2d(3,2,5)` where the y coordinate grows
bottom-up, or `img2d(3,2,2)` where the y coordinate grows top down (like the standard
slippy tiles on open street maps or the conventional pixel coordinates in an image).
```
Quadtree path entry convention:
2