diff --git a/draft/applications/geospatial-indexes.txt b/draft/applications/geospatial-indexes.txt index f71061dab21..96a19c4c096 100644 --- a/draft/applications/geospatial-indexes.txt +++ b/draft/applications/geospatial-indexes.txt @@ -8,11 +8,13 @@ MongoDB provides rich location aware queries that return documents based on location with a special geospatial index type. This document introduces geospatial data modeling, indexing operations, and provides example queries using the :ref:`geospatial query operators -`. For more information about the -geospatial indexes and operations see the :doc:`/applications/geospatial-indexes`. +`. For more information about +geospatial indexes and operations see the :doc:`/core/geospatial-indexes` document. .. _geospatial-coordinates: +.. This include inserts an introduction to geospatial modeling. + "Representing Coordinate Data" .. include:: /includes/geospatial-coordinates.rst .. index:: geospatial queries @@ -24,7 +26,7 @@ Queries MongoDB provides special :ref:`geospatial query operators ` for performing queries on location data -inside of normal :func:`find() ` operation. The +inside the normal :func:`find() ` method. The :dbcommand:`geoNear` command also returns results using geospatial indexes, but also includes additional geospatial information in the return documents. @@ -37,10 +39,12 @@ return documents. MongoDB can also calculate and return accurate results for locations in a :ref:`spherical ` - coordinate system, suing :ref:`spherical query operations `. + coordinate system, using :ref:`spherical query operations `. .. index:: geospatial queries; exact +.. _geospatial-query-exact: + Exact ~~~~~ @@ -55,11 +59,11 @@ following prototypical form: This query will return any document that where the value of ``[ x, y ]`` is *exactly* the same as the one specified in the query. To return all documents in the ``places`` collection with values in the ``loc`` -field that are exactly ``[ 42, 42 ]``, consider the following example: +field that are exactly ``[ -74, 40.74 ]``, consider the following example: .. code-block:: javascript - db.places.find( { "loc": [ 42, 42 ] } ) + db.places.find( { "loc": [ -74, 40.74 ] } ) Exact geospatial queries only have applicability for a limited selection of cases, :ref:`proximity ` and :ref:`bounded @@ -97,7 +101,7 @@ In addition to :operator:`near`, the :dbcommand:`geoNear` command provides equivalent functionality. :dbcommand:`geoNear` adds additional options and returns more information for each document found. In its most simple form, the :dbcommand:`geoNear` -command has the following prototype form: +command has the following prototypical form: .. code-block:: javascript @@ -110,26 +114,33 @@ in the previous example: db.runCommand( {geoNear: "places", near: [ -74, 40.74 ] } ) +.. seealso:: + + :ref:`geospatial-query-exact` + +.. _geospatial-query-limit: + Limit ````` -To impose a limit on the result set other than the default 100 -document limit, use the :func:`limit() ` method with -:func:`find() ` queries, in the following -prototype operation. +By default, geospatial queries with :func:`find() +` return 100 documents. To impose a limit +on the result set, use the :func:`limit() ` method +with :func:`find() ` operator. The following is +the prototype operation: .. code-block:: javascript db.collection.find( { : { $near: [ x, y ] } } ).limit(n) -The following example, will return only 20 results of the above query: +The following example will return only 20 results of the above query: .. code-block:: javascript db.places.find( { loc: { $near: [ -74, 40.74 ] } } ).limit(20) -You may also use the ``num`` option with the :dbcommand:`geoNear` near -command, as in the following prototype: +You may also use the ``num`` option with the :dbcommand:`geoNear` +command and the ``near`` parameter, as in the following prototype: .. code-block:: javascript @@ -140,11 +151,26 @@ in the previous example: .. code-block:: javascript - db.runCommand( {geoNear: "collection", near: [ -74, 40.74 ], num: 20 } ) + db.runCommand( { geoNear: "collection", near: [ -74, 40.74 ], num: 20 } ) + +The :func:`limit() ` method and ``near`` parameter do not limit +geospatial query results by distance, only the number of returned +:term:`document`. To limit geospatial search results by distance, +please see the :ref:`geospatial-query-distance` section. + +.. note:: + + The :func:`limit() ` method and ``num`` option have + different performance characteristics. Geospatial queries with + :func:`limit() ` method will return 100 documents, + sort them, and finally the limit method is applied. Geospatial + queries with ``num`` option will only return the specified number + of documents unsorted. -.. index:: $maxDistance .. index:: geospatial queries; distance limit +.. _geospatial-query-distance: + Distance ```````` @@ -168,23 +194,25 @@ Specify the distance in the ``maxDistance`` option using the same units as the coordinate system specified. For example, if the indexed location data is in meters, the distance units are also in meters. +See the :ref:`geospatial-query-limit` section to limit geospatial +query results by the number of returned :term:`documents `. + .. _geospatial-within: .. _geospatial-query-bounded: Bounded ~~~~~~~ -Bounded queries return results within the boundaries of a shape -specified in the query. The :operator:`$within` operator allows you to -construct these quires. Bounded queries do not return sorted results: -as a result these queries are faster than :ref:`proximity -` queries. +Bounded queries return documents that have coordinates within a shape +specified in the query. Bounded queries, using the :operator:`$within` +operator do not return sorted results and are faster than +:ref:`proximity queries ` Using the :operator:`$within`, you can specify boundaries with the following shapes: - circles, -- rectangles (i.e. "boxes,") or +- rectangles, - polygons. Bounded queries take the following prototype form: @@ -197,6 +225,9 @@ Bounded queries take the following prototype form: } } ) +See the :ref:`geospatial-query-distance` section to perform geospatial +queries for a particular distance around a certain point. + The following sections provide examples of bounded queries using the :operator:`$within` operator. @@ -237,12 +268,12 @@ corners of the shape, using the :operator:`$within` operator and the The following query will return all documents that have coordinates that exist within the rectangle, where the lower-left corner is at ``[ -0, 0 ]`` and the upper-right corner is at ``[ 5, 5 ]`` using a +0, 0 ]`` and the upper-right corner is at ``[ 3, 3 ]`` using a geospatial index on the ``loc`` field: .. code-block:: javascript - db.places.find( { "loc": { "$within": { "$box": [ [0, 0] , [5, 5] ] } } } ) + db.places.find( { "loc": { "$within": { "$box": [ [0, 0] , [3, 3] ] } } } ) Polygons ```````` @@ -265,7 +296,7 @@ of points: .. code-block:: javascript - [4,0], [3,2], [2,3], [2,4], [4,5] + [0,0], [3,3], [6,0] The following query will return all documents that have coordinates that exist within the bounds of the polygon, where the sides of the @@ -275,20 +306,19 @@ polygon connects at the above points using a geospatial index on the .. code-block:: javascript db.places.find({ "loc": { "$within": { "$polygon": - [4,0], [3,2], [2,3], [2,4], [4,5] - } } }) + [0,0], [3,3], [6,0] } } } ) .. _geospatial-query-spherical: Spherical ~~~~~~~~~ -If the coordinates in your documents represent points on a -spherical plane, :ref:`proximity ` and +If the coordinates in your :term:`document` represent points on a +spherical surface, :ref:`proximity ` and some :ref:`bounded ` queries will not return accurate results. To compensate, you can use the following spherical -queries which adjust for these errors. The following table provides a -list of spherical query operators and their flat system equivalents: +queries that adjust for these differences. The following table provides a +list of spherical query operators and their flat surface equivalents: ========================== =================== Spherical Flat @@ -297,8 +327,8 @@ list of spherical query operators and their flat system equivalents: :operator:`$centerSphere` :operator:`$center` ========================== =================== -The :dbcommand:`geoNear` will return results for spherical systems if -you specify the ``{ spherical: true }`` option to the command. +The :dbcommand:`geoNear` command returns documents assuming a spherical surface if +you specify the ``{ spherical: true }`` option. .. admonition:: Spherical Queries Use Radians for Distance @@ -321,16 +351,19 @@ you specify the ``{ spherical: true }`` option to the command. The following query would return documents from the ``places`` collection, within the circle described by the center ``[ -74, 40.74 ]`` -with a radius of ``100`` kilometers: +with a radius of ``100`` miles: .. code-block:: javascript db.places.find( { loc: { $centerSphere: [ [ -74, 40.74 ] , - 100 / 6378.137 ] } } ) + 100 / 3963.192 ] } } ) Remember that you must convert the distance of the radius to radians. This conversion *must* happen in your client -(i.e. application) code. +(i.e. application) code. You may also use the ``distanceMultiplier`` +option to the :dbcommand:`geoNear` to convert in the :program:`mongod` +process, rather than in your application code. Please see the +:ref:`distance multiplier ` section. The following spherical proximity query, returns all documents in the collection ``places`` within ``100`` miles from the point ``[ -74, @@ -340,10 +373,35 @@ collection ``places`` within ``100`` miles from the point ``[ -74, db.runCommand( { geoNear: "places", near: [ -74, 40.74 ], - maxDistance: { 100 / 3963.192 }, spherical: true } ) +The output of the above command would be: + +.. code-block:: javascript + + { + // [ ... ] + "results" : [ + { + "dis" : 0.01853688938212826, + "obj" : { + "_id" : ObjectId( ... ) + "loc" : [ + -73, + 40 + ] + } + } + ], + "stats" : { + // [ ... ] + "avgDistance" : 0.01853688938212826, + "maxDistance" : 0.01853714811400047 + }, + "ok" : 1 + } + :dbcommand:`geoNear` returns documents in this result set sorted by their distance from the ``[ -74, 40.74 ]`` point. @@ -358,7 +416,116 @@ their distance from the ``[ -74, 40.74 ]`` point. between ``-180`` inclusive, and ``180``, valid values for latitude are between ``-90`` and ``90``. -.. TODO add in distanceMultiplier description +.. _geospatial-distance-multiplier: + +Distance Multiplier +~~~~~~~~~~~~~~~~~~~ + +The ``distanceMultiplier`` option multiplies all distance values in +the ``distance`` field returned by :dbcommand:`geoNear` command by an +assigned value. + + Use ``distanceMultiplier`` with :ref:`spherical queries +` to convert the contents of the +``distance`` field returned in the extra output of the +:dbcommand:`geoNear` command from radians to distances. For more +information about the conversion, see the :ref:`spherical queries +` section. + +.. note:: + + Because ``distanceMultiplier`` is an option to + :dbcommand:`geoNear`, the multiplication operation occurs on the + :program:`mongod` process. The operation adds a slight overhead to + the operation of :dbcommand:`geoNear`. + +Using ``distanceMultiplier`` in spherical queries allows one to use +results from the :dbcommand:`geoNear` command without radian to +distance conversion. The following example uses ``distanceMultiplier`` in the +:dbcommand:`geoNear` command with a :ref:`spherical +` example: + +.. code-block:: javascript + + db.runCommand( { geoNear: "places", + near: [ -74, 40.74 ], + spherical: true, + distanceMultiplier: 3963.192 + } ) + +The output of the above command would be: + +.. code-block:: javascript + + { + // [ ... ] + "results" : [ + { + "dis" : 73.46525170413567, + "obj" : { + "_id" : ObjectId( ... ) + "loc" : [ + -73, + 40 + ] + } + } + ], + "stats" : { + // [ ... ] + "avgDistance" : 0.01853688938212826, + "maxDistance" : 0.01853714811400047 + }, + "ok" : 1 + } + +.. seealso:: + :ref:`Distance operator ` + +.. _geospatial-haystack-queries: + +Querying Haystack Indexes +------------------------- + +Geospatial haystack indexes are a special geospatial index that that +allows MongoDB to optimize the query process for location queries, +given a coordinate and another field in your documents. To create +geospatial indexes with the haystack option and a particular +``bucketSize``, please see: :ref:`Haystack Index +` + +.. note:: + + Haystack indexes are not suited to returning the closest documents to + a particular location, as the closest documents could be far away + compared to the ``bucketSize``. + +The :dbcommand:`geoSearch` is the only way to return results using the +haystack index: :func:`find() ` and +:dbcommand:`geoNear` cannot access the haystack index. You must +specify both the coordinate and other field to geoSearch, which takes +the following prototypical form: + +.. code-block:: javascript + + db.runCommand( { geoSearch: , + search: { : } } ) + +For example, to return all documents with the value +``restaurants`` in the ``type`` field near the example point, the command would resemble: + +.. code-block:: javascript + + db.runCommand( { geoSearch: "places", + search: { type: "restaurant" }, + near: [-74, 40.74] } ) + +.. note:: + + :ref:`Spherical queries ` are + not currently supported by haystack indexes. + +.. _geospatial-multi-location: Multi-location Documents ------------------------ @@ -418,13 +585,17 @@ coordinates. Consider the following prototype data model: ] } -Then, create the geospatial index on the ``addresses.lock`` field as +Then, create the geospatial index on the ``addresses.loc`` field as in the following example: .. code-block:: javascript db.records.ensureIndex( { "addresses.loc": "2d" } ) +To include the location field with the distance field in +multi-location document queries, specify ``includeLocs: true`` +in the :dbcommand:`geoNear` command. + .. the following is a section about the limitations of geospatial indexes in sharding: diff --git a/draft/core/geospatial-indexes.txt b/draft/core/geospatial-indexes.txt index 824e97ce37f..0ce315e0fbb 100644 --- a/draft/core/geospatial-indexes.txt +++ b/draft/core/geospatial-indexes.txt @@ -8,15 +8,15 @@ Overview -------- MongoDB supports location-based queries and geospatial data with a -special index for coordinate data. The index stores :ref:`geohashes +special index for coordinate data. The geospatial index stores :ref:`geohashes `, and makes it possible to return documents based on proximity to a point or within a bounded region. Geospatial -queries support coordinate systems on either flat and spherical planes. +queries support coordinate systems on either flat and spherical surfaces. Additionally, geospatial haystack indexes provide additional support for certain classes of region-based queries. This document introduces the core concepts -that underpin geospatial queries and indexes in MongoDB. For more +that underpin geospatial queries and indexes in MongoDB. For more information, :doc:`/applications/geospatial-indexes` provide complete documentation of all location-based operations and queries. @@ -31,7 +31,7 @@ Geospatial Indexes location data in MongoDB. To use geospatial functions in MongoDB, model -location data in a 2D array and create an index using the +location data in a 2D array, then create an index using the :func:`ensureIndex ` method on this field using the ``2d`` option. Consider the following prototype operation: @@ -39,16 +39,20 @@ using the ``2d`` option. Consider the following prototype operation: db.collection.ensureIndex( { : "2d" } ) -All queries using coordinates will use this geospatial index. -The index uses a :term:`geohash` calculated from the coordinates. -For more information on :term:`geohash`, please refer to the -:ref:`geohash ` section. +After the ``2d`` index has been created, all queries using coordinates +will use this geospatial index. The index uses a :term:`geohash` +calculated from the coordinates. For more information on +:term:`geohash`, please refer to the :ref:`geohash +` section. + +To perform queries on your geospatial data, please see +:doc:`/applications/geospatial-indexes`. .. note:: MongoDB only supports *one* geospatial index per collection. As with any MongoDB index, any single query can only - use one index. Creating more than one geospatial index to a + use one index. Creating more than one geospatial index with a collection will produce unexpected results. .. _geospatial-indexes-range: @@ -56,13 +60,13 @@ For more information on :term:`geohash`, please refer to the Range ~~~~~ -All geospatial indexes are bounded. MongoDB will return an error and -reject documents with coordinate pairs outside of these -boundaries. The default boundaries assume latitude and -longitude data, and are -between -180 inclusive and 180 non-inclusive. +All geospatial indexes are bounded. MongoDB will +return an error and reject documents with coordinate data outside of +the specified range. The default range assumes latitude and longitude +data, and are between -180 inclusive and 180 +non-inclusive (i.e. ``[-180, 180)``.) -To configure the boundaries of a geospatial index, use the ``min`` and +To configure the range of a geospatial index, use the ``min`` and ``max`` options with the :func:`ensureIndex() ` operation, as in the following prototype. @@ -72,7 +76,7 @@ operation, as in the following prototype. { min: , max: } ) The following operation will create an index on the ``places`` -collection, for coordinates in the ``loc`` field, with boundaries +collection, for coordinates in the ``loc`` field, with the range between ``-90`` and ``90``: .. code-block:: javascript @@ -81,7 +85,7 @@ between ``-90`` and ``90``: { min: 90 , max: 90 } ) For more information see the :ref:`geospatial precision -` and :ref:`rehashes +` and :ref:`geohash ` sections. .. _geospatial-indexes-precision: @@ -89,8 +93,8 @@ For more information see the :ref:`geospatial precision Precision ~~~~~~~~~ -Geospatial indexes represent precision, or resolution in -"bits". Higher bit values allow MongoDB to return more precise +Geospatial indexes use "bits" to represent precision, or +resolution. Higher bit values allow MongoDB to return more precise results, at the expense of speed. For more information on the relationship between bits and precision, see the :ref:`geohash ` section. @@ -98,7 +102,7 @@ relationship between bits and precision, see the :ref:`geohash By default, geospatial indexes in MongoDB have 26 bits of precision, although precision is configurable upon index creation and MongoDB supports up to 32 bits of precision. With 26 bits of precision, using -the default range of -180 to 180, results can be precise to roughly 2 +the default range of -180 to 180, geospatial data can be precise to roughly 2 feet or about 60 centimeters. You can set the precision of a geospatial index during creation by @@ -133,7 +137,7 @@ These indexes support regular geospatial queries as well as queries where you mu location and by another field. For example, if you need to return a list of restaurants near a given point, but you want to optionally filter restaurants by type, such as "take-out," or -"bar" stored in a ``type`` field. +"bar" stored in the ``type`` field. .. note:: @@ -148,26 +152,21 @@ filter restaurants by type, such as "take-out," or Haystack Index ~~~~~~~~~~~~~~ -Geospatial haystack indexes make it possible to build a special -``bucket`` for keys in the index to tune the distribution of data. Haystack -indexes improve query performance for queries limited to a specific -area. For more information, please refer to :doc:`Geospatial Indexes -`. - -To improve query performance when filtering geospatial -results along another dimension, consider -using a :ref:`compound index `. +Geospatial haystack indexes make it possible to tune the +distribution of your data and build a special bucket +index. Haystack indexes improve query performance for queries limited +to a specific area. .. note:: Haystack indexes are not suited to returning the closest documents to a particular location, as the closest documents could be far away - compared to the bucket size. + compared to the ``bucketSize``. To build a :term:`geoHaystack` index, specify the ``geoHaystack`` for the location field and a ``bucketSize`` parameter . The ``bucketSize`` parameter determines the granularity of the bucket index. A -``bucketSize`` of 1 creates an index that stores keys within a single unit +``bucketSize`` of ``1`` creates an index that stores keys within a single unit in the coordinate in the same bucket. .. code-block:: javascript @@ -178,19 +177,13 @@ in the coordinate in the same bucket. By default, all queries that use a geospatial haystack index will return 50 documents. -In the following example, the :func:`ensureIndex() -` method creates an index that would support -a query that: returned all locations (e.g. restaurants) in the -``places`` collection within a maximum distance of 2 degrees longitude -or latitude. Create this index using following command: - -.. code-block:: javascript +To query geohaystack indexes, you *must* use the :dbcommand:`geoSearch` +command, please see the :ref:`Querying Haystack Indexes +` section. - db.places.ensureIndex({ loc: "geoHaystack", type: 1} , - { bucketSize: 2 } ) +:ref:`Spherical queries ` are not +supported by haystack indexes. -.. TODO clarify what the type argument does or if it's just always - required. .. _geospatial-spherical-representation: @@ -232,19 +225,21 @@ two bit representation of four quadrants would be: 00 10 These two bit values, ``00``, ``01``, ``10``, and ``11``, represent -each of the quadrants, and points within that quadrant. For a geohash -with two bits of resolution, a point in the top left quadrant would -have the geohash of ``01``. +each of the quadrants, and points within that quadrant. For a +:term:`geohash` with two bits of resolution, a point in the bottom +left quadrant would have a geohash of ``00``. The top left quadrant +would have the geohash of ``01``. The bottom right and top right would +have a geohash of ``10`` and ``11``, respectively. To provide additional precision, continue dividing each quadrant into sub-quadrants. To identify quadrants within a sub-quadrant, take the -containing quadrant (e.g. ``01``) and concatenate the identifier for -the sub-quadrant. Therefore, for -the upper-right quadrant, ``11``, the sub-quadrants would be: +geohash for the containing quadrant (e.g. ``01``) and concatenate the geohash for +the sub-quadrant. Therefore, the geohash for +the upper-right quadrant is ``11``, the geohash for the sub-quadrants would be: ``1101``, ``1111``, ``1110``, and ``1100``. -To calculate a more precise geohash, continue dividing the -sub-quadrant concatenate the two-bit identifier for each division. The +To calculate a more precise :term:`geohash`, continue dividing the +sub-quadrant, concatenate the two-bit identifier for each division. The more "bits" in the hash identifier for a given point, the smaller possible area that the hash can describe, and the higher the resolution of the geospatial index. diff --git a/source/includes/geospatial-coordinates.rst b/source/includes/geospatial-coordinates.rst index ba910f66fff..4dbc031e302 100644 --- a/source/includes/geospatial-coordinates.rst +++ b/source/includes/geospatial-coordinates.rst @@ -9,7 +9,7 @@ that holds a 2 dimensional array. The preferred form is: [ x, y ] Consistency is crucial: all documents must store the values in the -same order. you may also use an embeded document, as in: +same order. You may also use an embeded document, as in: .. code-block:: javascript