{"id":9548,"date":"2020-10-30T06:01:54","date_gmt":"2020-10-30T13:01:54","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=9548"},"modified":"2025-06-13T22:45:07","modified_gmt":"2025-06-14T05:45:07","slug":"geospatial-search-how-do-i-use-thee-let-me-count-the-ways","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/","title":{"rendered":"Using NoSQL for Geospatial Search Without a Spatial Database"},"content":{"rendered":"<h2><span style=\"font-weight: 400\">Introduction<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Couchbase <a href=\"https:\/\/www.couchbase.com\/products\/full-text-search\/\">Full Text Search<\/a> (FTS) is a great tool for indexing and querying <a href=\"https:\/\/www.couchbase.com\/blog\/geospatial-basics-spatial-databases-and-nosql-examples\/\">geospatial data<\/a>.\u00a0 In this article, I\u2019ll present a geospatial search use case and demonstrate the various ways that we can perform a search of location data using the Couchbase Full Text Search service.\u00a0 I\u2019ll be using Couchbase Server Enterprise Edition 6.6 (running <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/install\/getting-started-docker.html\"><span style=\"font-weight: 400\">locally in Docker<\/span><\/a><span style=\"font-weight: 400\">) to create an FTS index on my sample geospatial dataset and then run geospatial queries against the index.<\/span><\/p>\n<p>What makes this case interesting is that we aren&#8217;t using a spatial database. <a href=\"https:\/\/www.couchbase.com\/blog\/geospatial-basics-spatial-databases-and-nosql-examples\/\">What is a spatial database?<\/a> Unlike Couchbase Server, which is a NoSQL document database, spatial databases are specially optimized for data that describes geometric spaces such as lines, points of interest, or even 3-D topology in advanced instances. As we&#8217;ll see, Couchbase&#8217;s Full Text Search capabilities make it just as useful for handling and querying geospatial data as anything we might expect from a more specialized solution.<\/p>\n<h3><span style=\"font-weight: 400\">Use Case<\/span><\/h3>\n<p><span style=\"font-weight: 400\">My family has always enjoyed visiting and exploring <a href=\"https:\/\/www.nps.gov\/grsm\/index.htm\">Great Smoky Mountains National Park<\/a> (or GRSM, the National Park Service\u2019s abbreviation), and one day we might be interested in relocating there. But you can\u2019t live in the national park, so we need to consider the various cities and towns near the park and make a short list of the ones to evaluate and possibly visit.\u00a0 <\/span><\/p>\n<p><span style=\"font-weight: 400\">The main objective is to be within close proximity to the national park, but we\u2019ll consider other factors like the size (population) of the towns, too. <\/span><\/p>\n<h3><span style=\"font-weight: 400\">Sample Dataset<\/span><\/h3>\n<p><span style=\"font-weight: 400\">To support my GRSM use case, I\u2019ve decided to use a public dataset from <\/span><a href=\"https:\/\/www.geonames.org\/\"><span style=\"font-weight: 400\">GeoNames<\/span><\/a><span style=\"font-weight: 400\"> that includes states, cities, towns, and other landmarks from various nations around the world.\u00a0 I downloaded their <\/span><a href=\"https:\/\/download.geonames.org\/export\/dump\/US.zip\"><span style=\"font-weight: 400\">United States data file<\/span><\/a><span style=\"font-weight: 400\"> and imported into Couchbase only the \u201cpopulated places\u201d data (records with <\/span><a href=\"https:\/\/www.geonames.org\/export\/codes.html\"><span style=\"font-weight: 400\">feature codes<\/span><\/a><span style=\"font-weight: 400\"> of &#8216;PPL&#8217;, &#8216;PPLA&#8217;, &#8216;PPLA2&#8217;, &#8216;PPLA3&#8242;,&#8217;PPLA4&#8217;, and &#8216;PPLC&#8217;) for cities\/towns with a non-zero population. The result is a Couchbase bucket \u201ccities\u201d with 30,734 documents.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Each city\u2019s document data model includes some attributes of interest for my GRSM use case: the name, state, population, elevation, and, most importantly, the latitude and longitude.\u00a0 Here are a couple of sample JSON documents:<\/span><\/p>\n<p><b>city::4699066<\/b><\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"geonameid\": 4699066,\r\n  \"featureclass\": \"P\",\r\n  \"featurecode\": \"PPLA2\",\r\n  \"name\": \"Houston\",\r\n  \"state\": \"TX\",\r\n  \"population\": 2296224,\r\n  \"elevation\": 12,\r\n  \"geo\": {\r\n    \"lat\": 29.76328,\r\n    \"lon\": -95.36327\r\n  }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><b>city::4649251<\/b><\/p>\n<pre class=\"lang:default decode:true\">{\r\n  \"geonameid\": 4649251,\r\n  \"featureclass\": \"P\",\r\n  \"featurecode\": \"PPL\",\r\n  \"name\": \"Pigeon Forge\",\r\n  \"state\": \"TN\",\r\n  \"population\": 6171,\r\n  \"elevation\": 305,\r\n  \"geo\": {\r\n    \"lat\": 35.78842,\r\n    \"lon\": -83.55433\r\n  }\r\n}\r\n<\/pre>\n<h2><span style=\"font-weight: 400\">Creating the Index<\/span><\/h2>\n<p><span style=\"font-weight: 400\">With the city data loaded into the cities bucket in Couchbase, we can build an FTS index that suits the \u201clive near GRSM\u201d use case at hand.\u00a0 I\u2019ll briefly cover the highlights of creating the index required here, and the full index definition is below in the appendix of the post. (For a more detailed explanation of creating FTS indexes, please refer to <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/full-text-search-indexing-best-practices-by-use-case\/\"><span style=\"font-weight: 400\">my blog post on the topic<\/span><\/a><span style=\"font-weight: 400\">.)<\/span><\/p>\n<p><span style=\"font-weight: 400\"><a href=\"https:\/\/docs.couchbase.com\/server\/current\/n1ql\/n1ql-language-reference\/createindex.html\">Index creation<\/a> key points:\u00a0<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Name: city_geo<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Bucket: cities<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Type identifier: \u201cDoc ID up to separator\u201d and enter \u201c::\u201d as the delimiter (note the keys of the sample documents above)<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Type mappings:\u00a0<\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Uncheck \u201cdefault\u201d<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Create a mapping for \u201ccity\u201d type documents, indexing only these specified fields:\u00a0<\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">name: I\u2019ll use the keyword analyzer for this field (because we want to sort by name later), and I\u2019ll check index, store, _all, term vectors, and docvalues so that, in addition to searching by this field, I can test the index with highlights and sort by this field.\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">state: Just store this text field so we can retrieve it in the search results.\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">population: Set the type to number, and check index, store, and docvalues so that I can sort results based on population later.\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">elevation: Set the type to number and check only store so that this value is included in the search results.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">geo: Set the type to geopoint (since each document has the \u201clat\u201d and lon\u201d properties in the \u201cgeo\u201d subdocument), and check index, store, and _all.\u00a0<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9556 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-city_geo-create-index-capture.gif\" alt=\"create the city_geo search index\" width=\"779\" height=\"868\" \/><\/p>\n<p><span style=\"font-weight: 400\">We\u2019ll wait until the indexing process is 100% complete: <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9591 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-index-process-complete.png\" alt=\"index processing complete\" width=\"933\" height=\"128\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-index-process-complete.png 933w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-index-process-complete-300x41.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-index-process-complete-768x105.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-index-process-complete-20x3.png 20w\" sizes=\"auto, (max-width: 933px) 100vw, 933px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Now, let\u2019s quickly test the index in the Couchbase UI to verify the index is working as expected.\u00a0 The result looks good! <\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9590 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-city_geo-test-index.png\" alt=\"testing the city_geo index\" width=\"609\" height=\"467\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-city_geo-test-index.png 609w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-city_geo-test-index-300x230.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-city_geo-test-index-20x15.png 20w\" sizes=\"auto, (max-width: 609px) 100vw, 609px\" \/><\/p>\n<h2><span style=\"font-weight: 400\">Geospatial Searches<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Now that the dataset is loaded and indexed, I can get to the heart of the subject at hand and execute some geospatial queries against the index.\u00a0 For demonstration purposes, I\u2019ll query the <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/fts\/fts-searching-with-the-rest-api.html\"><span style=\"font-weight: 400\">Couchbase Search Service REST API<\/span><\/a><span style=\"font-weight: 400\"> with <\/span><a href=\"https:\/\/curl.haxx.se\/\"><span style=\"font-weight: 400\">cURL<\/span><\/a><span style=\"font-weight: 400\">, but the Search queries can also be executed through any of the <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/sdk\/overview.html\"><span style=\"font-weight: 400\">Couchbase SDKs<\/span><\/a><span style=\"font-weight: 400\"> as part of your application or service.\u00a0 N1QL queries also support <a href=\"https:\/\/www.couchbase.com\/blog\/search-and-rescue-7-reasons-for-n1ql-sql-developers-to-use-search\/\">Full Text Search with SQL methods<\/a> without needing any coding.\u00a0 <\/span><\/p>\n<p><span style=\"font-weight: 400\">I\u2019ll format the REST API response for readability using <\/span><a href=\"https:\/\/stedolan.github.io\/jq\/\"><span style=\"font-weight: 400\">jq<\/span><\/a><span style=\"font-weight: 400\">, an open source command-line JSON processor.<\/span><\/p>\n<h3><span style=\"font-weight: 400\">Search Method 1: Point and Radius<\/span><\/h3>\n<p><span style=\"font-weight: 400\">Often we want to know what\u2019s nearby or within a specified distance of a specific point.\u00a0 In my use case, I\u2019d like to know what cities and towns are near the GRSM national park&#8230;maybe within 50 miles as a starting point.\u00a0 This first geospatial search method is referred to as \u201cpoint and radius\u201d, \u201cpoint and distance, or \u201cradius-based\u201d.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">For my \u201cpoint\u201d, I\u2019ve chosen <\/span><a href=\"https:\/\/www.nps.gov\/grsm\/planyourvisit\/nfg.htm\"><span style=\"font-weight: 400\">Newfound Gap<\/span><\/a><span style=\"font-weight: 400\">, which is a pass over the Smoky Mountains on the border of Tennessee and North Carolina, as well as a popular lookout point and a trailhead for the Appalachian Trail.\u00a0 It\u2019s a must-do for my family when we visit GRSM.\u00a0 Let\u2019s look for towns\/cities within 50 miles of Newfound Gap.\u00a0<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9549 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312.png\" alt=\"area for point and radius geospatial search\" width=\"1105\" height=\"995\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312.png 1105w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312-300x270.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312-1024x922.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312-768x692.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-50mi-radius-map-e1603990815312-20x18.png 20w\" sizes=\"auto, (max-width: 1105px) 100vw, 1105px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Here\u2019s the radius-based query:\u00a0<\/span><\/p>\n<pre class=\"lang:default decode:true \">$ curl -s -XPOST -H \"Content-Type: application\/json\" -u Administrator:password https:\/\/localhost:8094\/api\/index\/city_geo\/query -d '\r\n{\r\n  \"fields\": [\"name\",\"state\",\"elevation\",\"population\"],\r\n  \"size\": 500,\r\n  \"query\": {\r\n    \"location\": {\r\n      \"lon\": -83.4217,\r\n      \"lat\": 35.6067\r\n    },\r\n    \"distance\": \"50mi\",\r\n    \"field\": \"geo\"\r\n    },\r\n  \"sort\": [\r\n    {\r\n      \"by\": \"geo_distance\",\r\n      \"field\": \"geo\",\r\n      \"unit\": \"mi\",\r\n      \"location\": {\r\n        \"lon\": -83.4217,\r\n        \"lat\": 35.6067\r\n      }\r\n    }\r\n  ]\r\n}' | jq '(\"result_count: \"+ (.total_hits | tostring)), (.hits[]| (.fields.name + \", \" + .fields.state + \" - population: \" + (.fields.population | tostring) + \", elevation: \" + (.fields.elevation | tostring)))'<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">The result is 79 cities, sorted by distance from Newfound Gap.\u00a0 I\u2019ve included the first 15 results here:\u00a0<\/span><\/p>\n<pre class=\"lang:default decode:true\">\"result_count: 79\"\r\n\"Gatlinburg, TN - population: 4184, elevation: 394\"\r\n\"Pittman Center, TN - population: 565, elevation: 393\"\r\n\"Cherokee, NC - population: 2138, elevation: 605\"\r\n\"Bryson City, NC - population: 1458, elevation: 528\"\r\n\"Pigeon Forge, TN - population: 6171, elevation: 305\"\r\n\"Dillsboro, NC - population: 240, elevation: 607\"\r\n\"Maggie Valley, NC - population: 1251, elevation: 918\"\r\n\"Townsend, TN - population: 452, elevation: 326\"\r\n\"Sylva, NC - population: 2617, elevation: 623\"\r\n\"Sevierville, TN - population: 16490, elevation: 275\"\r\n\"Fair Garden, TN - population: 529, elevation: 340\"\r\n\"Webster, NC - population: 375, elevation: 656\"\r\n\"Cove Creek, NC - population: 1171, elevation: 767\"\r\n\"Walland, TN - population: 259, elevation: 281\"\r\n\"Cullowhee, NC - population: 6228, elevation: 645\"\r\n<\/pre>\n<h3><span style=\"font-weight: 400\">Search Method 2: Bounding Box<\/span><\/h3>\n<p><span style=\"font-weight: 400\">79 is a lot of towns &amp; cities to consider, so let\u2019s think about another way to look at this. From my visits to the national park over the years, I know roughly that I want to live somewhere between Knoxville, TN and Waynesville, NC.\u00a0 Given those two locations, I can query against my GeoNames dataset using the \u201cbounding box\u201d or \u201crectangle-based\u201d geospatial search method.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">I can supply the coordinates of places near Knoxville and Wanyesville as parameters to my search and those will be used as the upper left and lower right corners of a rectangle.\u00a0 Any cities located within that rectangle will be returned by the query.\u00a0\u00a0<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9550 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-bounding-box-map-large-e1603998092825.png\" alt=\"selected area for bounding box geospatial search\" width=\"865\" height=\"788\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-bounding-box-map-large-e1603998092825.png 865w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-bounding-box-map-large-e1603998092825-300x273.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-bounding-box-map-large-e1603998092825-768x700.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-bounding-box-map-large-e1603998092825-20x18.png 20w\" sizes=\"auto, (max-width: 865px) 100vw, 865px\" \/><\/p>\n<p><span style=\"font-weight: 400\">Here\u2019s the rectangle-based query:\u00a0<\/span><\/p>\n<pre class=\"lang:default decode:true \">$ curl -s -XPOST -H \"Content-Type: application\/json\" -u Administrator:password https:\/\/localhost:8094\/api\/index\/city_geo\/query -d '\r\n{\r\n  \"fields\": [\"name\",\"state\",\"elevation\",\"population\"],\r\n  \"size\": 50,\r\n  \"query\": {\r\n    \"top_left\": {\r\n      \"lon\": -83.937408,\r\n      \"lat\": 36.032024\r\n     },\r\n    \"bottom_right\": {\r\n      \"lon\": -82.947580,\r\n      \"lat\": 35.401835\r\n     },\r\n    \"field\": \"geo\"\r\n  },\r\n  \"sort\": [\r\n    \"name\"\r\n  ]\r\n}' | jq '(\"result_count: \"+ (.total_hits | tostring)), (.hits[]| (.fields.name + \", \" + .fields.state + \" - population: \" + (.fields.population | tostring) + \", elevation: \" + (.fields.elevation | tostring)))'\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">The result is 21 cities, sorted by name:\u00a0<\/span><\/p>\n<pre class=\"lang:default decode:true \">\"result_count: 21\"\r\n\"Bryson City, NC - population: 1458, elevation: 528\"\r\n\"Cherokee, NC - population: 2138, elevation: 605\"\r\n\"Cove Creek, NC - population: 1171, elevation: 767\"\r\n\"Dandridge, TN - population: 2924, elevation: 304\"\r\n\"Eagleton Village, TN - population: 5052, elevation: 289\"\r\n\"Fair Garden, TN - population: 529, elevation: 340\"\r\n\"Gatlinburg, TN - population: 4184, elevation: 394\"\r\n\"Hazelwood, NC - population: 1655, elevation: 842\"\r\n\"Knoxville, TN - population: 185291, elevation: 276\"\r\n\"Lake Junaluska, NC - population: 2734, elevation: 778\"\r\n\"Maggie Valley, NC - population: 1251, elevation: 918\"\r\n\"Newport, TN - population: 6834, elevation: 321\"\r\n\"Parrottsville, TN - population: 261, elevation: 363\"\r\n\"Pigeon Forge, TN - population: 6171, elevation: 305\"\r\n\"Pittman Center, TN - population: 565, elevation: 393\"\r\n\"Sevierville, TN - population: 16490, elevation: 275\"\r\n\"Seymour, TN - population: 10919, elevation: 285\"\r\n\"Townsend, TN - population: 452, elevation: 326\"\r\n\"Walland, TN - population: 259, elevation: 281\"\r\n\"Waynesville, NC - population: 9809, elevation: 837\"\r\n\"Wildwood, TN - population: 1098, elevation: 278\"\r\n<\/pre>\n<h3><span style=\"font-weight: 400\">Search Method 3: Polygon<\/span><\/h3>\n<p><span style=\"font-weight: 400\">After some additional research, I\u2019ve decided that I would prefer to live within Sevier County, but south of Interstate 40 and north of the national park boundary.\u00a0\u00a0<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-9552 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765.png\" alt=\"selected area for polygon-based geospatial search\" width=\"1200\" height=\"988\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765.png 1200w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765-300x247.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765-1024x843.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765-768x632.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-sevier-county-polygon-map-e1603998440765-20x16.png 20w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/p>\n<p><span style=\"font-weight: 400\">To do this, I will need to run a polygon-based search against my FTS index.\u00a0 This third method was recently added in Couchbase Server 6.5.1. The areas for geospatial search queries can now be specified as polygons, in addition to circles and rectangles.\u00a0 The polygon is expressed as a series of latitude-longitude coordinates, each determining the location of one corner of the polygon.\u00a0\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">On the map of Sevier County above (the light red line is the county boundary), I\u2019ve overlaid a polygon that roughly corresponds to the area that I\u2019m interested in, and I\u2019ve captured the coordinates of the points of the polygon.\u00a0 I\u2019ll use these coordinates to form my geospatial polygon-based query:<\/span><\/p>\n<pre class=\"lang:default decode:true \">$ curl -s -XPOST -H \"Content-Type: application\/json\" -u Administrator:password https:\/\/localhost:8094\/api\/index\/city_geo\/query -d '\r\n{\r\n  \"fields\": [\"name\",\"state\",\"elevation\",\"population\"],\r\n  \"size\": 50,\r\n  \"query\": {\r\n    \"field\": \"geo\",\r\n    \"polygon_points\": [\r\n      \"35.987374, -83.658937\",\r\n      \"35.971769, -83.654212\",\r\n      \"35.887168, -83.793874\",\r\n      \"35.686403, -83.678068\",\r\n      \"35.704374, -83.505435\",\r\n      \"35.769145, -83.275637\",\r\n      \"35.868423, -83.290819\", \r\n      \"35.919168, -83.350486\", \r\n      \"35.948053, -83.510420\",\r\n      \"35.990925, -83.568382\"\r\n    ]\r\n  },\r\n  \"sort\": [\r\n    {\r\n      \"by\" : \"field\",\r\n      \"field\" : \"population\",\r\n      \"missing\" : \"last\",\r\n      \"type\": \"number\"\r\n    }\r\n  ]\r\n}' | jq '(\"result_count: \"+ (.total_hits | tostring)), (.hits[]| (.fields.name + \", \" + .fields.state + \" - population: \" + (.fields.population | tostring) + \", elevation: \" + (.fields.elevation | tostring)))'\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p><span style=\"font-weight: 400\">The result is a very manageable list of 6 cities, sorted by population in ascending order:\u00a0<\/span><\/p>\n<pre class=\"lang:default decode:true \">\"result_count: 6\"\r\n\"Fair Garden, TN - population: 529, elevation: 340\"\r\n\"Pittman Center, TN - population: 565, elevation: 393\"\r\n\"Gatlinburg, TN - population: 4184, elevation: 394\"\r\n\"Pigeon Forge, TN - population: 6171, elevation: 305\"\r\n\"Seymour, TN - population: 10919, elevation: 285\"\r\n\"Sevierville, TN - population: 16490, elevation: 275\"\r\n<\/pre>\n<h2><span style=\"font-weight: 400\">Summary and Next Steps<\/span><\/h2>\n<p><span style=\"font-weight: 400\">With these three search methods, Couchbase offers a comprehensive geospatial search capability for you to include in your applications.\u00a0 I encourage you to create an index with geopoint data and run some geospatial point, or geospatial polygon-based queries.\u00a0 You can easily do this with one of our Couchbase <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/manage\/manage-settings\/install-sample-buckets.html\"><span style=\"font-weight: 400\">sample datasets<\/span><\/a><span style=\"font-weight: 400\">, travel-sample, which has a lot of location-based data to use for this purpose.\u00a0\u00a0<\/span><\/p>\n<p>Take it one step further and visualize JSON data as <a href=\"https:\/\/www.couchbase.com\/blog\/geospatial-aspnet-aurelia-google-maps\/\">real time output<\/a> from the document database search request using web-based geospatial technology platforms like <a href=\"https:\/\/mapbox.com\">Mapbox<\/a> or <a href=\"https:\/\/esri.com\">ESRI<\/a>.\u00a0 You will benefit from managing data in a distributed database management system that also supports horizontal scaling, general key value store, data consistency, and more.<\/p>\n<p><span style=\"font-weight: 400\">Geospatial search is just one of the capabilities of Full Text Search in Couchbase.\u00a0 You can also try out queries on <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/fts-and-n1ql-improving-performance-when-querying-multiple-arrays\/\"><span style=\"font-weight: 400\">arrays<\/span><\/a><span style=\"font-weight: 400\"> and natural language queries with scoring, faceting, and boosting.\u00a0 For more information on this topic, take a look at the application developer documentation and training links in the reference section below.\u00a0\u00a0<\/span><\/p>\n<h2><span style=\"font-weight: 400\">References<\/span><\/h2>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Couchbase <a href=\"https:\/\/www.couchbase.com\/products\/full-text-search\/\">Search<\/a> Resources: <\/span><a href=\"https:\/\/www.couchbase.com\/products\/full-text-search\/\"><span style=\"font-weight: 400\">https:\/\/www.couchbase.com\/products\/full-text-search<\/span><\/a><\/li>\n<li><a href=\"https:\/\/www.couchbase.com\/blog\/geospatial-basics-spatial-databases-and-nosql-examples\/\">What is a Spatial Database?<\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Couchbase FTS Documentation: <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/fts\/full-text-intro.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/server\/current\/fts\/full-text-intro.html<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Couchbase FTS Blog Posts: <\/span><a href=\"https:\/\/www.couchbase.com\/blog\/category\/full-text-search\/\"><span style=\"font-weight: 400\">https:\/\/www.couchbase.com\/blog\/category\/full-text-search\/<\/span><\/a><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Couchbase <a href=\"https:\/\/learn.couchbase.com\/store\/509465-cb121-intro-to-couchbase-full-text-search-fts\">NoSQL Search &#8211; Online Training<\/a>: <\/span><a href=\"https:\/\/learn.couchbase.com\/store\/509465-cb121-intro-to-couchbase-full-text-search-fts\"><span style=\"font-weight: 400\">https:\/\/learn.couchbase.com\/store\/509465-cb121-intro-to-couchbase-full-text-search-fts<\/span><\/a><\/li>\n<li>Couchbase NoSQL SDK &#8211; <a href=\"https:\/\/docs.couchbase.com\/java-sdk\/2.7\/full-text-searching-with-sdk.html\">Geospatial Search &#8211; Java<\/a>, <a href=\"https:\/\/docs.couchbase.com\/dotnet-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">.NET<\/a>, <a href=\"https:\/\/docs.couchbase.com\/python-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">Python<\/a>, <a href=\"https:\/\/docs.couchbase.com\/nodejs-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">Node.js<\/a>, <a href=\"https:\/\/docs.couchbase.com\/go-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">Go<\/a>, <a href=\"https:\/\/docs.couchbase.com\/scala-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">Scala<\/a>, <a href=\"https:\/\/docs.couchbase.com\/ruby-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">Ruby<\/a>, <a href=\"https:\/\/docs.couchbase.com\/c-sdk\/current\/howtos\/full-text-searching-with-sdk.html\">C<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400\">Appendix<\/span><\/h2>\n<p><span style=\"font-weight: 400\">Index Creation cURL Command and JSON Definition: <\/span><\/p>\n<pre class=\"lang:default decode:true \">$ curl -XPUT -H \"Content-Type: application\/json\" \\\r\n-u &lt;username&gt;:&lt;password&gt; https:\/\/localhost:8094\/api\/index\/city_geo -d \\\r\n'{\r\n  \"type\": \"fulltext-index\",\r\n  \"name\": \"city_geo\",\r\n  \"sourceType\": \"couchbase\",\r\n  \"sourceName\": \"cities\",\r\n  \"planParams\": {\r\n    \"maxPartitionsPerPIndex\": 171,\r\n    \"indexPartitions\": 6\r\n  },\r\n  \"params\": {\r\n    \"doc_config\": {\r\n      \"docid_prefix_delim\": \"::\",\r\n      \"docid_regexp\": \"\",\r\n      \"mode\": \"docid_prefix\",\r\n      \"type_field\": \"type\"\r\n    },\r\n    \"mapping\": {\r\n      \"analysis\": {},\r\n      \"default_analyzer\": \"standard\",\r\n      \"default_datetime_parser\": \"dateTimeOptional\",\r\n      \"default_field\": \"_all\",\r\n      \"default_mapping\": {\r\n        \"dynamic\": true,\r\n        \"enabled\": false\r\n      },\r\n      \"default_type\": \"_default\",\r\n      \"docvalues_dynamic\": true,\r\n      \"index_dynamic\": true,\r\n      \"store_dynamic\": false,\r\n      \"type_field\": \"_type\",\r\n      \"types\": {\r\n        \"city\": {\r\n          \"dynamic\": false,\r\n          \"enabled\": true,\r\n          \"properties\": {\r\n            \"elevation\": {\r\n              \"dynamic\": false,\r\n              \"enabled\": true,\r\n              \"fields\": [\r\n                {\r\n                  \"include_term_vectors\": true,\r\n                  \"name\": \"elevation\",\r\n                  \"store\": true,\r\n                  \"type\": \"number\"\r\n                }\r\n              ]\r\n            },\r\n            \"geo\": {\r\n              \"dynamic\": false,\r\n              \"enabled\": true,\r\n              \"fields\": [\r\n                {\r\n                  \"docvalues\": true,\r\n                  \"include_in_all\": true,\r\n                  \"include_term_vectors\": true,\r\n                  \"index\": true,\r\n                  \"name\": \"geo\",\r\n                  \"store\": true,\r\n                  \"type\": \"geopoint\"\r\n                }\r\n              ]\r\n            },\r\n            \"name\": {\r\n              \"dynamic\": false,\r\n              \"enabled\": true,\r\n              \"fields\": [\r\n                {\r\n                  \"analyzer\": \"keyword\",\r\n                  \"docvalues\": true,\r\n                  \"include_in_all\": true,\r\n                  \"include_term_vectors\": true,\r\n                  \"index\": true,\r\n                  \"name\": \"name\",\r\n                  \"store\": true,\r\n                  \"type\": \"text\"\r\n                }\r\n              ]\r\n            },\r\n            \"population\": {\r\n              \"dynamic\": false,\r\n              \"enabled\": true,\r\n              \"fields\": [\r\n                {\r\n                  \"docvalues\": true,\r\n                  \"include_term_vectors\": true,\r\n                  \"index\": true,\r\n                  \"name\": \"population\",\r\n                  \"store\": true,\r\n                  \"type\": \"number\"\r\n                }\r\n              ]\r\n            },\r\n            \"state\": {\r\n              \"dynamic\": false,\r\n              \"enabled\": true,\r\n              \"fields\": [\r\n                {\r\n                  \"name\": \"state\",\r\n                  \"store\": true,\r\n                  \"type\": \"text\"\r\n                }\r\n              ]\r\n            }\r\n          }\r\n        }\r\n      }\r\n    },\r\n    \"store\": {\r\n      \"indexType\": \"scorch\"\r\n    }\r\n  },\r\n  \"sourceParams\": {}\r\n}'\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Couchbase Full Text Search (FTS) is a great tool for indexing and querying geospatial data.\u00a0 In this article, I\u2019ll present a geospatial search use case and demonstrate the various ways that we can perform a search of location data [&hellip;]<\/p>\n","protected":false},"author":16362,"featured_media":9551,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,2165,8683,1818,1812,7277,2201],"tags":[8622],"ppma_author":[9100],"class_list":["post-9548","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-full-text-search","category-geospatial","category-java","category-n1ql-query","category-text-analysis","category-tools-sdks","tag-distributed-search"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using NoSQL for Geospatial Search Without a Spatial Database - The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Couchbase provides a variety of ways to perform geospatial search in your application. We&#039;ll review a use case for location data and demo the capabilities.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using NoSQL for Geospatial Search Without a Spatial Database\" \/>\n<meta property=\"og:description\" content=\"Couchbase provides a variety of ways to perform geospatial search in your application. We&#039;ll review a use case for location data and demo the capabilities.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-30T13:01:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T05:45:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/Geospatial-search-how-do-I-use-thee-Let-me-count-the-ways..png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"627\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Brian Kane, Solutions Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Brian Kane, Solutions Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\"},\"author\":{\"name\":\"Brian Kane, Solutions Engineer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/69569e5446e8ee83e32f8e5ed50a250e\"},\"headline\":\"Using NoSQL for Geospatial Search Without a Spatial Database\",\"datePublished\":\"2020-10-30T13:01:54+00:00\",\"dateModified\":\"2025-06-14T05:45:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\"},\"wordCount\":1444,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg\",\"keywords\":[\"distributed search\"],\"articleSection\":[\"Best Practices and Tutorials\",\"Full-Text Search\",\"Geospatial\",\"Java\",\"SQL++ \/ N1QL Query\",\"Text Analysis\",\"Tools &amp; SDKs\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\",\"name\":\"Using NoSQL for Geospatial Search Without a Spatial Database - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg\",\"datePublished\":\"2020-10-30T13:01:54+00:00\",\"dateModified\":\"2025-06-14T05:45:07+00:00\",\"description\":\"Couchbase provides a variety of ways to perform geospatial search in your application. We'll review a use case for location data and demo the capabilities.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg\",\"width\":2335,\"height\":680,\"caption\":\"Great Smoky Mountains National Park\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using NoSQL for Geospatial Search Without a Spatial Database\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/69569e5446e8ee83e32f8e5ed50a250e\",\"name\":\"Brian Kane, Solutions Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/d6ceb7493ed6dce23e12c34a4d31643e\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/366c828464bd7bc90174aca4473a71c317f4578e440915acf85a1de7e170c1e0?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/366c828464bd7bc90174aca4473a71c317f4578e440915acf85a1de7e170c1e0?s=96&d=mm&r=g\",\"caption\":\"Brian Kane, Solutions Engineer, Couchbase\"},\"description\":\"Brian Kane is a Solutions Engineer at Couchbase and has been working in application development and with database technologies since 1996. He is based in the Houston, Texas area.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/brian-kanecouchbase-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using NoSQL for Geospatial Search Without a Spatial Database - The Couchbase Blog","description":"Couchbase provides a variety of ways to perform geospatial search in your application. We'll review a use case for location data and demo the capabilities.","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:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/","og_locale":"en_US","og_type":"article","og_title":"Using NoSQL for Geospatial Search Without a Spatial Database","og_description":"Couchbase provides a variety of ways to perform geospatial search in your application. We'll review a use case for location data and demo the capabilities.","og_url":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/","og_site_name":"The Couchbase Blog","article_published_time":"2020-10-30T13:01:54+00:00","article_modified_time":"2025-06-14T05:45:07+00:00","og_image":[{"width":1200,"height":627,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/Geospatial-search-how-do-I-use-thee-Let-me-count-the-ways..png","type":"image\/png"}],"author":"Brian Kane, Solutions Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Brian Kane, Solutions Engineer, Couchbase","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/"},"author":{"name":"Brian Kane, Solutions Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/69569e5446e8ee83e32f8e5ed50a250e"},"headline":"Using NoSQL for Geospatial Search Without a Spatial Database","datePublished":"2020-10-30T13:01:54+00:00","dateModified":"2025-06-14T05:45:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/"},"wordCount":1444,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg","keywords":["distributed search"],"articleSection":["Best Practices and Tutorials","Full-Text Search","Geospatial","Java","SQL++ \/ N1QL Query","Text Analysis","Tools &amp; SDKs"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/","url":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/","name":"Using NoSQL for Geospatial Search Without a Spatial Database - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg","datePublished":"2020-10-30T13:01:54+00:00","dateModified":"2025-06-14T05:45:07+00:00","description":"Couchbase provides a variety of ways to perform geospatial search in your application. We'll review a use case for location data and demo the capabilities.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2020\/10\/BKane-Geospatial-grsm.jpg","width":2335,"height":680,"caption":"Great Smoky Mountains National Park"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/geospatial-search-how-do-i-use-thee-let-me-count-the-ways\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using NoSQL for Geospatial Search Without a Spatial Database"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/69569e5446e8ee83e32f8e5ed50a250e","name":"Brian Kane, Solutions Engineer, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/d6ceb7493ed6dce23e12c34a4d31643e","url":"https:\/\/secure.gravatar.com\/avatar\/366c828464bd7bc90174aca4473a71c317f4578e440915acf85a1de7e170c1e0?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/366c828464bd7bc90174aca4473a71c317f4578e440915acf85a1de7e170c1e0?s=96&d=mm&r=g","caption":"Brian Kane, Solutions Engineer, Couchbase"},"description":"Brian Kane is a Solutions Engineer at Couchbase and has been working in application development and with database technologies since 1996. He is based in the Houston, Texas area.","url":"https:\/\/www.couchbase.com\/blog\/author\/brian-kanecouchbase-com\/"}]}},"authors":[{"term_id":9100,"user_id":16362,"is_guest":0,"slug":"brian-kanecouchbase-com","display_name":"Brian Kane, Solutions Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/366c828464bd7bc90174aca4473a71c317f4578e440915acf85a1de7e170c1e0?s=96&d=mm&r=g","author_category":"","last_name":"Kane, Solutions Engineer, Couchbase","first_name":"Brian","job_title":"","user_url":"","description":"Brian Kane is a Solutions Engineer at Couchbase and has been working in application development and with database technologies since 1996. He is based in the Houston, Texas area."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/9548","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/16362"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=9548"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/9548\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/9551"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=9548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=9548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=9548"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=9548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}