{"id":104566,"date":"2024-11-26T21:18:58","date_gmt":"2024-11-26T21:18:58","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=104566"},"modified":"2024-11-14T21:45:16","modified_gmt":"2024-11-14T21:45:16","slug":"working-with-mongodb-indexes","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/nosql\/mongodb\/working-with-mongodb-indexes\/","title":{"rendered":"Working with MongoDB Indexes"},"content":{"rendered":"<p><strong>This article is part of Robert Sheldon's continuing series on Mongo DB. To see all of the items in the series, <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/robert-sheldon-ongoing-mongodb-primer\/\">click here<\/a>.<\/strong><\/p>\n\n\n\n\n<p>Throughout this series, I\u2019ve covered a number of topics about working with MongoDB collections and their data. One topic I have not covered is how to work with indexes. Similar to a relational database system, MongoDB lets you create indexes on your collections to help improve query read performance. You can create an index on one or more fields, even if those fields contain embedded documents, geospatial data, or date and time values.<\/p>\n\n\n\n<p>In this article, I demonstrate how to create several types of indexes. You\u2019ll also learn how to view existing indexes, drop indexes, and hide them from the query planner. The examples are based on MongoDB Shell commands, rather than the MongoDB Compass interface. By learning the Shell commands, you\u2019ll be able to better understand the principles behind index creation.<\/p>\n\n\n\n<p>You can access MongoDB Shell through MongoDB Compass or through your system\u2019s command-line interface. Either will serve for this article, where you\u2019ll learn how to create four types of indexes. Although MongoDB also supports other index types, I think you\u2019ll likely use these four basic types initially. From this foundation, you should have no problem creating the other types.<\/p>\n\n\n\n<p>MongoDB indexes can be extremely useful in supporting your data-driven applications, as long as those indexes are implemented with your workloads in mind. Although they can help speed up read operations, they can also slow down write operations because each data modification requires both the document and index data to be updated.<\/p>\n\n\n\n<p>Understanding your workloads\u2019 read-to-write ratios will be a key factor in planning an effective indexing strategy. You can also use tools such as the Performance Advisor in MongoDB Atlas to help you determine how best to implement your indexes. Once you\u2019ve decided to add indexes a collection, this article will help you get started.<\/p>\n\n\n\n<p>Note: For the examples in this article, I used the same MongoDB Atlas environment I used for the previous articles in this series. Refer to the first article for details about setting up these environments. The examples are based on the <code>hr<\/code> database and <code>employees<\/code> collection. You can use a different test database and collection if you like. Just modify the code accordingly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-creating-indexes-in-a-mongodb-collection\">Creating indexes in a MongoDB collection<\/h2>\n\n\n\n<p>You can create an index in MongoDB Shell by using the <code>createIndex<\/code> method, which lets you define different types of indexes based on one or more fields in your collection\u2019s documents. The following syntax shows the basic elements that go into a <code>createIndex<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.collection.createIndex( { key }, { options } );<\/pre>\n\n\n\n<p>The command\u2019s syntax is made up of the following elements:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><strong>db.<\/strong> System variable for referencing the current database and accessing the properties and methods available to the database object. For this article, you need to ensure that <code>hr<\/code> is the current database.<\/li>\n\n\n\n<li><strong><em>collection<\/em>.<\/strong> Placeholder for the target collection. For this article, we will be using the <code>employees<\/code> collection. When you specify a collection, you can access the properties and methods available to the collection object.<\/li>\n\n\n\n<li><strong>createIndex.<\/strong> A method available to the collection object for creating an index in the specified collection.<\/li>\n\n\n\n<li><strong><em>key<\/em>.<\/strong> Placeholder for one or more field\/value pairs. For each pair, you must specify the field on which the index will be based, along with a predefined value that determines the type of index to create on that field. For example, a value of <code>1<\/code> indicates a basic ascending index, a value of <code>-1<\/code> indicates a descending index, and a value of <code>2dsphere<\/code> indicates a type of geospatial index.<\/li>\n\n\n\n<li><strong><em>options<\/em>.<\/strong> Placeholder for one or more optional settings that refine the index definition.<\/li>\n<\/ul>\n<\/div>\n\n\n<p>I\u2019ll demonstrate how all this works shortly, but first, you\u2019ll need to prepare your test environment. Start by ensuring that the <code>hr<\/code> database and <code>employees<\/code> collection are in place and that the collection contains no documents. Then, in MongoDB Shell, run the following <code>insertMany<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.insertMany([\n  { \"_id\": 101, \n    \"name\": \"Drew\", \n    \"emp_id\": \"drews4873\",\n    \"position\": { \n      \"title\": \"Senior Developer\", \n      \"dept\": \"R&amp;D\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -122.3493036, 47.6205131 ] },\n      \"skills\": [ \"Java\", \"SQL\", \"Python\", \"PHP\" ],\n      \"yrs_exp\": 18 } },\n  { \"_id\": 102, \n    \"name\": \"Parker\", \n    \"emp_id\": \"parkerc5927\",\n    \"position\": { \n      \"title\": \"Data Scientist\", \n      \"dept\": \"R&amp;D\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -104.984848, 39.738449 ] },\n      \"skills\": [ \"Python\", \"R\", \"Go\", \"SAS\" ],\n      \"yrs_exp\": 14 } },\n  { \"_id\": 103, \n    \"name\": \"Harper\", \n    \"emp_id\": \"harperd0564\",\n    \"position\": { \n      \"title\": \"Marketing Manager\", \n      \"dept\": \"Marketing\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -73.9653627, 40.7827725 ] },\n      \"yrs_exp\": 22 } },\n  { \"_id\": 104, \n    \"name\": \"Darcy\", \n    \"emp_id\": \"darcyg7432\",\n    \"position\": { \n      \"title\": \"Senior Developer\", \n      \"dept\": \"R&amp;D\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -87.7517243, 41.7855141 ] },\n      \"skills\": [ \"Java\", \"Csharp\", \"Python\", \"R\" ],\n      \"yrs_exp\": 6 } },\n  { \"_id\": 105, \n    \"name\": \"Carey\", \n    \"emp_id\": \"careyr4038\",\n    \"position\": { \n      \"title\": \"SEO Specialist\", \n      \"dept\": \"Marketing\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -84.3732295, 33.7910822 ] },\n      \"yrs_exp\": 7 } },\n  { \"_id\": 106, \n    \"name\": \"Avery\", \n    \"emp_id\": \"averyl2074\",\n    \"position\": { \n      \"title\": \"Network Admin\", \n      \"dept\": \"IT\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -106.6699345, 35.0961125 ] },\n      \"yrs_exp\": 11 } },\n  { \"_id\": 107, \n    \"name\": \"Gabe\", \n    \"emp_id\": \"gabet5387\",\n    \"position\": { \n      \"title\": \"Developer\", \n      \"dept\": \"R&amp;D\",\n      \"location\": {\n        \"type\": \"Point\",\n        \"coordinates\": [ -122.4058344, 37.802379 ] },\n      \"skills\": [ \"Haskell\", \"Fortran\", \"Smalltalk\", \"COBOL\" ],\n      \"yrs_exp\": 8 } }\n]);<\/pre>\n\n\n\n<p>The command adds seven documents to the <code>employees<\/code> collection. When you run the command in MongoDB Shell, you should receive a message that shows the <code>_id<\/code> values of these documents.<\/p>\n\n\n\n<p>As you\u2019ll recall from previous articles in this series, every document in a collection must include the <code>_id<\/code> field. MongoDB automatically creates a unique index on the <code>_id<\/code> field as soon as you create the collection, even before you add any documents to the collection. This ensures that the values inserted into the <code>_id<\/code> field are always unique.<\/p>\n\n\n\n<p>You can view the indexes that are defined on a collection by using the <code>getIndexes<\/code> method available to the collection object. For example, the following command uses the method to retrieve the indexes defined on the <code>employees<\/code> collection:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.getIndexes();<\/pre>\n\n\n\n<p>You do not need to pass in any arguments when calling the <code>getIndexes<\/code> method. By default, it will list all indexes created in the specified collection. In this instance, the method should return only the index defined on the <code>_id<\/code> field, as shown in the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[ { v: 2, key: { _id: 1 }, name: '_id_' } ]<\/pre>\n\n\n\n<p>The results include three field\/value pairs that describe the index. The <code>v<\/code> field, which has a value of <code>2<\/code>, refers the index format version. The next pair is the <code>key<\/code> field and its value of <code>{<\/code> <code>_id<\/code>: <code>1<\/code> <code>}<\/code>. This is the field\/value pair (key) on which the index is based. This is followed by the <code>name<\/code> field, which has a value of <code>_id_<\/code>. This is the name that MongoDB automatically assigns to the index.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-create-a-single-field-index-in-a-mongodb-collection\">Create a single-field index in a MongoDB collection<\/h2>\n\n\n\n<p>MongoDB supports multiple types of indexes. One of the most common is the single-field index, such as the one that MongoDB automatically creates on the <code>_id<\/code> field. You can use the <code>createIndex<\/code> method to define an index on any field in a document. For example, the following <code>createIndex<\/code> command defines an index on the <code>emp_id<\/code> field:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.createIndex( { \"emp_id\": 1 } );<\/pre>\n\n\n\n<p>In this case, the method takes only one argument, the field\/value key pair. The key specifies the target field (<code>emp_id<\/code>), followed by the sort order (<code>1<\/code>). A value of <code>1<\/code> indicates that the index should be sorted in ascending order. A value of <code>-1<\/code> indicates that the index should be sorted in descending order. MongoDB documentation warns against creating descending indexes because they can negatively impact index performance.<\/p>\n\n\n\n<p>When you run the <code>createIndex<\/code> command, MongoDB creates the index and returns the name that is automatically assigned to this index, which is <code>emp_id_1<\/code>. The generated index name is made up of the key\u2019s field\/value pair, with the field and value separated by an underscore.<\/p>\n\n\n\n<p>If the index is a compound index (made up of multiple fields), the index name includes all the key pairs, separated by underscores. Not surprisingly, a complex compound index can result in a very lengthy index name. However, MongoDB lets you name an index when you create it, as you\u2019ll see shortly.<\/p>\n\n\n\n<p>The index itself is made up of the values in the target field, which in this case is <code>emp_id<\/code>. The values are sorted in ascending order. Each entry is associated with a pointer that indicates where the data resides.<\/p>\n\n\n\n<p>After you create an index, you can verify that it has been properly defined by again running a <code>getIndexes<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.getIndexes();<\/pre>\n\n\n\n<p>The command returns the following results, which now show two index listings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'emp_id_1' }\n]<\/pre>\n\n\n\n<p>The first listing is the same one you saw before, the one MongoDB automatically generated on the <code>_id<\/code> field. The second listing is for the index you just created on the <code>emp_id<\/code> field.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-dropping-an-index-in-a-mongodb-collection\">Dropping an index in a MongoDB collection<\/h2>\n\n\n\n<p>In some cases, you might want to update an index definition to better refine it. However, you can\u2019t modify an index except in a few instances, such as hiding or unhiding the index. Instead, you must first drop the index and then re-create it.<\/p>\n\n\n\n<p>You can drop any index except the one that MongoDB automatically creates on the <code>_id<\/code> field. To drop an index in MongoDB Shell, use the <code>dropIndex<\/code> method, as in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.dropIndex(\"emp_id_1\");<\/pre>\n\n\n\n<p>The method takes either one of the following arguments: the index name or its field\/value key. In this example, I\u2019ve used the index name. This is the index you just created. When you run the command, MongoDB removes the index and returns the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{ nIndexesWas: 2, ok: 1 }<\/pre>\n\n\n\n<p>The <code>nIndexesWas<\/code> field shows the number of indexes that existed prior to running the <code>dropIndex<\/code> command. The <code>ok<\/code> field and its <code>1<\/code> value indicate that the command was successfully. If it had been unsuccessful, the value would be <code>0<\/code>. Note that, when you run a command such as <code>dropIndex<\/code> against an Atlas collection, your results will also include cluster-related information, although it will still contain the core information shown here.<\/p>\n\n\n\n<p>After you remove the index, you can then re-create it with an updated definition. For example, the following <code>createIndex<\/code> command again creates an index on the <code>emp_id<\/code> field, but this time the index definition includes two options:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.createIndex( \n  { \"emp_id\": 1 },\n  { name: \"unique_id\", unique: true } );<\/pre>\n\n\n\n<p>Each option is a field\/value pair that sets the value of an index property. The first option is <code>name<\/code>, which assigns the value <code>unique_id<\/code> to the <code>name<\/code> property. As a result, the index will be named <code>unique_id<\/code>, rather than use a name generated automatically by MongoDB. The second option is <code>unique<\/code>, and its value is set to <code>true<\/code>, so the index will be defined as a unique index.<\/p>\n\n\n\n<p>When you run the command, MongoDB should return the index name that you specified in the definition. You can then run a <code>getIndexes<\/code> command to verify your changes. The command should return the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'unique_id', unique: true }\n]<\/pre>\n\n\n\n<p>As you can see, the listing for the new index now includes the name that you assigned to the index and indicates that this is a unique index.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-create-a-compound-index-in-a-mongodb-collection\">Create a compound index in a MongoDB collection<\/h2>\n\n\n\n<p>As already noted, a compound index is one that is made up of multiple fields. You can include up to 32 fields, although you\u2019re more likely to use only two or three. For each field that you include in the index definition, you must specify a field\/value key. The data within the index is grouped by the first specified field, then by the second, and so on.<\/p>\n\n\n\n<p>Compound indexes can be useful when your applications frequently query a specific set of fields. For example, an HR system might often query employee usernames and last names. To improve query performance, you can create a compound index on the two fields. Compound indexes also make it possible to support covered queries, in which the query pulls all the required data from the index, without needing to access the underlying documents.<\/p>\n\n\n\n<p>As with single-field indexes, you can use the <code>createIndex<\/code> method to define a compound index. The main difference is that, with a compound index, you specify two or more field\/value keys, as in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.createIndex( \n  { \"position.dept\": 1, \"position.title\": 1 },\n  { name: \"title_dept\" } );<\/pre>\n\n\n\n<p>The command creates a compound index on the <code>position.dept<\/code> field and the <code>position.title<\/code> field, with both fields sorted in ascending order. Notice that a comma separates the field\/value keys and that the index is named <code>title_dept<\/code>.<\/p>\n\n\n\n<p>In this case, the index has been created on fields in an embedded document. It\u2019s also possible to create an index on the embedded document itself, such as the <code>position<\/code> field. However, for a query to be able to take advantage of such an index, it must specify the entire embedded document, and it must specify the embedded fields in the exact order they\u2019re defined. For example, if you create an index on the <code>position<\/code> field, a query that searches only the <code>position.dept<\/code> field cannot take advantage of the index.<\/p>\n\n\n\n<p>After you create the <code>title_dept<\/code> index, you should again run a <code>getIndexes<\/code> command to verify the new index. The command should now return the following information:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'unique_id', unique: true },\n  {\n    v: 2,\n    key: { 'position.dept': 1, 'position.title': 1 },\n    name: 'title_dept'\n  }\n]<\/pre>\n\n\n\n<p>The third listing provides details about the compound index. As expected, the <code>key<\/code> value reflects both of the field\/value pairs used to define the index.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-hiding-an-index-in-a-mongodb-collection\">Hiding an index in a MongoDB collection<\/h2>\n\n\n\n<p>Earlier in the article, I demonstrated how you can drop an index. You might do this so you can redefine the index or simply because you want to remove it from the collection. In some cases, however, it might be useful to see what impact the index\u2019s removal will have on performance, before you actually drop the index.<\/p>\n\n\n\n<p>You can achieve this by <em>hiding<\/em> the index. When you hide an index, you\u2019re essentially deactivating it and hiding it from the query planner. If hiding the index negatively impacts performance, you can simply <em>unhide<\/em> the index without having to drop and re-create it. The index is still fully maintained when it\u2019s hidden, so it can be enabled with little effort. On the other hand, if hiding the index doesn\u2019t impact performance, you might choose go ahead and drop it.<\/p>\n\n\n\n<p>In MongoDB Shell, you can use the <code>hideIndex<\/code> method to hide an index. For example, the following command uses the method to hide the <code>title_dept<\/code> index that you just created:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.hideIndex( \"title_dept\" );<\/pre>\n\n\n\n<p>The method\u2019s only argument is the name of the target index. When you run the command, MongoDB sets the index as hidden and returns the following message:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{ hidden_old: false, hidden_new: true, ok: 1 }<\/pre>\n\n\n\n<p>The message essentially states that the index was not hidden previously, but now it is. You can verify this change by running a <code>getIndexes<\/code> command, which returns the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'unique_id', unique: true },\n  {\n    v: 2,\n    key: { 'position.dept': 1, 'position.title': 1 },\n    name: 'title_dept',\n    hidden: true\n  }\n]<\/pre>\n\n\n\n<p>The listing for the compound index now shows the <code>hidden<\/code> field as <code>true<\/code>. Note that the <code>getIndexes<\/code> method returns the <code>hidden<\/code> property only if its value is <code>true<\/code>.<\/p>\n\n\n\n<p>If you decide you want to reactivate the index, you can unhide it by running an <code>unhideIndex<\/code> command, as in the following example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.unhideIndex( \"title_dept\" );<\/pre>\n\n\n\n<p>As with the <code>hideIndex<\/code> method, the <code>unhideIndex<\/code> method takes only the target index as its argument. When you run the command, you should receive the following message:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{ hidden_old: true, hidden_new: false, ok: 1 }<\/pre>\n\n\n\n<p>Now the index will be fully operational, which means that the query planner can see the index and use it to optimize performance for queries that rely on the fields specified in the index definition.<\/p>\n\n\n\n<p>You can also configure an index as hidden when you first create it. For this, you need to include the <code>hidden<\/code> option in the index definition and set its value to <code>true<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-create-a-multikey-index-in-a-mongodb-collection\">Create a multikey index in a MongoDB collection<\/h2>\n\n\n\n<p>MongoDB also supports a type of index called multikey, which is simply an index defined on an <code>Array<\/code> field. The index contains all the values within the array, whether scalar values or embedded documents. If an array contains duplicate values, the index will include only one entry for that value.<\/p>\n\n\n\n<p>You do not need to do anything special to define a multikey index. MongoDB automatically creates the index as multikey when you define it on an <code>Array<\/code> field. For example, the following <code>createIndex<\/code> command defines a multikey index on the <code>position.skills<\/code> field:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.createIndex( \n  { \"position.skills\": 1 },\n  { name: \"multi_skills\", sparse: true } );<\/pre>\n\n\n\n<p>Most of the command\u2019s elements you\u2019ve seen before. The index is based on the <code>position.skills<\/code> field, sorted in ascending order, and is named <code>multi_skills<\/code>. Because the field is an array, MongoDB automatically creates the index as multikey.<\/p>\n\n\n\n<p>The index definition also includes the <code>sparse<\/code> option, with its value set to <code>true<\/code>. This option tells MongoDB to exclude entries for documents that do not contain the <code>position.skills<\/code> field. I\u2019ll demonstrate how you can confirm this shortly. But first, run the above <code>createIndex<\/code> command, and then, after you\u2019ve successfully created the index, run a <code>getIndexes<\/code> command. The command should return the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'unique_id', unique: true },\n  {\n    v: 2,\n    key: { 'position.dept': 1, 'position.title': 1 },\n    name: 'title_dept'\n  },\n  {\n    v: 2,\n    key: { 'position.skills': 1 },\n    name: 'multi_skills',\n    sparse: true\n  }\n]<\/pre>\n\n\n\n<p>The fourth listing shows the new multikey index, with the name we specified and the <code>sparse<\/code> property set to <code>true<\/code>. Unfortunately, MongoDB provides no indication that this is a multikey index. All you have to go on is that fact that the <code>position.skills<\/code> field is an array.<\/p>\n\n\n\n<p>However, you can verify that the <code>sparse<\/code> property is giving you the results you want. First, run the following <code>find<\/code> command against the <code>employees<\/code> collection:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.find().count();<\/pre>\n\n\n\n<p>The command uses the <code>find<\/code> method and its <code>count<\/code> method to determine the number of documents in this collection. In this case, the count should be <code>7<\/code>, assuming you didn\u2019t add or remove any other documents from the collection.<\/p>\n\n\n\n<p>Next, run the following <code>find<\/code> command, which also includes the <code>hint<\/code> method:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.find().hint( \"multi_skills\" ).count();<\/pre>\n\n\n\n<p>The command instructs MongoDB to use the <code>multi_skills<\/code> index when determining the document count. As a result, the command will return a count of <code>4<\/code> rather than <code>7<\/code> because only four documents include the <code>position.skills<\/code> field.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-create-a-geospatial-index-in-a-mongodb-collection\">Create a geospatial index in a MongoDB collection<\/h2>\n\n\n\n<p>MongoDB lets you store geospatial data as GeoJSON objects or legacy coordinate pairs in your documents. The sample documents you inserted into the <code>employees<\/code> collection include the <code>position.location<\/code> field, which contains geospatial data stored as GeoJSON objects. For example, the first document includes the following geolocation data:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\"location\": {\n  \"type\": \"Point\",\n  \"coordinates\": [ -122.3493036, 47.6205131 ] },<\/pre>\n\n\n\n<p>The <code>position.location<\/code> field is an embedded document that includes the <code>type<\/code> and <code>coordinates<\/code> fields. The <code>type<\/code> field specifies the GeoJSON object type, which in this case, is <code>Point<\/code>. The <code>Point<\/code> type indicates that the coordinates apply to a specific point location. The <code>coordinates<\/code> field is an array that contains the point\u2019s two coordinates, with the longitude listed first.<\/p>\n\n\n\n<p>Data that is stored as GeoJSON objects is used to represent geographic points or geometrical shapes on an Earth-like sphere. For this reason, they\u2019re commonly used to store location data. However, you can also store geospatial data as legacy coordinate pairs. This makes it possible to store location data on a Euclidean plane, which is flat and two-dimensional. You can learn more about geospatial data in the MongoDB topic <a href=\"https:\/\/www.mongodb.com\/docs\/manual\/geospatial-queries\/\">Geospatial Queries<\/a>.<\/p>\n\n\n\n<p>MongoDB lets you create indexes on either type of geospatial data. When defining a geospatial index, you must use <code>2dsphere<\/code> as the key value for a GeoJSON index and use <code>2d<\/code> as the key value for a legacy index. For example, the following <code>createIndex<\/code> command creates a GeoJSON index on the <code>position.location<\/code> field:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.createIndex( \n  { \"position.location\": \"2dsphere\" },\n  { name: \"geo_location\" } );<\/pre>\n\n\n\n<p>The command creates an index on the entire <code>position.location<\/code> field, even though the coordinates themselves are stored in the <code>position.location.coordinates<\/code> field. The command also names the index <code>geo_location<\/code>.<\/p>\n\n\n\n<p>After you run this command, you can again use a <code>getIndexes<\/code> command to verify the new index. The command should now return the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[\n  { v: 2, key: { _id: 1 }, name: '_id_' },\n  { v: 2, key: { emp_id: 1 }, name: 'unique_id', unique: true },\n  {\n    v: 2,\n    key: { 'position.dept': 1, 'position.title': 1 },\n    name: 'title_dept'\n  },\n  {\n    v: 2,\n    key: { 'position.skills': 1 },\n    name: 'multi_skills',\n    sparse: true\n  },\n  {\n    v: 2,\n    key: { 'position.location': '2dsphere' },\n    name: 'geo_location',\n    '2dsphereIndexVersion': 3\n  }\n]<\/pre>\n\n\n\n<p>The listing for the <code>geo_location<\/code> index looks similar to the others, except that the key value is now <code>2dsphere<\/code>. In addition, the listing includes the <code>2dsphereIndexVersion<\/code> property, which refers the format version used for this type of index.<\/p>\n\n\n\n<p>As you can also see in these results, the <code>getIndexes<\/code> command now returns five index listings, including the default one that MongoDB automatically created on the <code>_id<\/code> field. These are all the indexes that we\u2019re going to cover in this article, so you\u2019re now going to delete the four indexes that you created. For this, you can run the following <code>dropIndexes<\/code> command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">db.employees.dropIndexes();<\/pre>\n\n\n\n<p>The <code>dropIndexes<\/code> method drops all indexes except the one on the <code>_id<\/code> field. This is different from the <code>dropIndex<\/code> method you saw earlier, which removes only the specified index. When you run the <code>dropIndexes<\/code> command, it should return the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{\n  nIndexesWas: 5,\n  msg: 'non-_id indexes dropped for collection',\n  ok: 1\n}<\/pre>\n\n\n\n<p>The results indicate that five indexes existed before the command ran and that all but the <code>_id<\/code> index was dropped. You can confirm this by once again running a <code>getIndexes<\/code> command, which should return the following results:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[ { v: 2, key: { _id: 1 }, name: '_id_' } ]<\/pre>\n\n\n\n<p>As you can see, only the auto-generated index now exists in the <code>employees<\/code> collection.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-getting-started-with-mongodb-indexes\">Getting started with MongoDB indexes<\/h2>\n\n\n\n<p>In this article, I demonstrated how you can create several different types of indexes. However, a single article is not enough to explain everything there is to know about indexes and index types. For example, MongoDB also supports wildcard and hashed indexes and provides additional options for refining your indexes, such as partial and time to live (TTL). I highly recommend that you refer to MongoDB documentation for further information, starting with the topic <a href=\"https:\/\/www.mongodb.com\/docs\/manual\/indexes\/\">Indexes<\/a>.<\/p>\n\n\n\n<p>MongoDB indexes can provide you with a powerful tool for improving query performance. Without an index, a query must scan every document in a collection to get the information it needs. The strategic use of indexes can help improve query execution when accessing the same fields repeatedly, which is especially important for high-volume data operations.<\/p>\n\n\n\n<p>That said, indexes can have a detrimental impact on write performance, so the type of workloads you support will be integral in determining your indexing strategy. Again, refer to the MongoDB documentation for guidelines about creating indexes and measuring their use. Indexes should be an important consideration in your data-delivery strategy, but you should implement them with great care.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Throughout this series, I\u2019ve covered a number of topics about working with MongoDB collections and their data. One topic I have not covered is how to work with indexes. Similar to a relational database system, MongoDB lets you create indexes on your collections to help improve query read performance. You can create an index on&#8230;&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":104567,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,159161],"tags":[5618,159226],"coauthors":[6779],"class_list":["post-104566","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-mongodb","tag-mongodb","tag-mongodbseriesrobertsheldon"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=104566"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104566\/revisions"}],"predecessor-version":[{"id":104571,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/104566\/revisions\/104571"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/104567"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=104566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=104566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=104566"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=104566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}