<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/geospatial-queries-using-pymongo-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://mlampros.github.io/mlampros.github.io/2017/08/07/the_GeoMongo_package/"> mlampros</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Since I submitted the <a rel="nofollow" href="https://cran.r-project.org/package=geojsonR" target="_blank"><em>geojsonR</em> package</a> I was interested in running geospatial MongoDB queries using GeoJson data. I decided to use PyMongo (through the reticulate package) after opening two Github issues <a rel="nofollow" href="https://github.com/jeroen/mongolite/issues/7" target="_blank">here</a> and <a rel="nofollow" href="https://github.com/rstudio/reticulate/issues/81" target="_blank">here</a>. In my opinion, the PyMongo library is huge and covers a lot of things however, my intention was to be able to run geospatial queries from within R.</p>
<h3>The GeoMongo package</h3>
<p>The <a rel="nofollow" href="https://github.com/mlampros/GeoMongo" target="_blank"><em>GeoMongo</em></a> package allows the user,</p>
<ul>
<li>to insert and query <strong>only</strong> GeoJson data using the <strong>geomongo</strong> R6 class</li>
<li>to read data in either json (through the geojsonR package) or BSON format (I’ll explain later when BSON is necessary for inserting data)</li>
<li>to validate a json instance using a schema using the <strong>json_schema_validator()</strong> function (input parameters are R named lists)</li>
<li>to utilize MongoDB console commands using the <strong>mongodb_console()</strong> function. The <em>mongodb_console()</em> function takes advantage of the base R <em>system()</em> function. For instance, MongoDB console commands are necessary in case of bulk import / export of data as documented <a rel="nofollow" href="https://docs.mongodb.com/manual/reference/program/mongoimport/" target="_blank">here</a> and <a rel="nofollow" href="https://docs.mongodb.com/manual/reference/program/mongoexport/" target="_blank">here</a>.</li>
</ul>
<p></p>
<p>I was able to reproduce the majority of geospatial MongoDB queries ( System Requirements : MongoDB (>= 3.4) and Python (>= 3.5) ) using a number of blog posts on the web, however I’ll take advantage of the following two in order to explain how one can use the <strong>GeoMongo</strong> package for this purpose:</p>
<ul>
<li><a rel="nofollow" href="http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries" target="_blank">first example blog post</a> [ The 80/20 Guide to MongoDB Geospatial Queries, by Valeri Karpov]</li>
<li><a rel="nofollow" href="https://docs.mongodb.com/manual/geospatial-queries/" target="_blank">second documentation example</a> [ Geospatial Queries, in MongoDB documentation ]</li>
</ul>
<p></p>
<h3>queries based on <a rel="nofollow" href="http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries" target="_blank">first example blog post</a></h3>
<p></p>
<p>When inserting data using the <em>geomongo</em> R6 class the user has the option (via the <em>TYPE_DATA</em> parameter) to either give a <em>character string (or vector)</em>, a <em>list</em>, a <em>file</em> or a <em>folder of files</em> as input. To start with, I’ll use the following character strings ( they appear in the first example blog post , the “_id” ‘s were removed),</p>
<div>
<pre><code><span>
</span><span>library</span><span>(</span><span>GeoMongo</span><span>)</span><span>
</span><span># important : the property-names of each geojson object should be of type character string
</span><span>
</span><span>loc1</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot; : &quot;Squaw Valley&quot;,
&quot;location&quot; : {
&quot;type&quot; : &quot;Point&quot;,
&quot;coordinates&quot; : [
-120.24,
39.21
]
}
}'</span><span>
</span><span>loc2</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot; : &quot;Mammoth Lakes&quot;,
&quot;location&quot; : {
&quot;type&quot; : &quot;Point&quot;,
&quot;coordinates&quot; : [
-118.9,
37.61
]
}
}'</span><span>
</span><span>loc3</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot; : &quot;Aspen&quot;,
&quot;location&quot; : {
&quot;type&quot; : &quot;Point&quot;,
&quot;coordinates&quot; : [
-106.82,
39.18
]
}
}'</span><span>
</span><span>loc4</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot; : &quot;Whistler&quot;,
&quot;location&quot; : {
&quot;type&quot; : &quot;Point&quot;,
&quot;coordinates&quot; : [
-122.95,
50.12
]
}
}'</span><span>
</span><span># create a vector of character strings
</span><span>
</span><span>char_FILES</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>loc1</span><span>,</span><span> </span><span>loc2</span><span>,</span><span> </span><span>loc3</span><span>,</span><span> </span><span>loc4</span><span>)</span><span> </span></code></pre>
</div>
<p></p>
<p>Before inserting the data one should <strong>make sure that MongoDB is running on the Operating System</strong>. Information on how to <strong>install MongoDB</strong> can be found <a rel="nofollow" href="https://docs.mongodb.com/manual/installation/" target="_blank">here</a>.</p>
<p></p>
<p>The <strong>geomongo</strong> R6 class will be initialized and a database and collection will be created,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span> </span><span>=</span><span> </span><span>geomongo</span><span>$</span><span>new</span><span>(</span><span>host</span><span> </span><span>=</span><span> </span><span>'localhost'</span><span>,</span><span> </span><span>port</span><span> </span><span>=</span><span> </span><span>27017</span><span>)</span><span> </span><span># assuming MongoDB runs locally
</span><span>
</span><span>getter_client</span><span> </span><span>=</span><span> </span><span>init</span><span>$</span><span>getClient</span><span>()</span><span> </span><span># get MongoClient()
</span><span>
</span><span>init_db</span><span> </span><span>=</span><span> </span><span>getter_client</span><span>[[</span><span>&quot;example_db&quot;</span><span>]]</span><span> </span><span># create a new database
</span><span>
</span><span>init_col</span><span> </span><span>=</span><span> </span><span>init_db</span><span>$</span><span>create_collection</span><span>(</span><span>&quot;example_col&quot;</span><span>)</span><span> </span><span># create a new collection
</span><span>
</span></code></pre>
</div>
<p></p>
<p>After the preliminary steps, one can continue by inserting the <em>char_FILES</em> object to the relevant database / collection using the <strong>geoInsert</strong> method. The <em>TYPE_DATA</em> parameter equals here to <em>dict_many</em> meaning it can take either a <em>list of lists (nested list)</em> or a <em>character vector of strings</em>,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>geoInsert</span><span>(</span><span>DATA</span><span> </span><span>=</span><span> </span><span>char_FILES</span><span>,</span><span> </span><span># input data
</span><span> </span><span>TYPE_DATA</span><span> </span><span>=</span><span> </span><span>'dict_many'</span><span>,</span><span> </span><span># character vector of strings as input
</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>init_col</span><span>,</span><span> </span><span># specify the relevant collection
</span><span> </span><span>GEOMETRY_NAME</span><span> </span><span>=</span><span> </span><span>&quot;location&quot;</span><span>)</span><span> </span><span># give the 'geometry name' of each geo-object
</span><span>
</span></code></pre>
</div>
<p></p>
<p>One can now run various commands to check the correctness of the inserted data,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init_db</span><span>$</span><span>collection_names</span><span>()</span><span> </span><span># prints out the collection names of the relevant database
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>&quot;example_col&quot;</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init_col</span><span>$</span><span>find_one</span><span>()</span><span> </span><span># prints one of the inserted geometry objects
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>$</span><span>`_id`</span><span>
</span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6a</span><span>
</span><span>$</span><span>location</span><span>
</span><span>$</span><span>location</span><span>$</span><span>type</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Point&quot;</span><span>
</span><span>$</span><span>location</span><span>$</span><span>coordinates</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>-120.24</span><span> </span><span>39.21</span><span>
</span><span>$</span><span>name</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Squaw Valley&quot;</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>init_col</span><span>$</span><span>count</span><span>()</span><span> </span><span># prints the number of the inserted geometry objects
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>4</span><span>
</span></code></pre>
</div>
<p></p>
<p>I’ll continue reproducing some of the geo-queries of the <a rel="nofollow" href="http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries" target="_blank">first example blog post</a> from within an R-session.</p>
<p></p>
<p>The first query is about the number of locations in the state of Colorado, where Colorado is approximated as the below GeoJson square,</p>
<p></p>
<div>
<pre><code><span>
</span><span>{</span><span>
</span><span>&quot;type&quot;</span><span>:</span><span> </span><span>&quot;Polygon&quot;</span><span>,</span><span>
</span><span>&quot;coordinates&quot;</span><span>:</span><span> </span><span>[[</span><span>
</span><span>[</span><span>-109</span><span>,</span><span> </span><span>41</span><span>],</span><span>
</span><span>[</span><span>-102</span><span>,</span><span> </span><span>41</span><span>],</span><span>
</span><span>[</span><span>-102</span><span>,</span><span> </span><span>37</span><span>],</span><span>
</span><span>[</span><span>-109</span><span>,</span><span> </span><span>37</span><span>],</span><span>
</span><span>[</span><span>-109</span><span>,</span><span> </span><span>41</span><span>]</span><span>
</span><span>]]</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p></p>
<p>and the corresponding MongoDB query would be,</p>
<p></p>
<div>
<pre><code><span>
</span><span>db.locations.find</span><span>({</span><span>
</span><span>...</span><span> </span><span>location</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>$</span><span>geoIntersects</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>$</span><span>geometry</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>type</span><span>:</span><span> </span><span>&quot;Polygon&quot;</span><span>,</span><span>
</span><span>...</span><span> </span><span>coordinates</span><span>:</span><span> </span><span>[[</span><span>
</span><span>...</span><span> </span><span>[</span><span>-109</span><span>,</span><span> </span><span>41</span><span>],</span><span>
</span><span>...</span><span> </span><span>[</span><span>-102</span><span>,</span><span> </span><span>41</span><span>],</span><span>
</span><span>...</span><span> </span><span>[</span><span>-102</span><span>,</span><span> </span><span>37</span><span>],</span><span>
</span><span>...</span><span> </span><span>[</span><span>-109</span><span>,</span><span> </span><span>37</span><span>],</span><span>
</span><span>...</span><span> </span><span>[</span><span>-109</span><span>,</span><span> </span><span>41</span><span>]</span><span>
</span><span>...</span><span> </span><span>]]</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>})</span><span>
</span></code></pre>
</div>
<p></p>
<p>This query can be <em>translated</em> in R in the following way:</p>
<ul>
<li><em>curly braces</em> correspond to <em>R-lists</em></li>
<li><em>arrays</em> (of size 2) to <em>R-vectors</em>,</li>
</ul>
<p></p>
<div>
<pre><code><span>
</span><span>query_geoIntersects</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'location'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'$geoIntersects'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'$geometry'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>
</span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;Polygon&quot;</span><span>,</span><span> </span><span>coordinates</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>
</span><span>list</span><span>(</span><span>
</span><span>c</span><span>(</span><span>-109</span><span>,</span><span> </span><span>41</span><span>),</span><span> </span><span>c</span><span>(</span><span>-102</span><span>,</span><span> </span><span>41</span><span>),</span><span> </span><span>c</span><span>(</span><span>-102</span><span>,</span><span> </span><span>37</span><span>),</span><span> </span><span>c</span><span>(</span><span>-109</span><span>,</span><span> </span><span>37</span><span>),</span><span> </span><span>c</span><span>(</span><span>-109</span><span>,</span><span> </span><span>41</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<p>and the <strong>find</strong> METHOD of <strong>geoQuery</strong> function will be used to return locations which are within the boundaries of Colorado,</p>
<p></p>
<div>
<pre><code><span>
</span><span>loc_intersect</span><span> </span><span>=</span><span> </span><span>init</span><span>$</span><span>geoQuery</span><span>(</span><span>QUERY</span><span> </span><span>=</span><span> </span><span>query_geoIntersects</span><span>,</span><span> </span><span># query from previous chunk
</span><span> </span><span>METHOD</span><span> </span><span>=</span><span> </span><span>&quot;find&quot;</span><span>,</span><span> </span><span># the method to use
</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>init_col</span><span>,</span><span> </span><span># the collection to use
</span><span>
</span><span>GEOMETRY_NAME</span><span> </span><span>=</span><span> </span><span>&quot;location&quot;</span><span>,</span><span> </span><span># the geometry name to use
</span><span> </span><span>TO_LIST</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span> </span><span># returns a data.table
</span><span>
</span><span>loc_intersect</span><span>
</span></code></pre>
</div>
<p></p>
<p>The output can be returned either as a <em>list</em> or as a <em>data.table</em>,</p>
<p></p>
<div>
<pre><code><span>
</span><span># data.table format
</span><span>
</span><span>location.type</span><span> </span><span>location.coordinates1</span><span> </span><span>location.coordinates2</span><span> </span><span>name</span><span> </span><span>id</span><span>
</span><span>1</span><span>:</span><span> </span><span>Point</span><span> </span><span>-106.82</span><span> </span><span>39.18</span><span> </span><span>Aspen</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6c</span><span>
</span></code></pre>
</div>
<p></p>
<p>The next few code chunks will show how to return documents that are <em>within a certain distance of a given point</em> using the <em>geoWithin</em> and <em>centerSphere</em> operators (locations with a square of circumradius 300 miles centered on San Francisco, approximately latitude 37.7, longitude -122.5).</p>
<div>
<pre><code><span>
</span><span># MongoDB query
</span><span>
</span><span>db.locations.find</span><span>({</span><span>
</span><span>...</span><span> </span><span>location</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>$</span><span>geoWithin</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>$</span><span>centerSphere</span><span>:</span><span> </span><span>[[</span><span>-122.5</span><span>,</span><span> </span><span>37.7</span><span>],</span><span> </span><span>300</span><span> </span><span>/</span><span> </span><span>3963.2</span><span>]</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>})</span><span>
</span></code></pre>
</div>
<p></p>
<p>and the corresponding query in R,</p>
<p></p>
<div>
<pre><code><span>
</span><span>geoWithin_sph</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'location'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'$geoWithin'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'$centerSphere'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>
</span><span>c</span><span>(</span><span>-122.5</span><span>,</span><span> </span><span>37.7</span><span>),</span><span> </span><span>300</span><span> </span><span>/</span><span> </span><span>3963.2</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span>)</span><span>
</span><span># no need to specify again the &quot;COLLECTION&quot; and &quot;GEOMETRY_NAME&quot; parameters
# as we use the same initialization of the R6 class with the previous query
</span><span>
</span><span>res_geoWithin_sph</span><span> </span><span>=</span><span> </span><span>init</span><span>$</span><span>geoQuery</span><span>(</span><span>QUERY</span><span> </span><span>=</span><span> </span><span>geoWithin_sph</span><span>,</span><span>
</span><span>METHOD</span><span> </span><span>=</span><span> </span><span>&quot;find&quot;</span><span>)</span><span>
</span><span>res_geoWithin_sph</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>location.type</span><span> </span><span>location.coordinates1</span><span> </span><span>location.coordinates2</span><span> </span><span>name</span><span> </span><span>id</span><span>
</span><span>1</span><span>:</span><span> </span><span>Point</span><span> </span><span>-118.90</span><span> </span><span>37.61</span><span> </span><span>Mammoth</span><span> </span><span>Lakes</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6b</span><span>
</span><span>2</span><span>:</span><span> </span><span>Point</span><span> </span><span>-120.24</span><span> </span><span>39.21</span><span> </span><span>Squaw</span><span> </span><span>Valley</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6a</span><span>
</span></code></pre>
</div>
<p></p>
<p>One can read more about the magic number 3963.2 (radius of the Earth) either in the <a rel="nofollow" href="http://thecodebarbarian.com/80-20-guide-to-mongodb-geospatial-queries" target="_blank">first example blog post</a> or in the <a rel="nofollow" href="https://docs.mongodb.com/manual/tutorial/calculate-distances-using-spherical-geometry-with-2d-geospatial-indexes/" target="_blank">MongoDB documentation</a>.</p>
<p></p>
<p>Here one can also plot the output locations using the <strong>leaflet</strong> package,</p>
<p></p>
<div>
<pre><code><span>
</span><span>map_dat</span><span> </span><span>&lt;-</span><span> </span><span>leaflet</span><span>::</span><span>leaflet</span><span>()</span><span>
</span><span>map_dat</span><span> </span><span>&lt;-</span><span> </span><span>leaflet</span><span>::</span><span>addTiles</span><span>(</span><span>map_dat</span><span>)</span><span>
</span><span>map_dat</span><span> </span><span>&lt;-</span><span> </span><span>leaflet</span><span>::</span><span>addMarkers</span><span>(</span><span>map_dat</span><span>,</span><span> </span><span>lng</span><span> </span><span>=</span><span> </span><span>unlist</span><span>(</span><span>res_geoWithin_sph</span><span>$</span><span>location.coordinates1</span><span>),</span><span> </span><span>lat</span><span> </span><span>=</span><span> </span><span>unlist</span><span>(</span><span>res_geoWithin_sph</span><span>$</span><span>location.coordinates2</span><span>))</span><span>
</span><span>map_dat</span><span>
</span></code></pre>
</div>
<p></p>
<p><img alt="Alt text" src="https://i0.wp.com/mlampros.github.io/images/leaflet1.png?w=456" data-recalc-dims="1"></p>
<p></p>
<p>The next query utilizes the <strong>aggregate</strong> method to return the locations <em>sorted by distance from a given point</em>,</p>
<p></p>
<div>
<pre><code><span>
</span><span># MongoDB query
</span><span>
</span><span>db.locations.aggregate</span><span>([{</span><span>
</span><span>...</span><span> </span><span>$</span><span>geoNear</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>near</span><span>:</span><span> </span><span>{</span><span>
</span><span>...</span><span> </span><span>type</span><span>:</span><span> </span><span>'Point'</span><span>,</span><span>
</span><span>...</span><span> </span><span>coordinates</span><span>:</span><span> </span><span>[</span><span>-122.5</span><span>,</span><span> </span><span>37.1</span><span>]</span><span>
</span><span>...</span><span> </span><span>},</span><span>
</span><span>...</span><span> </span><span>spherical</span><span>:</span><span> </span><span>true</span><span>,</span><span>
</span><span>...</span><span> </span><span>maxDistance</span><span>:</span><span> </span><span>900</span><span> </span><span>*</span><span> </span><span>1609.34</span><span>,</span><span>
</span><span>...</span><span> </span><span>distanceMultiplier</span><span>:</span><span> </span><span>1</span><span> </span><span>/</span><span> </span><span>1609.34</span><span>,</span><span>
</span><span>...</span><span> </span><span>distanceField</span><span>:</span><span> </span><span>'distanceFromSF'</span><span>
</span><span>...</span><span> </span><span>}</span><span>
</span><span>...</span><span> </span><span>}])</span><span>
</span></code></pre>
</div>
<p></p>
<p>and the corresponding query in R,</p>
<p></p>
<div>
<pre><code><span>
</span><span>query_geonear</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>'$geoNear'</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>near</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>
</span><span>type</span><span> </span><span>=</span><span> </span><span>&quot;Point&quot;</span><span>,</span><span> </span><span>coordinates</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>-122.5</span><span>,</span><span> </span><span>37.1</span><span>)</span><span>
</span><span>),</span><span> </span><span>distanceField</span><span> </span><span>=</span><span> </span><span>&quot;distanceFromSF&quot;</span><span>,</span><span> </span><span>maxDistance</span><span> </span><span>=</span><span> </span><span>900</span><span> </span><span>*</span><span> </span><span>1609.34</span><span>,</span><span>
</span><span>distanceMultiplier</span><span> </span><span>=</span><span> </span><span>1</span><span> </span><span>/</span><span> </span><span>1609.34</span><span>,</span><span> </span><span>spherical</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>)</span><span>
</span><span>)</span><span>
</span><span>func_quer_geonear</span><span> </span><span>=</span><span> </span><span>init</span><span>$</span><span>geoQuery</span><span>(</span><span>QUERY</span><span> </span><span>=</span><span> </span><span>query_geonear</span><span>,</span><span> </span><span>METHOD</span><span> </span><span>=</span><span> </span><span>&quot;aggregate&quot;</span><span>)</span><span>
</span><span>func_quer_geonear</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>distanceFromSF</span><span> </span><span>location.type</span><span> </span><span>location.coordinates1</span><span> </span><span>location.coordinates2</span><span> </span><span>name</span><span> </span><span>id</span><span>
</span><span>1</span><span>:</span><span> </span><span>190.8044</span><span> </span><span>Point</span><span> </span><span>-120.24</span><span> </span><span>39.21</span><span> </span><span>Squaw</span><span> </span><span>Valley</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6a</span><span>
</span><span>2</span><span>:</span><span> </span><span>201.0443</span><span> </span><span>Point</span><span> </span><span>-118.90</span><span> </span><span>37.61</span><span> </span><span>Mammoth</span><span> </span><span>Lakes</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6b</span><span>
</span><span>3</span><span>:</span><span> </span><span>863.9478</span><span> </span><span>Point</span><span> </span><span>-106.82</span><span> </span><span>39.18</span><span> </span><span>Aspen</span><span> </span><span>5984</span><span>a</span><span>0</span><span>b</span><span>742</span><span>b</span><span>2563</span><span>fb5838f6c</span><span>
</span></code></pre>
</div>
<h3>queries based on the <a rel="nofollow" href="https://docs.mongodb.com/manual/geospatial-queries/" target="_blank">second (MongoDB) documentation example</a></h3>
<p></p>
<p>I picked this documentation example in order to show how someone can use the <strong>command</strong> METHOD besides the <strong>find</strong> and <strong>aggregate</strong> methods.</p>
<p></p>
<p>First I’ll build a new collection (<em>places</em>) and then I’ll insert the example data,</p>
<p></p>
<div>
<pre><code><span>
</span><span>places_col</span><span> </span><span>=</span><span> </span><span>init_db</span><span>$</span><span>create_collection</span><span>(</span><span>&quot;places&quot;</span><span>)</span><span> </span><span># create a new collection
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># important : the property-names of each geojson object should be of type character string
</span><span>
</span><span>place1</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot;: &quot;Central Park&quot;,
&quot;location&quot;: { &quot;type&quot;: &quot;Point&quot;, &quot;coordinates&quot;: [ -73.97, 40.77 ] },
&quot;category&quot;: &quot;Parks&quot;
}'</span><span>
</span><span>place2</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot;: &quot;Sara D. Roosevelt Park&quot;,
&quot;location&quot;: { &quot;type&quot;: &quot;Point&quot;, &quot;coordinates&quot;: [ -73.9928, 40.7193 ] },
&quot;category&quot;: &quot;Parks&quot;
}'</span><span>
</span><span>place3</span><span> </span><span>=</span><span> </span><span>'{
&quot;name&quot;: &quot;Polo Grounds&quot;,
&quot;location&quot;: { &quot;type&quot;: &quot;Point&quot;, &quot;coordinates&quot;: [ -73.9375, 40.8303 ] },
&quot;category&quot;: &quot;Stadiums&quot;
}'</span><span>
</span><span># create a vector of character strings
</span><span>
</span><span>doc_FILES</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>place1</span><span>,</span><span> </span><span>place2</span><span>,</span><span> </span><span>place3</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>geoInsert</span><span>(</span><span>DATA</span><span> </span><span>=</span><span> </span><span>doc_FILES</span><span>,</span><span> </span><span># insert data
</span><span> </span><span>TYPE_DATA</span><span> </span><span>=</span><span> </span><span>'dict_many'</span><span>,</span><span> </span><span># character vector of strings as input
</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>places_col</span><span>,</span><span> </span><span># specify the relevant collection
</span><span> </span><span>GEOMETRY_NAME</span><span> </span><span>=</span><span> </span><span>&quot;location&quot;</span><span>)</span><span> </span><span># give the 'geometry name' of each geo-object
</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span># outputs the collection names
</span><span>
</span><span>init_db</span><span>$</span><span>collection_names</span><span>()</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;places&quot;</span><span> </span><span>&quot;example_col&quot;</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span>places_col</span><span>$</span><span>count</span><span>()</span><span> </span><span># number of geojson objects in collection
</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>3</span><span>
</span></code></pre>
</div>
<p></p>
<p>After the data is inserted one can now query the data using the <strong>command</strong> METHOD.</p>
<p></p>
<p>Worth mentioning for this particular method are the differences between MongoDB and PyMongo. The following code chunk shows the MongoDB <em>runCommand</em>,</p>
<p></p>
<div>
<pre><code><span>
</span><span>db.runCommand</span><span>(</span><span>
</span><span>{</span><span>
</span><span>geoNear</span><span>:</span><span> </span><span>&quot;places&quot;</span><span>,</span><span>
</span><span>near</span><span>:</span><span> </span><span>{</span><span> </span><span>type</span><span>:</span><span> </span><span>&quot;Point&quot;</span><span>,</span><span> </span><span>coordinates</span><span>:</span><span> </span><span>[</span><span> </span><span>-73.9667</span><span>,</span><span> </span><span>40.78</span><span> </span><span>]</span><span> </span><span>},</span><span>
</span><span>spherical</span><span>:</span><span> </span><span>true</span><span>,</span><span>
</span><span>query</span><span>:</span><span> </span><span>{</span><span> </span><span>category</span><span>:</span><span> </span><span>&quot;Parks&quot;</span><span> </span><span>}</span><span>
</span><span>}</span><span>
</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<p>which corresponds to the following query in <em>GeoMongo</em> (similar to PyMongo),</p>
<div>
<pre><code><span>
</span><span>Args_Kwargs</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>&quot;geoNear&quot;</span><span>,</span><span> </span><span>&quot;places&quot;</span><span>,</span><span>
</span><span>near</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>&quot;type&quot;</span><span> </span><span>=</span><span> </span><span>&quot;Point&quot;</span><span>,</span><span> </span><span>&quot;coordinates&quot;</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>-73.9667</span><span>,</span><span> </span><span>40.78</span><span>)),</span><span>
</span><span>spherical</span><span> </span><span>=</span><span> </span><span>TRUE</span><span>,</span><span>
</span><span>query</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>&quot;category&quot;</span><span> </span><span>=</span><span> </span><span>&quot;Parks&quot;</span><span>))</span><span>
</span></code></pre>
</div>
<p></p>
<p>Information about the various parameters of the <em>command</em> method can be found in the <a rel="nofollow" href="http://api.mongodb.com/python/current/api/pymongo/database.html?highlight=command#pymongo.database.Database.command" target="_blank">PyMongo documentation</a>.</p>
<p></p>
<p>Then the GeoMongo <strong>command</strong> method takes the parameters in the same way as the <em>find</em> or <em>aggregate</em> methods,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>geoQuery</span><span>(</span><span>QUERY</span><span> </span><span>=</span><span> </span><span>Args_Kwargs</span><span>,</span><span> </span><span>METHOD</span><span> </span><span>=</span><span> </span><span>&quot;command&quot;</span><span>,</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>places_col</span><span>,</span><span> </span><span>DATABASE</span><span> </span><span>=</span><span> </span><span>init_db</span><span>,</span><span> </span><span># additionally I have to specify the database
</span><span>
</span><span>TO_LIST</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<p>which returns only the ‘Parks’ (of the <em>category</em> property name) from the input documents,</p>
<div>
<pre><code><span>
</span><span>obj.category</span><span> </span><span>obj.location.type</span><span> </span><span>obj.location.coordinates1</span><span> </span><span>obj.location.coordinates2</span><span> </span><span>obj.name</span><span> </span><span>dis</span><span> </span><span>id</span><span>
</span><span>Parks</span><span> </span><span>Point</span><span> </span><span>-73.9700</span><span> </span><span>40.7700</span><span> </span><span>Central</span><span> </span><span>Park</span><span> </span><span>1147.422</span><span> </span><span>5985</span><span>b</span><span>4</span><span>d</span><span>242</span><span>b</span><span>2563</span><span>fb5838f6e</span><span>
</span><span>Parks</span><span> </span><span>Point</span><span> </span><span>-73.9928</span><span> </span><span>40.7193</span><span> </span><span>Sara</span><span> </span><span>D.</span><span> </span><span>Roosevelt</span><span> </span><span>Park</span><span> </span><span>7106.506</span><span> </span><span>5985</span><span>b</span><span>4</span><span>d</span><span>242</span><span>b</span><span>2563</span><span>fb5838f6f</span><span>
</span></code></pre>
</div>
<p></p>
<p>The following two blog posts include also a variety of geospatial queries ( <a rel="nofollow" href="http://tugdualgrall.blogspot.gr/2014/08/introduction-to-mongodb-geospatial.html" target="_blank">here</a> and <a rel="nofollow" href="https://docs.mongodb.com/manual/tutorial/geospatial-tutorial/" target="_blank">here</a> ).</p>
<p></p>
<p>More details about the <em>geomongo</em> R6 class and each method (<em>read_mongo_bson()</em>, <em>geoInsert()</em>, <em>geoQuery()</em>) can be found in the <em>Details</em> and <em>Methods</em> of the package documentation.</p>
<p></p>
<h3>When to input data in bson rather than in json format (applies to the geomongo R6 class)</h3>
<p></p>
<p>When inserting data to MongoDB there are cases where the <em>id</em> appears in the following format,</p>
<div>
<pre><code><span>
</span><span># data taken from : https://docs.mongodb.com/manual/tutorial/geospatial-tutorial/
</span><span>
</span><span>example_dat</span><span> </span><span>=</span><span> </span><span>'{&quot;_id&quot;:
{&quot;$oid&quot;:&quot;55cba2476c522cafdb053add&quot;},
&quot;location&quot;:
{&quot;coordinates&quot;:[-73.856077,40.848447],&quot;type&quot;:&quot;Point&quot;},
&quot;name&quot;:&quot;Morris Park Bake Shop&quot;}'</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span>bson_col</span><span> </span><span>=</span><span> </span><span>init_db</span><span>$</span><span>create_collection</span><span>(</span><span>&quot;example_bson&quot;</span><span>)</span><span> </span><span># create a new collection
</span><span>
</span></code></pre>
</div>
<p></p>
<p>Inserting the <em>example_dat</em> in the <em>bson_col</em> will raise an error,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>geoInsert</span><span>(</span><span>DATA</span><span> </span><span>=</span><span> </span><span>example_dat</span><span>,</span><span> </span><span># insert data
</span><span> </span><span>TYPE_DATA</span><span> </span><span>=</span><span> </span><span>'dict_one'</span><span>,</span><span> </span><span># single list as input
</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>bson_col</span><span>,</span><span> </span><span># specify the relevant collection
</span><span> </span><span>GEOMETRY_NAME</span><span> </span><span>=</span><span> </span><span>&quot;location&quot;</span><span>,</span><span> </span><span># give the 'geometry name' of each geo-object
</span><span> </span><span>read_method</span><span> </span><span>=</span><span> </span><span>&quot;geojsonR&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>Error</span><span> </span><span>in</span><span> </span><span>py_call_impl</span><span>(</span><span>callable</span><span>,</span><span> </span><span>dots</span><span>$</span><span>args</span><span>,</span><span> </span><span>dots</span><span>$</span><span>keywords</span><span>)</span><span> </span><span>:</span><span> </span><span>InvalidDocument</span><span>:</span><span> </span><span>key</span><span> </span><span>'$oid'</span><span> </span><span>must</span><span> </span><span>not</span><span> </span><span>start</span><span> </span><span>with</span><span> </span><span>'$'</span><span>
</span></code></pre>
</div>
<p></p>
<p>This error is explained also in a similar <a rel="nofollow" href="https://stackoverflow.com/questions/42089045/bson-errors-invaliddocument-key-oid-must-not-start-with-trying-to-insert" target="_blank">StackOverflow question</a></p>
<p></p>
<p>In such a case, one has to change the <em>read_method</em> to <strong>mongo_bson</strong> to correctly insert the data,</p>
<p></p>
<div>
<pre><code><span>
</span><span>init</span><span>$</span><span>geoInsert</span><span>(</span><span>DATA</span><span> </span><span>=</span><span> </span><span>example_dat</span><span>,</span><span> </span><span># insert data
</span><span> </span><span>TYPE_DATA</span><span> </span><span>=</span><span> </span><span>'dict_one'</span><span>,</span><span> </span><span># single character string as input
</span><span> </span><span>COLLECTION</span><span> </span><span>=</span><span> </span><span>bson_col</span><span>,</span><span> </span><span># specify the relevant collection
</span><span> </span><span>GEOMETRY_NAME</span><span> </span><span>=</span><span> </span><span>&quot;location&quot;</span><span>,</span><span> </span><span># give the 'geometry name' of each geo-object
</span><span> </span><span>read_method</span><span> </span><span>=</span><span> </span><span>&quot;mongo_bson&quot;</span><span>)</span><span>
</span></code></pre>
</div>
<p></p>
<p>Finally, we can check the correctness of the inserted data,</p>
<p></p>
<div>
<pre><code><span>
</span><span>bson_col</span><span>$</span><span>count</span><span>()</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>1</span><span>
</span></code></pre>
</div>
<p></p>
<div>
<pre><code><span>
</span><span>bson_col</span><span>$</span><span>find_one</span><span>()</span><span>
</span></code></pre>
</div>
<div>
<pre><code><span>
</span><span># example output
</span><span>
</span><span>$</span><span>`_id`</span><span>
</span><span>55</span><span>cba2476c522cafdb053add</span><span>
</span><span>$</span><span>location</span><span>
</span><span>$</span><span>location</span><span>$</span><span>type</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Point&quot;</span><span>
</span><span>$</span><span>location</span><span>$</span><span>coordinates</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>-73.85608</span><span> </span><span>40.84845</span><span>
</span><span>$</span><span>name</span><span>
</span><span>[</span><span>1</span><span>]</span><span> </span><span>&quot;Morris Park Bake Shop&quot;</span><span>
</span></code></pre>
</div>
<p></p>
<p>The <em>README.md</em> file of the <em>GeoMongo</em> package includes the SystemRequirements and installation instructions.</p>
<p>An updated version of the GeoMongo package can be found in my <a rel="nofollow" href="https://github.com/mlampros/GeoMongo" target="_blank">Github repository</a> and to report bugs/issues please use the following link, <a rel="nofollow" href="https://github.com/mlampros/GeoMongo/issues" target="_blank">https://github.com/mlampros/GeoMongo/issues</a>.</p>
<p></p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://mlampros.github.io/mlampros.github.io/2017/08/07/the_GeoMongo_package/"> mlampros</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/opeNGhpaLOw" height="1"></a></div>