Skip to content

Instantly share code, notes, and snippets.

@datadavev
Created August 4, 2021 18:43
Show Gist options
  • Save datadavev/1741a78c88e7f3345a202190633cb022 to your computer and use it in GitHub Desktop.
Save datadavev/1741a78c88e7f3345a202190633cb022 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Dependencies:\n",
"\n",
"To run this notebook, pip install these in a virtual environment:\n",
"\n",
"- jupyter\n",
"- shapely\n",
"- requests\n",
"- jupyterlab-geojson\n",
"- ipyleaflet\n",
"\n",
"## Solr setup:\n",
"\n",
"Add the JTS jar. on my Max it went into: `/usr/local/Cellar/solr/8.9.0/server/solr-webapp/webapp/WEB-INF/lib`\n",
"\n",
"The examples here are using a collection called \"geo_test\". On my Mac, the solr config sets are located in `/usr/local/Cellar/solr/8.9.0/server/solr/configsets` In there, copy the `_default` config set to a new one called `spatial` that is used for testing here.\n",
"\n",
"Edit `spatial/conf/managed-schema` and ensure these exist therein:\n",
"```xml\n",
" <!--\n",
" LatLonPointSpatialField\n",
" https://solr.apache.org/guide/8_9/spatial-search.html#bboxfield\n",
" --> \n",
" <dynamicField name=\"*_ll\" type=\"location\" indexed=\"true\" stored=\"true\" />\n",
" <!-- \n",
" Bounding Box \n",
" https://solr.apache.org/guide/8_9/spatial-search.html#bboxfield\n",
" -->\n",
" <dynamicField name=\"*_bb\" type=\"bbox\" />\n",
" <!--\n",
" RptWithGeometryySpatialField\n",
" https://solr.apache.org/guide/8_9/spatial-search.html#rptwithgeometryspatialfield\n",
" -->\n",
" <dynamicField name=\"*_rpt\" type=\"location_rpt\" indexed=\"true\" stored=\"true\" multiValued=\"true\"/>\n",
"\n",
" <fieldType name=\"location\" class=\"solr.LatLonPointSpatialField\" docValues=\"true\"/>\n",
"\n",
" <fieldType name=\"bbox\" class=\"solr.BBoxField\"\n",
" geo=\"true\" distanceUnits=\"kilometers\" numberType=\"pdouble\" />\n",
"\n",
" <fieldType name=\"location_rpt\" class=\"solr.SpatialRecursivePrefixTreeFieldType\"\n",
" spatialContextFactory=\"JTS\"\n",
" geo=\"true\" \n",
" autoIndex=\"true\" \n",
" />\n",
"\n",
"```\n",
"\n",
"A collection using the `spatial` config set can be created / deleted from the command line, e.g.:\n",
"```\n",
"solr delete -c geo_test\n",
"brew services restart solr\n",
"solr create -d spatial -c geo_test\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"import json\n",
"import logging\n",
"import shapely.wkt\n",
"import shapely.geometry\n",
"from IPython.display import GeoJSON\n",
"\n",
"logging.basicConfig(level=logging.DEBUG)\n",
"\n",
"DEFAULT_COLLECTION = \"geo_test\"\n",
"BASE_URL = f\"http://localhost:8983/solr/{DEFAULT_COLLECTION}\"\n",
"\n",
"def sendJson(doc, collection=DEFAULT_COLLECTION):\n",
" '''Sends a single JSON document to solr for indexing\n",
"\n",
" Args:\n",
" doc: dict, to be serialized as JSON\n",
" '''\n",
" headers = {\"Content-type\": \"application/json\"}\n",
" params = {\"commit\":\"true\"}\n",
" # This endpoint is a somewhat undocumented mechanism to send \n",
" # JSON documents to the Solr update engine\n",
" url = f\"{BASE_URL}/update/json/docs\"\n",
" data = json.dumps(doc)\n",
" res = requests.post(url, params=params, headers=headers, data=data)\n",
" logging.debug(res.status_code)\n",
" logging.debug(res.text)\n",
"\n",
"\n",
"def solrGet(_id):\n",
" \"\"\"\n",
" Get document by id using Solr realtime get.\n",
"\n",
" Args:\n",
" _id: str, Document identifier \n",
" \"\"\"\n",
" headers = {\"Accept\": \"application/json\"}\n",
" params = {\"id\":_id, \"wt\":\"json\"}\n",
" url = f\"{BASE_URL}/get\"\n",
" return requests.get(url, headers=headers, params=params).json()\n",
"\n",
"\n",
"def solrDelete(_id=None):\n",
" \"\"\"\n",
" Delete documents from Solr\n",
"\n",
" Args:\n",
" _id: str, if set then delete specific document, otherwise delete everything\n",
" \"\"\"\n",
" headers = {\"Accept\": \"application/json\", \"Content-type\":\"application/json\"}\n",
" params = {\"commit\":\"true\"}\n",
" body = json.dumps({\"delete\":{\"id\":_id}})\n",
" if _id is None:\n",
" body = json.dumps({\"delete\":{\"query\":\"*:*\"}})\n",
" url = f\"{BASE_URL}/update\"\n",
" res = requests.post(url, headers=headers, params=params, data=body)\n",
" logging.debug(res.text)\n",
"\n",
"\n",
"def getGeoJSON(q, fl=\"*\", field=\"loc_geo\"):\n",
" '''Solr GeoJSON writer only appears to work with RPT using JTS.\n",
"\n",
" This method generalizes the op to work with other field types\n",
" '''\n",
" headers = {\"Accept\":\"application/json\"}\n",
" params = {\n",
" \"q\":q,\n",
" \"rows\":9999,\n",
" \"fl\": fl,\n",
" \"wt\":\"geojson\",\n",
" \"geojson.field\":field,\n",
" }\n",
" url = f\"{BASE_URL}/select\"\n",
" res = requests.get(url, headers=headers, params=params).json()\n",
" return res[\"response\"]\n",
"\n",
"def WKTtoGeoJson(ws:str):\n",
" g = shapely.wkt.loads(ws)\n",
" return shapely.geometry.mapping(g)\n",
"\n",
"def getGeoJSON2(q, fl=\"*\", field=\"loc_geo\"):\n",
" '''Construct GeoJSON from Solr JSON response. \n",
" \n",
" This works for field types other that RPT with JTS which don't \n",
" seem to return correct geojson.\n",
" '''\n",
" headers = {\"Accept\":\"application/json\"}\n",
" params = {\n",
" \"q\": q,\n",
" \"rows\": 9999,\n",
" \"fl\": fl,\n",
" \"wt\": \"json\"\n",
" }\n",
" url = f\"{BASE_URL}/select\"\n",
" res = requests.get(url, headers=headers, params=params).json()\n",
" response = res.get(\"response\", {})\n",
" geo_json = {\n",
" \"type\":\"FeatureCollection\",\n",
" \"numFound\": response[\"numFound\"],\n",
" \"start\": response[\"start\"],\n",
" \"numFoundExact\": response[\"numFoundExact\"],\n",
" \"features\":[]\n",
" }\n",
" for doc in response.get(\"docs\", []):\n",
" gj = WKTtoGeoJson(doc.get(field, None))\n",
" if not gj is None:\n",
" feat = {\"type\":\"Feature\", \"geometry\":gj, \"properties\":{}}\n",
" for k,v in doc.items():\n",
" if k != field:\n",
" feat[\"properties\"][k] = v\n",
" geo_json[\"features\"].append(feat)\n",
" return geo_json\n",
"\n",
"\n",
"def geoJsonToWKT(gj):\n",
" if gj.get(\"type\") == \"FeatureCollection\":\n",
" res = []\n",
" for feature in gj.get(\"features\", {}):\n",
" wkt = geoJsonToWKT(feature)\n",
" if wkt is not None:\n",
" res.append(wkt)\n",
" return res\n",
" if gj.get(\"type\") == \"Feature\":\n",
" gw = shapely.geometry.shape(gj.get(\"geometry\", {}))\n",
" return gw.wkt\n",
" return None\n",
"\n",
"\n",
"def shapelyToSolr(shape):\n",
" centroid = shape.centroid\n",
" bb = shape.bounds\n",
" res = {\n",
" \"loc_ll\": f\"{centroid.y},{centroid.x}\",\n",
" \"loc_bb\":f\"ENVELOPE({bb[0]}, {bb[2]}, {bb[3]}, {bb[1]})\",\n",
" \"loc_rpt\": shape.wkt\n",
" }\n",
" return res\n",
"\n",
"\n",
"def geoJsonToSolr(gj):\n",
" '''Given a GeoJSON object, compute the Solr index properties:\n",
" - centroid\n",
" - bounding box\n",
" - geometry\n",
" '''\n",
" gg = gj\n",
" #TODO: combine multiple shapes in shapely\n",
" if gj.get(\"type\") == \"FeatureCollection\":\n",
" feats = gj.get(\"features\",[])\n",
" gg = feats[0].get(\"geometry\", {})\n",
" shape = shapely.geometry.shape(gg)\n",
" return shapelyToSolr(shape)\n",
"\n",
"\n",
"def WKTtoSolr(wkt):\n",
" '''Generate the Solr index fields given a WKT string\n",
" '''\n",
" shape = shapely.wkt.loads(wkt)\n",
" return shapelyToSolr(shape)\n",
"\n",
"\n",
"def latitudeLongitudeToSolr(lat, lon):\n",
" '''Generate Solr index field values given latitude and longitude \n",
" '''\n",
" return shapelyToSolr(shapely.geometry.Point(lon, lat))\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"POST /solr/geo_test/update?commit=true HTTP/1.1\" 200 68\n",
"DEBUG:root:{\n",
" \"responseHeader\":{\n",
" \"rf\":1,\n",
" \"status\":0,\n",
" \"QTime\":84}}\n",
"\n"
]
}
],
"source": [
"# clear the index\n",
"solrDelete()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"POST /solr/geo_test/update/json/docs?commit=true HTTP/1.1\" 200 69\n",
"DEBUG:root:200\n",
"DEBUG:root:{\n",
" \"responseHeader\":{\n",
" \"rf\":1,\n",
" \"status\":0,\n",
" \"QTime\":107}}\n",
"\n"
]
}
],
"source": [
"# create a record with a single point\n",
"record = latitudeLongitudeToSolr(-5,-45)\n",
"record[\"id\"] = \"g0\"\n",
"sendJson(record)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"POST /solr/geo_test/update/json/docs?commit=true HTTP/1.1\" 200 69\n",
"DEBUG:root:200\n",
"DEBUG:root:{\n",
" \"responseHeader\":{\n",
" \"rf\":1,\n",
" \"status\":0,\n",
" \"QTime\":128}}\n",
"\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\"loc_ll\": \"36.27428708808831,33.082677294282036\", \"loc_bb\": \"ENVELOPE(29.487304687499996, 36.826171875, 39.740986355883564, 34.161818161230386)\", \"loc_rpt\": \"LINESTRING (31.81640625 39.74098635588356, 29.4873046875 36.87962060502676, 31.552734375 34.16181816123039, 36.298828125 35.13787911963419, 36.826171875 37.68382032669382, 36.5625 38.92522904714054)\", \"id\": \"g1\"}\n"
]
}
],
"source": [
"# Add a linestring to solr\n",
"geo = {\n",
" \"type\": \"FeatureCollection\",\n",
" \"features\": [\n",
" {\n",
" \"type\": \"Feature\",\n",
" \"properties\": {},\n",
" \"geometry\": {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [\n",
" 31.81640625,\n",
" 39.740986355883564\n",
" ],\n",
" [\n",
" 29.487304687499996,\n",
" 36.87962060502676\n",
" ],\n",
" [\n",
" 31.552734374999996,\n",
" 34.161818161230386\n",
" ],\n",
" [\n",
" 36.298828125,\n",
" 35.137879119634185\n",
" ],\n",
" [\n",
" 36.826171875,\n",
" 37.68382032669382\n",
" ],\n",
" [\n",
" 36.5625,\n",
" 38.92522904714054\n",
" ]\n",
" ]\n",
" }\n",
" }\n",
" ]\n",
"}\n",
"\n",
"record = geoJsonToSolr(geo)\n",
"record[\"id\"] = \"g1\"\n",
"print(json.dumps(record))\n",
"sendJson(record)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"POST /solr/geo_test/update/json/docs?commit=true HTTP/1.1\" 200 69\n",
"DEBUG:root:200\n",
"DEBUG:root:{\n",
" \"responseHeader\":{\n",
" \"rf\":1,\n",
" \"status\":0,\n",
" \"QTime\":107}}\n",
"\n"
]
}
],
"source": [
"# Add a bundle of things in WKT string\n",
"record = WKTtoSolr(\"GEOMETRYCOLLECTION (POINT (40 10), LINESTRING (10 10, 20 20, 10 40), POLYGON ((40 40, 20 45, 45 30, 40 40)))\")\n",
"record[\"id\"] = \"g2\"\n",
"sendJson(record)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dump GEOJson for the records stored so far:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"GET /solr/geo_test/select?q=%2A%3A%2A&rows=9999&fl=%2A&wt=geojson&geojson.field=loc_rpt HTTP/1.1\" 200 1909\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\n",
" \"type\": \"FeatureCollection\",\n",
" \"numFound\": 3,\n",
" \"start\": 0,\n",
" \"numFoundExact\": true,\n",
" \"features\": [\n",
" {\n",
" \"type\": \"Feature\",\n",
" \"geometry\": {\n",
" \"type\": \"Point\",\n",
" \"coordinates\": [\n",
" -45,\n",
" -5\n",
" ]\n",
" },\n",
" \"properties\": {\n",
" \"loc_ll\": \"-5.0,-45.0\",\n",
" \"loc_bb\": \"ENVELOPE(-45.0, -45.0, -5.0, -5.0)\",\n",
" \"id\": \"g0\",\n",
" \"loc_bb__minY\": -5.0,\n",
" \"loc_bb__minX\": -45.0,\n",
" \"loc_bb__maxY\": -5.0,\n",
" \"loc_bb__maxX\": -45.0,\n",
" \"_version_\": 1707188922527776768\n",
" }\n",
" },\n",
" {\n",
" \"type\": \"Feature\",\n",
" \"geometry\": {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [\n",
" 31.816406,\n",
" 39.740986\n",
" ],\n",
" [\n",
" 29.487305,\n",
" 36.879621\n",
" ],\n",
" [\n",
" 31.552734,\n",
" 34.161818\n",
" ],\n",
" [\n",
" 36.298828,\n",
" 35.137879\n",
" ],\n",
" [\n",
" 36.826172,\n",
" 37.68382\n",
" ],\n",
" [\n",
" 36.5625,\n",
" 38.925229\n",
" ]\n",
" ]\n",
" },\n",
" \"properties\": {\n",
" \"loc_ll\": \"36.27428708808831,33.082677294282036\",\n",
" \"loc_bb\": \"ENVELOPE(29.487304687499996, 36.826171875, 39.740986355883564, 34.161818161230386)\",\n",
" \"id\": \"g1\",\n",
" \"loc_bb__minY\": 34.161818161230386,\n",
" \"loc_bb__minX\": 29.487304687499996,\n",
" \"loc_bb__maxY\": 39.740986355883564,\n",
" \"loc_bb__maxX\": 36.826171875,\n",
" \"_version_\": 1707188925299163136\n",
" }\n",
" },\n",
" {\n",
" \"type\": \"Feature\",\n",
" \"geometry\": {\n",
" \"type\": \"GeometryCollection\",\n",
" \"geometries\": [\n",
" {\n",
" \"type\": \"Point\",\n",
" \"coordinates\": [\n",
" 40,\n",
" 10\n",
" ]\n",
" },\n",
" {\n",
" \"type\": \"LineString\",\n",
" \"coordinates\": [\n",
" [\n",
" 10,\n",
" 10\n",
" ],\n",
" [\n",
" 20,\n",
" 20\n",
" ],\n",
" [\n",
" 10,\n",
" 40\n",
" ]\n",
" ]\n",
" },\n",
" {\n",
" \"type\": \"Polygon\",\n",
" \"coordinates\": [\n",
" [\n",
" [\n",
" 40,\n",
" 40\n",
" ],\n",
" [\n",
" 20,\n",
" 45\n",
" ],\n",
" [\n",
" 45,\n",
" 30\n",
" ],\n",
" [\n",
" 40,\n",
" 40\n",
" ]\n",
" ]\n",
" ]\n",
" }\n",
" ]\n",
" },\n",
" \"properties\": {\n",
" \"loc_ll\": \"38.33333333333333,35.0\",\n",
" \"loc_bb\": \"ENVELOPE(10.0, 45.0, 45.0, 10.0)\",\n",
" \"id\": \"g2\",\n",
" \"loc_bb__minY\": 10.0,\n",
" \"loc_bb__minX\": 10.0,\n",
" \"loc_bb__maxY\": 45.0,\n",
" \"loc_bb__maxX\": 45.0,\n",
" \"_version_\": 1707188929917091840\n",
" }\n",
" }\n",
" ]\n",
"}\n"
]
}
],
"source": [
"gj = getGeoJSON(\"*:*\", field=\"loc_rpt\")\n",
"print(json.dumps(gj, indent=2))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/geo+json": {
"features": [
{
"geometry": {
"coordinates": [
-45,
-5
],
"type": "Point"
},
"properties": {
"_version_": 1707188922527776800,
"id": "g0",
"loc_bb": "ENVELOPE(-45.0, -45.0, -5.0, -5.0)",
"loc_bb__maxX": -45,
"loc_bb__maxY": -5,
"loc_bb__minX": -45,
"loc_bb__minY": -5,
"loc_ll": "-5.0,-45.0"
},
"type": "Feature"
},
{
"geometry": {
"coordinates": [
[
31.816406,
39.740986
],
[
29.487305,
36.879621
],
[
31.552734,
34.161818
],
[
36.298828,
35.137879
],
[
36.826172,
37.68382
],
[
36.5625,
38.925229
]
],
"type": "LineString"
},
"properties": {
"_version_": 1707188925299163100,
"id": "g1",
"loc_bb": "ENVELOPE(29.487304687499996, 36.826171875, 39.740986355883564, 34.161818161230386)",
"loc_bb__maxX": 36.826171875,
"loc_bb__maxY": 39.740986355883564,
"loc_bb__minX": 29.487304687499996,
"loc_bb__minY": 34.161818161230386,
"loc_ll": "36.27428708808831,33.082677294282036"
},
"type": "Feature"
},
{
"geometry": {
"geometries": [
{
"coordinates": [
40,
10
],
"type": "Point"
},
{
"coordinates": [
[
10,
10
],
[
20,
20
],
[
10,
40
]
],
"type": "LineString"
},
{
"coordinates": [
[
[
40,
40
],
[
20,
45
],
[
45,
30
],
[
40,
40
]
]
],
"type": "Polygon"
}
],
"type": "GeometryCollection"
},
"properties": {
"_version_": 1707188929917091800,
"id": "g2",
"loc_bb": "ENVELOPE(10.0, 45.0, 45.0, 10.0)",
"loc_bb__maxX": 45,
"loc_bb__maxY": 45,
"loc_bb__minX": 10,
"loc_bb__minY": 10,
"loc_ll": "38.33333333333333,35.0"
},
"type": "Feature"
}
],
"numFound": 3,
"numFoundExact": true,
"start": 0,
"type": "FeatureCollection"
},
"text/plain": [
"<IPython.display.GeoJSON object>"
]
},
"metadata": {
"application/geo+json": {
"expanded": false,
"root": "root"
}
},
"output_type": "display_data"
}
],
"source": [
"# Show the shapes on a map using the simple GeoJSON viewer\n",
"GeoJSON(gj)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f34c8b1f1e86470185d52e46747bf7e4",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Map(center=[20.0, 5.3], controls=(ZoomControl(options=['position', 'zoom_in_text', 'zoom_in_title', 'zoom_out_…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# A more sophisticated viewer using Leaflet\n",
"\n",
"import random\n",
"import ipyleaflet\n",
"\n",
"def random_color(feature):\n",
" return {\n",
" 'color': 'black',\n",
" 'fillColor': random.choice(['red', 'yellow', 'green', 'orange']),\n",
" }\n",
"\n",
"m = ipyleaflet.Map(center=(20.0, 5.3), zoom=3)\n",
"geo_json = ipyleaflet.GeoJSON(\n",
" data=gj,\n",
" style={\n",
" 'opacity': 1, 'dashArray': '9', 'fillOpacity': 0.1, 'weight': 1\n",
" },\n",
" hover_style={\n",
" 'color': 'white', 'dashArray': '0', 'fillOpacity': 0.5\n",
" },\n",
" style_callback=random_color\n",
")\n",
"m.add_layer(geo_json)\n",
"\n",
"m"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Heatmaps\n",
"\n",
"Heatmaps provide a count of features overlapping grid squares. The values are presented in the `counts_ints2D` list of lists. \n",
"\n",
"The `gridLevel` property determines the number of rows and columns and is determined by interaction between the bounding box and the `distErr` property. Generally good to leave this `None`. For default RPT properties and global views, a max of 3 works otherwise an exception is thrown from too many cells."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): localhost:8983\n",
"DEBUG:urllib3.connectionpool:http://localhost:8983 \"GET /solr/geo_test/select?q=%2A%3A%2A&rows=0&wt=json&facet=true&facet.heatmap=loc_rpt&facet.heatmap.geom=%5B-180.0+-90.0+TO+180.0+90.0%5D&facet.heatmap.gridLevel=2 HTTP/1.1\" 200 5388\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\"responseHeader\": {\"zkConnected\": true, \"status\": 0, \"QTime\": 0, \"params\": {\"facet.heatmap.gridLevel\": \"2\", \"q\": \"*:*\", \"facet.heatmap\": \"loc_rpt\", \"facet.heatmap.geom\": \"[-180.0 -90.0 TO 180.0 90.0]\", \"rows\": \"0\", \"wt\": \"json\", \"facet\": \"true\"}}, \"response\": {\"numFound\": 3, \"start\": 0, \"numFoundExact\": true, \"docs\": []}, \"facet_counts\": {\"facet_queries\": {}, \"facet_fields\": {}, \"facet_ranges\": {}, \"facet_intervals\": {}, \"facet_heatmaps\": {\"loc_rpt\": {\"gridLevel\": 2, \"columns\": 32, \"rows\": 32, \"minX\": -180.0, \"maxX\": 180.0, \"minY\": -90.0, \"maxY\": 90.0, \"counts_ints2D\": [null, null, null, null, null, null, null, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], null, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]}}}}\n"
]
}
],
"source": [
"default_bb = {\n",
" \"minx\":-180.0,\n",
" \"miny\":-90.0,\n",
" \"maxx\": 180.0,\n",
" \"maxy\": 90.0\n",
"}\n",
"\n",
"def solrHeatmap(q, field, bb=default_bb, grid_level=None):\n",
" headers = {\"Accept\": \"application/json\"}\n",
" params = {\n",
" \"q\": q,\n",
" \"rows\":0,\n",
" \"wt\":\"json\",\n",
" \"facet\":\"true\",\n",
" \"facet.heatmap\": field,\n",
" \"facet.heatmap.geom\": f\"[{bb['minx']} {bb['miny']} TO {bb['maxx']} {bb['maxy']}]\"\n",
" }\n",
" if not grid_level is None:\n",
" params[\"facet.heatmap.gridLevel\"] = grid_level\n",
" url = f\"{BASE_URL}/select\"\n",
" res = requests.get(url, headers=headers, params=params).json()\n",
" return res\n",
"\n",
"print(json.dumps(solrHeatmap(\"*:*\", \"loc_rpt\", grid_level=2)))"
]
}
],
"metadata": {
"interpreter": {
"hash": "5f395b2d31c77b3803f4db4fdfaf006703467cc699cde2dbad7428ad23403050"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment