{"id":11312,"date":"2014-03-26T13:08:35","date_gmt":"2014-03-26T12:08:35","guid":{"rendered":"https:\/\/blog.trifork.com\/?p=11312"},"modified":"2014-03-26T13:08:35","modified_gmt":"2014-03-26T12:08:35","slug":"server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued","status":"publish","type":"post","link":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/","title":{"rendered":"Server-side clustering of geo-points on a map using Elasticsearch &#8211; continued"},"content":{"rendered":"<p>In a <a href=\"https:\/\/blog.trifork.com\/2013\/08\/01\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch\/\">previous post<\/a> I described a problem of data visualization and a possible solution provided by a plugin of elasticsearch. I noticed that elasticsearch might one day evolve to make the plugin unnecessary. That day seems to have come:&nbsp;starting from version 1.0.0, elasticsearch includes Aggregations,&nbsp;a new API for data mining. In this post I&#8217;ll show you how to use aggregations to reproduce the functionality of the plugin.<\/p>\n<p><!--more--><\/p>\n<p><span style=\"line-height: 1.5em\">Note: if you want to be sure to understand what follows, you&#8217;d better read the <a href=\"https:\/\/blog.trifork.com\/2013\/08\/01\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch\/\">original post<\/a> first. After reading, you will know:<\/span><\/p>\n<ul>\n<li>what exactly the problem of the &#8220;too many markers on a map&#8221; is;<\/li>\n<li>how you can use geohashes to solve the problem<\/li>\n<li>a solution for the elasticsearch ecosystem based on a plugin<\/li>\n<\/ul>\n<p>Elasticsearch aggregations, described <a href=\"http:\/\/www.elasticsearch.org\/guide\/en\/elasticsearch\/reference\/current\/search-aggregations.html\">here<\/a>, are a tool to extract aggregated (hence the name) information from a set of documents. It is similar to the GROUP BY clause and aggregate functions in SQL.<\/p>\n<p>The authors of the API also defined a very specific type of aggregation, <a href=\"http:\/\/www.elasticsearch.org\/guide\/en\/elasticsearch\/reference\/1.x\/search-aggregations-bucket-geohashgrid-aggregation.html\">geohash_grid<\/a>. It does something similar to what the plugin does: grouping documents with a location, according to the similarity of the respective geohash strings. All I&#8217;m going to do is to add a little functionality that is not offered by the plain geohash_grid aggregation, and which helps in displaying the documents on a map. This missing part is the average position of the documents belonging to the same bucket.<\/p>\n<p>In short, this will be a verbose post to show a small enhancement on a powerful feature of elasticsearch.<\/p>\n<p>Let&#8217;s proceed in order:<\/p>\n<p><strong>1. Filtering<\/strong><\/p>\n<p>Since we are processing the documents with the final purpose to show them on a map, it&#8217;s a good idea to filter out immediately the documents which fall outside the visible region of the map. and this is the first version of our query:<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">&lt;br&gt;\n{&lt;br&gt;\n    &quot;query&quot;: {&lt;br&gt;\n        &quot;match_all&quot;: {}&lt;br&gt;\n    },&lt;br&gt;\n    &quot;size&quot;: 0,&lt;br&gt;\n    &quot;aggs&quot;: {&lt;br&gt;\n        &quot;filtered_cells&quot;: {&lt;br&gt;\n            &quot;filter&quot;: {&lt;br&gt;\n                &quot;geo_bounding_box&quot;: {&lt;br&gt;\n                    &quot;location&quot;: {&lt;br&gt;\n                        &quot;top_left&quot;: &quot;50.1234, 4.0000&quot;,&lt;br&gt;\n                        &quot;bottom_right&quot;: &quot;52.1234, 4.5555&quot;&lt;br&gt;\n                    }&lt;br&gt;\n                }&lt;br&gt;\n            }&lt;br&gt;\n        }&lt;br&gt;\n    }&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p><strong><span style=\"line-height: 1.5em\">2. Aggregate by geohash<\/span><\/strong><\/p>\n<p>Now we want to use the geohash_grid to do the actual geohash based grouping, but in the context of the filter just defined: therefore, we declare the next aggregation as nested inside the &#8220;filtered_cells&#8221; aggregation.<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">&lt;br&gt;\n{&lt;br&gt;\n    &quot;query&quot;: {&lt;br&gt;\n        &quot;match_all&quot;: {}&lt;br&gt;\n    },&lt;br&gt;\n    &quot;size&quot;: 0, &quot;aggs&quot;: {&lt;br&gt;\n        &quot;filtered_cells&quot;: {&lt;br&gt;\n            &quot;filter&quot;: {&lt;br&gt;\n                &quot;geo_bounding_box&quot;: {&lt;br&gt;\n                    &quot;location&quot;: {&lt;br&gt;\n                        &quot;top_left&quot;: &quot;50.1234, 4.0000&quot;,&lt;br&gt;\n                        &quot;bottom_right&quot;: &quot;52.1234, 4.5555&quot;&lt;br&gt;\n                    }&lt;br&gt;\n                }&lt;br&gt;\n            },&lt;br&gt;\n            &quot;aggs&quot;: {&lt;br&gt;\n                &quot;cells&quot;: {&lt;br&gt;\n                    &quot;geohash_grid&quot;: {&lt;br&gt;\n                        &quot;field&quot;: &quot;location&quot;,&lt;br&gt;\n                        &quot;precision&quot;: 3&lt;br&gt;\n                    }&lt;br&gt;\n                }&lt;br&gt;\n            }&lt;br&gt;\n        }&lt;br&gt;\n    }&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>In this sample request, we want to group together all the documents which have a common 3-chars prefix in their geohash.<\/p>\n<p><strong>3. Add group centroid<\/strong><\/p>\n<p><em><strong>EDIT: <\/strong> the coming part makes use of dynamic scripting, a feature that is disabled by default starting from ES 1.2.0. In case you have that version or a more recent one, you will need to enable scripting by setting <code>script.disable_dynamic: false<\/code> in your <code>elasticsearch.yml<\/code> file.<br \/>\n<\/em><br \/>\nLast, since we need to eventually draw each bucket on a map, it&#8217;s a good idea to calculate the average coordinate of the documents included in the cluster. We might also position the marker at the center of the cell specified by the geohash, but this would result in all the markers being perfectly aligned in a grid, losing some visual information. The only way I could add this data was by further nesting 2 aggregations inside the &#8220;cells&#8221; aggregation, one to calculate the average value of the latitude and the other to do the same with longitude:<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">&lt;br&gt;\n{&lt;br&gt;\n    &quot;query&quot;: {&lt;br&gt;\n        &quot;match_all&quot;: {}&lt;br&gt;\n    },&lt;br&gt;\n    &quot;size&quot;: 0,&lt;br&gt;\n    &quot;aggs&quot;: {&lt;br&gt;\n        &quot;filtered_cells&quot;: {&lt;br&gt;\n            &quot;filter&quot;: {&lt;br&gt;\n                &quot;geo_bounding_box&quot;: {&lt;br&gt;\n                    &quot;location&quot;: {&lt;br&gt;\n                        &quot;top_left&quot;: &quot;50.1234, 4.0000&quot;,&lt;br&gt;\n                        &quot;bottom_right&quot;: &quot;52.1234, 4.5555&quot;&lt;br&gt;\n                    }&lt;br&gt;\n                }&lt;br&gt;\n            },&lt;br&gt;\n            &quot;aggs&quot;: {&lt;br&gt;\n                &quot;cells&quot;: {&lt;br&gt;\n                    &quot;geohash_grid&quot;: {&lt;br&gt;\n                        &quot;field&quot;: &quot;location&quot;,&lt;br&gt;\n                        &quot;precision&quot;: &quot;precision&quot;&lt;br&gt;\n                    },&lt;br&gt;\n                    &quot;aggs&quot;: {&lt;br&gt;\n                        &quot;center_lat&quot;: {&lt;br&gt;\n                            &quot;avg&quot;: {&lt;br&gt;\n                                &quot;script&quot;: &quot;doc&#x5B;'location'].lat&quot;&lt;br&gt;\n                            }&lt;br&gt;\n                        },&lt;br&gt;\n                        &quot;center_lon&quot;: {&lt;br&gt;\n                            &quot;avg&quot;: {&lt;br&gt;\n                                &quot;script&quot;: &quot;doc&#x5B;'location'].lon&quot;&lt;br&gt;\n                            }&lt;br&gt;\n                        }&lt;br&gt;\n                    }&lt;br&gt;\n                }&lt;br&gt;\n            }&lt;br&gt;\n        }&lt;br&gt;\n    }&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>You can see 2 aggregations, both nested inside &#8220;cells&#8221; and both of type <a href=\"http:\/\/www.elasticsearch.org\/guide\/en\/elasticsearch\/reference\/current\/search-aggregations-metrics-avg-aggregation.html#search-aggregations-metrics-avg-aggregation\">avg<\/a>. Each one calculates the average on values specified by a script, respectively, the latitude and longitude value of a document.<\/p>\n<p>The previous query will be answered with a JSON like below:<\/p>\n<p><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">&lt;br&gt;\n{&lt;br&gt;\n    ...&lt;br&gt;\n    &quot;aggregations&quot;: {&lt;br&gt;\n        &quot;filtered-cells&quot;: {&lt;br&gt;\n            &quot;cells&quot;: {&lt;br&gt;\n                &quot;buckets&quot;: &#x5B;&lt;br&gt;\n                    {&lt;br&gt;\n                        &quot;center_lat&quot;: {&lt;br&gt;\n                            &quot;value&quot;: 51.82441700086297&lt;br&gt;\n                        },&lt;br&gt;\n                        &quot;center_lon&quot;: {&lt;br&gt;\n                            &quot;value&quot;: 4.698991342820276&lt;br&gt;\n                        },&lt;br&gt;\n                        &quot;doc_count&quot;: 116950,&lt;br&gt;\n                        &quot;key&quot;: &quot;u15&quot;&lt;br&gt;\n                    },&lt;br&gt;\n                    {&lt;br&gt;\n                        &quot;center_lat&quot;: {&lt;br&gt;\n                            &quot;value&quot;: 52.47565999229339&lt;br&gt;\n                        },&lt;br&gt;\n                        &quot;center_lon&quot;: {&lt;br&gt;\n                            &quot;value&quot;: 4.977245411610905&lt;br&gt;\n                        },&lt;br&gt;\n                        &quot;doc_count&quot;: 46845,&lt;br&gt;\n                        &quot;key&quot;: &quot;u17&quot;&lt;br&gt;\n                    },&lt;br&gt;\n                    ...&lt;br&gt;\n                ]&lt;br&gt;\n            },&lt;br&gt;\n            &quot;doc_count&quot;: 191775&lt;br&gt;\n        }&lt;br&gt;\n    },&lt;br&gt;\n    ...&lt;br&gt;\n}&lt;br&gt;\n<\/pre><\/p>\n<p>which is equivalent to what you can obtain with the plugin.<\/p>\n<p>To recapitulate, there is good news: elasticsearch became more powerful with these data mining operations. This allows us to solve the use case described in the previous post by using just base functionality.<\/p>\n<p>There&#8217;s one thing I couldn&#8217;t get to work though: showing the ID of the single document in a bucket, for all the buckets with size 1. It&#8217;s a feature that I was requested to add to the plugin, and it&#8217;s wasn&#8217;t difficult to implement in there. If anyone finds a way to achieve this with aggregations, comments to the post are welcome!<\/p>\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/bit.ly\/3BAo305\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"256\" src=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" alt=\"\" class=\"wp-image-20303\" srcset=\"https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png 1024w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-300x75.png 300w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-768x192.png 768w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1536x384.png 1536w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-2048x512.png 2048w, https:\/\/trifork.nl\/blog\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1920x480.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>In a previous post I described a problem of data visualization and a possible solution provided by a plugin of elasticsearch. I noticed that elasticsearch might one day evolve to make the plugin unnecessary. That day seems to have come:&nbsp;starting from version 1.0.0, elasticsearch includes Aggregations,&nbsp;a new API for data mining. In this post I&#8217;ll [&hellip;]<\/p>\n","protected":false},"author":52,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"categories":[15,65,10],"tags":[61],"class_list":["post-11312","post","type-post","status-publish","format-standard","hentry","category-enterprise-search","category-big_data_search","category-development","tag-elasticsearch"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog\" \/>\n<meta property=\"og:description\" content=\"In a previous post I described a problem of data visualization and a possible solution provided by a plugin of elasticsearch. I noticed that elasticsearch might one day evolve to make the plugin unnecessary. That day seems to have come:&nbsp;starting from version 1.0.0, elasticsearch includes Aggregations,&nbsp;a new API for data mining. In this post I&#8217;ll [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/\" \/>\n<meta property=\"og:site_name\" content=\"Trifork Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-03-26T12:08:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\" \/>\n<meta name=\"author\" content=\"Gianluca Ortelli\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Gianluca Ortelli\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/\",\"url\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/\",\"name\":\"Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog\",\"isPartOf\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"datePublished\":\"2014-03-26T12:08:35+00:00\",\"author\":{\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/0f5a4d92d4a7704cad27bfbdc2a71c7b\"},\"breadcrumb\":{\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage\",\"url\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\",\"contentUrl\":\"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/trifork.nl\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Server-side clustering of geo-points on a map using Elasticsearch &#8211; continued\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/trifork.nl\/blog\/#website\",\"url\":\"https:\/\/trifork.nl\/blog\/\",\"name\":\"Trifork Blog\",\"description\":\"Keep updated on the technical solutions Trifork is working on!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/trifork.nl\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/0f5a4d92d4a7704cad27bfbdc2a71c7b\",\"name\":\"Gianluca Ortelli\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/eaf077709d7fdae692d5bdf94f50d86c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/eaf077709d7fdae692d5bdf94f50d86c?s=96&d=mm&r=g\",\"caption\":\"Gianluca Ortelli\"},\"url\":\"https:\/\/trifork.nl\/blog\/author\/gianluca\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/","og_locale":"en_US","og_type":"article","og_title":"Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog","og_description":"In a previous post I described a problem of data visualization and a possible solution provided by a plugin of elasticsearch. I noticed that elasticsearch might one day evolve to make the plugin unnecessary. That day seems to have come:&nbsp;starting from version 1.0.0, elasticsearch includes Aggregations,&nbsp;a new API for data mining. In this post I&#8217;ll [&hellip;]","og_url":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/","og_site_name":"Trifork Blog","article_published_time":"2014-03-26T12:08:35+00:00","og_image":[{"url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","type":"","width":"","height":""}],"author":"Gianluca Ortelli","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Gianluca Ortelli","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/","url":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/","name":"Server-side clustering of geo-points on a map using Elasticsearch - continued - Trifork Blog","isPartOf":{"@id":"https:\/\/trifork.nl\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage"},"image":{"@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage"},"thumbnailUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","datePublished":"2014-03-26T12:08:35+00:00","author":{"@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/0f5a4d92d4a7704cad27bfbdc2a71c7b"},"breadcrumb":{"@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#primaryimage","url":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png","contentUrl":"https:\/\/trifork.nl\/articles\/wp-content\/uploads\/sites\/3\/2022\/02\/Blog-Banner-1-1024x256.png"},{"@type":"BreadcrumbList","@id":"https:\/\/trifork.nl\/blog\/server-side-clustering-of-geo-points-on-a-map-using-elasticsearch-continued\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/trifork.nl\/blog\/"},{"@type":"ListItem","position":2,"name":"Server-side clustering of geo-points on a map using Elasticsearch &#8211; continued"}]},{"@type":"WebSite","@id":"https:\/\/trifork.nl\/blog\/#website","url":"https:\/\/trifork.nl\/blog\/","name":"Trifork Blog","description":"Keep updated on the technical solutions Trifork is working on!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/trifork.nl\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/0f5a4d92d4a7704cad27bfbdc2a71c7b","name":"Gianluca Ortelli","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/trifork.nl\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/eaf077709d7fdae692d5bdf94f50d86c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/eaf077709d7fdae692d5bdf94f50d86c?s=96&d=mm&r=g","caption":"Gianluca Ortelli"},"url":"https:\/\/trifork.nl\/blog\/author\/gianluca\/"}]}},"_links":{"self":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/11312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/users\/52"}],"replies":[{"embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/comments?post=11312"}],"version-history":[{"count":0,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/posts\/11312\/revisions"}],"wp:attachment":[{"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/media?parent=11312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/categories?post=11312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/trifork.nl\/blog\/wp-json\/wp\/v2\/tags?post=11312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}