{"id":100940,"date":"2024-01-22T21:31:46","date_gmt":"2024-01-22T21:31:46","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=100940"},"modified":"2024-11-14T22:15:35","modified_gmt":"2024-11-14T22:15:35","slug":"querying-mongodb-documents","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/nosql\/mongodb\/querying-mongodb-documents\/","title":{"rendered":"Querying MongoDB Documents"},"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<p>MongoDB provides an efficient environment for storing document data at scale. However, most of your interactions with MongoDB will not be related to storing data but rather to querying data. The better you understand how to retrieve the data you need, the more effectively you can interact with MongoDB and support your data-driven applications.<\/p>\n<p>To help you get started, this article introduces you to various ways you can query document data in a MongoDB database. I demonstrate how to use both MongoDB Shell and the MongoDB Compass GUI when interacting with your collection data.<\/p>\n<p>Keep in mind, however, that building MongoDB queries is an extensive and many-faceted topic, one that can easily justify multiple articles (if not a book or two). In this article, I introduce you to the basics, with the goal of helping you create a foundation on which you can continue to build. The better you understand the concepts presented here, the more easily you\u2019ll be able to move onto more advanced topics.<\/p>\n<p>Note: For the examples in this article, I used MongoDB Atlas and MongoDB Compass. The last section of this article\u2014\u201cAppendix: Preparing your MongoDB environment\u201d\u2014provides information about how to set up your environment and includes a link to a .json file that you\u2019ll need to download if you want to try out these examples for yourself.<\/p>\n<h2>Querying documents in a MongoDB collection<\/h2>\n<p>When working in MongoDB Compass, you have two options for finding documents in a collection. You can use MongoDB Shell, which is embedded in Compass, or you can use the graphical components of the Compass interface. I plan to demonstrate both approaches.<\/p>\n<p>The graphical features in Compass are useful when learning about MongoDB or when you want to run ad hoc queries. Compass also makes it easier to view the documents returned by your queries. However, you\u2019ll likely want to work in the shell as well, especially as you gain experience with MongoDB. The shell can be faster and more efficient for some operations, and it enables you to run shell scripts.<\/p>\n<p>By learning both approaches, you can see first-hand how the shell commands and GUI features relate to each other, which can lead to a better understanding of both approaches. You\u2019ll also be able to better decide which approach is best for you from one situation to the next as you become more comfortable with retrieving MongoDB data.<\/p>\n<p>When running queries in the shell, you\u2019ll often use a <code>find<\/code> statement that specifies which documents to include in the results and which fields to include in the documents. A <code>find<\/code> statement is actually a call to the <code>find<\/code> method, which is one of the method\u2019s available to a collection object. The following syntax shows the basic elements that make up a <code>find<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.collection.find( { filter }, { project } ).options;<\/pre>\n<p>A <code>find<\/code> statement includes both required and optional components. Here\u2019s a breakdown of what each one means:<\/p>\n<ul>\n<li><strong>db.<\/strong> System variable for referencing the current database and accessing the properties and methods available to the database object.<\/li>\n<li><strong><em>collection<\/em>.<\/strong> Placeholder. The name of the target collection.<\/li>\n<li><strong>find.<\/strong> The find method, which is one of the methods available to the collection object for retrieving documents from that collection. For this article, you will be using <code>reports<\/code> as the collection name.<\/li>\n<li><strong><em>filter<\/em>.<\/strong> Placeholder. An optional parameter that determines which documents are returned from the collection. If the parameter is omitted or passed in as an empty document (<code>{}<\/code>), MongoDB returns all documents from the collection. Some MongoDB documentation refers to this element as the query, rather than filter.<\/li>\n<li><strong><em>projection<\/em>.<\/strong> Placeholder. An optional parameter that determines which document fields are included in the results. If the parameter is omitted, MongoDB includes all fields in the returned documents.<\/li>\n<li><strong><em>options<\/em>.<\/strong> Placeholder. One or more optional settings that can be included in a <code>find<\/code> statement to better refine the query.<\/li>\n<\/ul>\n<p>From this syntax, you can see that the simplest <code>find<\/code> statement is one that returns all documents in a collection and all fields within those documents. In other words, the statement includes no optional components, as shown in the following simplified syntax:<\/p>\n<pre class=\"lang:none theme:none\">db.collection.find();<\/pre>\n<p>Before you run a <code>find<\/code> statement in MongoDB Shell, you should first ensure that you\u2019re working within the context of the target database. If you\u2019re not, you should run a <code>use<\/code> statement that specifies that database, which in this case, is <code>weather<\/code>. The <code>weather<\/code> database contains the <code>reports<\/code> collection, both of which are discussed in the appendix. The following <code>use<\/code> statement changes the context to the <code>weather<\/code> database:<\/p>\n<pre class=\"lang:none theme:none\">use weather;<\/pre>\n<p>To run this command, type or paste the statement at the shell\u2019s command prompt and then press Enter. If the shell is not displayed in Compass, click the <strong>&gt;_MONGOSH<\/strong> link at the bottom left corner of the interface. This will expand the bottom window and display the shell\u2019s command prompt, where you can now run the <code>USE<\/code> and other MongoDB statements.<\/p>\n<p>After you run your <code>USE<\/code> statement, you can then run the following <code>find<\/code> statement, which returns all documents in the <code>reports<\/code> collection:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find();<\/pre>\n<p>The collection contains 100 documents; however, the shell displays only 20 documents at a time. To view the next set of documents, you must enter <code>it<\/code>. (The it command stands for iterate.) The following figure shows the <code>find<\/code> statement and a portion of the first document returned by the query.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1010\" height=\"1624\" class=\"wp-image-100941\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-1.png\" \/><\/p>\n<p>As you can see, the figure shows only a small portion of the results, which points to the fact that returning a lot of large documents to the shell can get quite unwieldy. As you progress through this article, you\u2019ll learn various ways to refine your query to get more precise results.<\/p>\n<p>In the meantime, you might find it useful to view only the number of documents that a query would return, rather than returning all those documents. For this, you can use the <code>count<\/code> option, which you tag onto the end of you statement, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find().count();<\/pre>\n<p>To include the <code>count<\/code> option, add a period after the <code>find<\/code> method\u2019s closing parenthesis and then specify the option name, followed by its own set of parentheses. Now the statement will return the value <code>100<\/code>, rather than the documents themselves.<\/p>\n<p>If you want to view the collection\u2019s documents in the Compass GUI instead of the shell, you need only open the collection in the main window. Opening a collection is comparable to running a <code>find<\/code> statement without any of the optional parameters. One of the biggest advantages to using the GUI is that you have three different options for displaying the documents: List View, JSON View, and Table View, which I discussed in the <a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/nosql\/getting-started-with-mongodb\/\">first article in this series<\/a>.<\/p>\n<h2>Adding a basic filter to your MongoDB query<\/h2>\n<p>Now that you understand how to run a <code>find<\/code> statement, you can start adding filters to your queries to control which documents to include in your results. At its most basic, a filter consists of a field name and a field value. The field name comes first and the value follows. The two are separated by a colon and enclosed in curly brackets to define them as an embedded document.<\/p>\n<p>For example, the following <code>find<\/code> statement includes a filter that specifies <code>callLetters<\/code> as the field and <code>GTOT<\/code> as the target value:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"callLetters\": \"GTOT\" } );<\/pre>\n<p>The statement will now return only those documents whose <code>callLetters<\/code> field has a value of <code>GTOT<\/code>. As it turns out, only one document meets this search condition. The following figure shows part of the document as it appears in MongoDB Shell. Notice that the <code>callLetters<\/code> field has a value of <code>GTOT<\/code>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-100942\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-2.png\" width=\"604\" height=\"752\" \/><\/p>\n<p>If you want to return the same results in the Compass GUI, you must take a slightly different approach to defining your filter parameter. Start by locating the <strong>Filter<\/strong> text box that sits above the main GUI window (Just over the Add Data and Export Data buttons). In this box, type or paste the following code snippet:<\/p>\n<pre class=\"lang:none theme:none\">{ \"callLetters\": \"GTOT\" }<\/pre>\n<p>This is the same filter parameter that you defined in the previous <code>Find<\/code> method call. As before, the filter is an embedded document that specifies the <code>callLetters<\/code> field with <code>GTOT<\/code> as the value.<\/p>\n<p>After you add the code to the <strong>Filter<\/strong> text box, click the <strong>Find<\/strong> button, which is to the right of the text box. Compass will then display the single document, as shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-100943\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-3.png\" width=\"1064\" height=\"625\" \/><\/p>\n<p>Notice how much easier it is to view the document in the Compass GUI than in the shell. One thing I want to point out, however, is that you must use the correct upper and lower cases when specifying field and value names, whether using the shell or the graphical features. For example, the following <code>find<\/code> statement uses <code>CallLetters<\/code> (initial cap) rather than <code>callLetters<\/code>, so the statement returns no documents:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"CallLetters\": \"GTOT\" } );<\/pre>\n<p>I also want to point out the <code>findOne<\/code> method, which you can use in place of the <code>find<\/code> method when working with single documents. As its name suggests, the <code>findOne<\/code> method returns only one document. The following example demonstrates how this works:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.findOne( { \"callLetters\": \"GTOT\" } );<\/pre>\n<p>The statement will return the same results as the earlier example because only one document satisfies the search condition. However, if you use the <code>findOne<\/code> method for a query that would otherwise return multiple documents, MongoDB will return only the first document, based on the natural order of the documents on the disk.<\/p>\n<p>In this case, the <code>findOne<\/code> method would be comparable to using the <code>find<\/code> method with the <code>limit<\/code> option, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"callLetters\": \"GTOT\" } ).limit(1);<\/pre>\n<p>The <code>limit<\/code> option specifies the maximum number of documents that the query should return. Because that argument is <code>1<\/code>, only the first document is returned, based on the natural order of the documents on disk. The document is the same one returned by the previous <code>findOne<\/code> statement. For the most part, you should use a <code>findOne<\/code> statement only when you\u2019re working with single documents.<\/p>\n<h2>Basing your query on an array<\/h2>\n<p>In the previous examples, the filter section (the embedded document) references a string field. However, you can also specify other types of fields in your filter, including arrays and embedded documents. For example, the following <code>find<\/code> statement filters the documents based on the <code>sections<\/code> array and the <code>UG2<\/code> value in that array.<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"sections\": \"UG2\" } );<\/pre>\n<p>When you base your filter on an array, you need only supply the field name and value, just like you saw with the string field. You don\u2019t have to be concerned with where the value is positioned in the array. The statement returns all documents in which the <code>sections<\/code> array contains the value <code>UG2<\/code>. Seven documents meet this condition.<\/p>\n<p>You can also achieve the same results in the Compass GUI by entering the following code snippet into the <strong>Filter<\/strong> text box and then clicking <strong>Find<\/strong>:<\/p>\n<pre class=\"lang:none theme:none\">{ \"sections\": \"UG2\" }<\/pre>\n<p>Compass displays the seven returned documents in the main window, as you saw in the previous examples. If you view the values in the <code>sections<\/code> array in each document, you\u2019ll see that they include the <code>UG2<\/code> value.<\/p>\n<p>Now let\u2019s recast the preceding <code>find<\/code> statement as a <code>findOne<\/code> statement and run the new statement in the shell:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.findOne( { \"sections\": \"UG2\" } );<\/pre>\n<p>This example is identical to the previous one except that it uses the <code>findOne<\/code> method. As a result, it returns only the first document. You can achieve the same results by running the following <code>find<\/code> statement, which includes the <code>limit<\/code> option:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"sections\": \"UG2\" } ).limit(1);<\/pre>\n<p>You can also achieve these results in the Compass GUI by entering the following code snippet into the <strong>Filter<\/strong> text box:<\/p>\n<pre class=\"lang:none theme:none\">{ \"sections\": \"UG2\" }<\/pre>\n<p>In addition, you must type <strong>1<\/strong> in the <strong>Limit<\/strong> text box in the query form, as shown in the following figure. To access this form, click the <strong>Options<\/strong> link at the far right of the interface, above the main window. After you define the <strong>Limit<\/strong> option, click the <strong>Find<\/strong> button. MongoDB now returns only a single document. Notice that the document\u2019s <code>sections<\/code> array includes the <code>UG2<\/code> value.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1990\" height=\"1544\" class=\"wp-image-100944\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-4.png\" \/><\/p>\n<p>You\u2019re not limited to searching on only one value in an array. You can search for multiple values by creating an embedded array for the filter\u2019s value. For example, the following <code>find<\/code> statement returns documents whose <code>sections<\/code> array contains either the <code>UG2<\/code> value or the <code>AY1<\/code> value (but not both):<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"sections\": [ \"UG2\", \"AY1\" ] } );<\/pre>\n<p>As it turns out, the <code>reports<\/code> collection includes no documents that contain only one of the two values. However, if you want to return documents that include either one or both values, you can use the <code>$in<\/code> operator as part of the field value:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"sections\": { $in: [ \"UG2\", \"AY1\" ] } } );<\/pre>\n<p>As with many MongoDB operators, when you use the <code>$in<\/code> operator, you define an embedded document as the filter\u2019s field\u2019s value. The embedded document includes the <code>$in<\/code> operator as the embedded document field name and an array as the field value. The array contains the target values.<\/p>\n<p>The <code>$in<\/code> operator returns all documents that include any of the specified values. In this case, it will return any documents that contain the <code>UG2<\/code> value, the <code>AY1<\/code> value, or both. As a result, the <code>find<\/code> statement now returns 93 documents.<\/p>\n<p>In some cases, you might want to return only those documents that contain all the specified array values, in which case, you can use the <code>$all<\/code> operator rather than <code>$in<\/code>, as in this following example:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"sections\": { $all: [ \"UG2\", \"AY1\" ] } } );<\/pre>\n<p>The <code>find<\/code> statement now returns only six documents, which are the only ones that contain both the <code>UG2<\/code> and <code>AY1<\/code> values.<\/p>\n<p>You can also use the <code>$in<\/code> or <code>$all<\/code> operator when setting up your queries in the Compass GUI. For example, you can duplicate the results of the preceding example by entering the following code snippet into the <strong>Filter<\/strong> text box:<\/p>\n<pre class=\"lang:none theme:none\">{ \"sections\": { $all: [ \"UG2\", \"AY1\" ] } }<\/pre>\n<p>After you click <strong>Find<\/strong>, Compass returns the six documents and displays them in the main window. As before, you can view the values in the <code>sections<\/code> array in each document to verify that they each include both the <code>UG2<\/code> and <code>AY1<\/code> values.<\/p>\n<h2>Basing your query on an embedded document<\/h2>\n<p>When working with a MongoDB collection, you\u2019ll likely want to base your queries on embedded documents, just like you saw with arrays. For instance, the documents in the <code>reports<\/code> collection contain the <code>airTemperature<\/code> field, which is an embedded document. One of the fields in the <code>airTemperature<\/code> document is <code>value<\/code>, which takes a numerical value. You can base your statement\u2019s filter on the <code>value<\/code> field and its value, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"airTemperature.value\": 25 } );<\/pre>\n<p>Similar to what you\u2019ve seen in previous examples, the filter parameter is an embedded document that specifies the field and its target value, which is <code>25<\/code>. Notice that the field is specified as a two-part name. The first part is the <code>airTemperature<\/code> field, and the second part is the <code>value<\/code> subfield. As a result, the statement returns only those documents whose <code>airTemperature.value<\/code> field has a value of <code>25<\/code>, which turns out to be six documents.<\/p>\n<p>To return the same results in the Compass GUI, you should enter the same filter (embedded document) in the <strong>Filter<\/strong> text box and then click <strong>Find<\/strong>, just like you did in previous examples:<\/p>\n<pre class=\"lang:none theme:none\">{ \"airTemperature.value\": 25 }<\/pre>\n<p>The Compass main window should now display the same six documents that were returned by the previous <code>find<\/code> statement. You can also drill into the returned documents to verify that they meet the search condition.<\/p>\n<p>In some cases, you might need to dig even deeper into the hierarchy of embedded documents. For instance, the <code>reports<\/code> collection includes documents that contain the <code>wind<\/code> field, which is an embedded document. One of the fields in the embedded document is <code>direction<\/code>, also an embedded document. The <code>direction<\/code> field, in turn, contains the <code>angle<\/code> field, which takes a numerical value.<\/p>\n<p>Suppose you want to retrieve only those documents whose <code>angle<\/code> value is <code>300<\/code>. The following <code>find<\/code> statement demonstrates how to achieve this:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"wind.direction.angle\": 300 } );<\/pre>\n<p>When specifying the <code>angle<\/code> field in your filter, you must qualify the name with the <code>wind<\/code> field, then the <code>direction<\/code> field, and finally the <code>angle<\/code> field. In this case, the <code>angle<\/code> field must have a value of <code>300<\/code> for the document to be returned. Three documents meet this search condition.<\/p>\n<p>As before, you can achieve the same results in the Compass GUI by entering the statement\u2019s filter into the <strong>Filter<\/strong> text box and then clicking <strong>Find<\/strong>:<\/p>\n<pre class=\"lang:none theme:none\">{ \"wind.direction.angle\": 300 }<\/pre>\n<p>The <code>reports<\/code> documents also contain the <code>pastWeatherObservationManual<\/code> field, which is an array. The array contains an embedded document, and the embedded document contains the <code>period<\/code> field, which is also an embedded document. One of the fields in the <code>period<\/code> document is <code>value<\/code>.<\/p>\n<p>You can query the <code>value<\/code> field by again qualifying the name, as you saw before, even though the top-level field is an array. For example, the following <code>find<\/code> statement retrieves those documents whose <code>value<\/code> field has a value of 3:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( { \"pastWeatherObservationManual.period.value\": 3 } );<\/pre>\n<p>In this case, the statement returns 10 documents, but you can mix up your queries in other ways. For instance, you can query arrays embedded in documents and even in other arrays.<\/p>\n<h2>Specifying fields in a MongoDB query<\/h2>\n<p>The examples up to this point showed you different methods of controlling which documents to include in your search results, but you can also control which fields to include in those documents. (Or in other words, what fields to include in your search results.)<\/p>\n<p>To specify the fields, you must add a projection parameter to your statements. The parameter, which follows the filter parameter, is also defined as an embedded document. Within this document, you specify one or more field names, along with a status code that indicates whether to include or exclude the field.<\/p>\n<p>For example, the following <code>find<\/code> statement defines a projection parameter that includes the <code>airTemperature<\/code> and <code>dewpoint<\/code> fields:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"callLetters\": \"GTOT\" },\n  { \"airTemperature\": 1, \"dewPoint\": 1 }\n);<\/pre>\n<p>For each included field, the projection parameter specifies a value of <code>1<\/code>, which means that the two fields should be included in the results. None of the other fields will be included in this output.<\/p>\n<p>The following figure shows the statement and the single document it returns, as they appear in MongoDB Shell. Notice that the results include the <code>_id<\/code> field along with the fields you specified. MongoDB includes the <code>_id<\/code> field automatically unless you specifically tell it not to, which I\u2019ll demonstrate in just a bit.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"992\" height=\"922\" class=\"wp-image-100945\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-5.png\" \/><\/p>\n<p>If you want to achieve the same results in the MongoDB GUI, start by clicking the <strong>Options<\/strong> link to open the query form, as you saw earlier. Then, in the <strong>Filter<\/strong> text box, add the following code snippet:<\/p>\n<pre class=\"lang:none theme:none\">{ \"callLetters\": \"GTOT\" }<\/pre>\n<p>This is just like you defined the filter in the previous examples. The form\u2019s <strong>Filter<\/strong> text box serves as the counterpart to the filter parameter in a <code>find<\/code> statement. Next, enter the following snippet in the <strong>Project<\/strong> text box and click <strong>Find<\/strong>:<\/p>\n<pre class=\"lang:none theme:none\">{ \"airTemperature\": 1, \"dewPoint\": 1 }<\/pre>\n<p>Similar to the <strong>Filter<\/strong> text box, the <strong>Project<\/strong> text box serves as the counterpart to the projection parameter in a <code>find<\/code> statement. The following figure shows the query form with the <strong>Filter<\/strong> and <strong>Project<\/strong> text boxes completed, along with the returned document.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"2004\" height=\"958\" class=\"wp-image-100946\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-6.png\" \/><\/p>\n<p>In some cases, you might want to return all the documents but still limit which fields are returned. You can do this by including an empty filter parameter\u2014a set of curly brackets (<code>{}<\/code>)\u2014in the position where you would normally define the parameter. For example, the following <code>find<\/code> statement is similar to the previous example except that it returns all 100 documents:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( {}, { \"airTemperature\": 1, \"dewPoint\": 1 } );<\/pre>\n<p>Notice that the first argument in the <code>find<\/code> method is the filter parameter, which is simply a set of empty curly brackets. The second argument defines the projection parameter.<\/p>\n<p>As noted earlier, the previous two <code>find<\/code> statements returned the <code>_id<\/code> field along with the requested fields. However, there might be times when you want to omit this field from your results. If this is the case, you should include the <code>_id<\/code> field in your projection parameter, but set its value to <code>0<\/code>, rather than <code>1<\/code>, as in the following example:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"callLetters\": \"GTOT\" },\n  { \"airTemperature\": 1, \"dewPoint\": 1, \"_id\": 0 }\n);<\/pre>\n<p>The <code>_id<\/code> field is somewhat of an anomaly, in terms of how it\u2019s used in a projection. Normally, the parameter\u2019s specified columns must all be set to the same value, either <code>1<\/code> for inclusion or <code>0<\/code> for exclusion (exclusion would return all fields except the excluded ones).<\/p>\n<p>The only exception to this is the <code>_id<\/code> field. As you can see in this example, it\u2019s okay to define it with a different setting than the other fields.<\/p>\n<h2>Adding options to a MongoDB query<\/h2>\n<p>Earlier in the article, you saw examples of <code>find<\/code> statements that included options tagged onto the end. For example, you learned how to use the <code>count<\/code> option to return the number of documents, rather than the actual documents. You also learned about how to use the <code>limit<\/code> option to restrict the number of returned documents to the specified amount.<\/p>\n<p>Another useful option is <code>sort<\/code>, which lets you control how the returned documents are ordered. When you use this option, you include an embedded document as the option\u2019s argument. The embedded document specifies the names of one or more fields on which to base the ordering, along with a code that indicates the sort order. For instance, the following <code>find<\/code> statement specifies that the returned documents should be sorted by the <code>callLetters<\/code> field values, in ascending order:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"sections\": \"UG2\" },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"callLetters\": 1 } );<\/pre>\n<p>The <code>callLetters<\/code> field in the <code>sort<\/code> option is assigned a value of <code>1<\/code>, which indicates ascending order. If you want them sorted in descending order, you should specify <code>-1<\/code>. The following figure shows the statement and several of the returned documents. The statement returns seven documents in all.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1022\" height=\"1692\" class=\"wp-image-100947\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-7.png\" \/><\/p>\n<p>You can duplicate this statement in the Compass GUI, as you saw with other examples. Once again, expand the query form and enter the filter and projection in the <strong>Filter<\/strong> and <strong>Project<\/strong> text boxes, respectively. Then, in the <strong>Sort<\/strong> text box, enter the following snippet and click <strong>Find<\/strong>:<\/p>\n<pre class=\"lang:none theme:none\">{ \"callLetters\": 1 }<\/pre>\n<p>The following figure shows the filled-out query form and part of the results returned by the query.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"2002\" height=\"1532\" class=\"wp-image-100948\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-8.png\" \/><\/p>\n<p>When defining the <code>sort<\/code> option, you can specify multiple fields with different sort orders. For example, the following <code>find<\/code> statement sorts first on the <code>visibility.distance.value<\/code> field, in ascending order, and then on the <code>airTemperature.value<\/code> field, in descending order:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"sections\": \"UG2\" },\n  { \"callLetters\": 1, \"visibility\": 1, \"airTemperature\": 1 }  \n).sort( { \"visibility.distance.value\": 1, \"airTemperature.value\": -1 } );<\/pre>\n<p>The <code>find<\/code> statement returns seven documents. You can achieve the same results in the Compass GUI by entering the following code snippet in the query form\u2019s <strong>Sort<\/strong> box:<\/p>\n<pre class=\"lang:none theme:none\">{ \"visibility.distance.value\": 1, \"airTemperature.value\": -1 }<\/pre>\n<p>Another available option is <code>skip<\/code>, which lets you specify the number of rows to skip when returning documents. According to MongoDB documentation, this capability can be useful when you want to paginate your results. The following <code>find<\/code> statement provides an example of the <code>skip<\/code> option, which specifies that five documents should be skipped:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"sections\": \"UG2\" },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"callLetters\": 1 } ).skip(5);<\/pre>\n<p>Normally, this statement would return seven documents, but now it returns only the last two. If you want to get these same results in the Compass GUI, you must specify the number of documents to bypass in the <strong>Skip<\/strong> text box in the query form, as shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"2002\" height=\"1126\" class=\"wp-image-100949\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-9.png\" \/><\/p>\n<p>MongoDB also lets you stack options at the end of a <code>find<\/code> statement. For instance, the following <code>find<\/code> statement includes both the <code>skip<\/code> option and the <code>collation<\/code> option, which specifies <code>en<\/code> as the <code>locale<\/code> value:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"sections\": \"UG2\" },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"callLetters\": 1 } ).skip(5).collation( { locale: \"en\" } );<\/pre>\n<p>The <code>collation<\/code> option, which is tagged onto the statement after the <code>skip<\/code> option, lets you choose which collation to use for the documents returned by the <code>find<\/code> statement. In this case, the <code>en<\/code> collation is specified, which represents English.<\/p>\n<p>You can also define the collation in the Compass query form. For instance, to achieve the same results as those in the previous example, you would enter the following snippet in the <strong>Collation<\/strong> text box, along with the other code.<\/p>\n<pre class=\"lang:none theme:none\">{ locale: \"en\" }<\/pre>\n<p>The following figure shows the query form after all the text boxes have been filled out, including the <strong>Collation<\/strong> text box. The figure also shows the two documents retuned by the query.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1990\" height=\"1004\" class=\"wp-image-100950\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/word-image-100940-10.png\" \/><\/p>\n<p>There are plenty of other options from which to choose when building your queries. You can learn more about the available options in the MongoDB article <a href=\"https:\/\/www.mongodb.com\/docs\/manual\/reference\/method\/js-cursor\/\">Cursor Methods<\/a>. The options are referred to as cursor methods because the <code>find<\/code> statement returns a cursor object, and the methods build off that object, which is why you can call them in your <code>find<\/code> statements.<\/p>\n<h2>Working with operators in a MongoDB query<\/h2>\n<p>MongoDB also supports the use of operators to help you better refine your queries. For example, you can use comparison operators in your filters as part of the field values, as in the following <code>find<\/code> statement:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"airTemperature.value\": { $lte: 0 } },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"callLetters\": 1 } );<\/pre>\n<p>The statement includes the <code>$lte<\/code> (less than or equal to) operator and specifies <code>0<\/code> as the operator\u2019s value. When you include an operator in your filter parameter, you add it as an embedded document in which the operator is the field name and its value is the target comparison value. In this case, the statement returns all documents whose <code>airTemperature.value<\/code> field has a value less than or equal to <code>0<\/code>. Seven documents meet this search condition.<\/p>\n<p>Another useful operator is <code>$in<\/code>, which you\u2019ve already seen in action. The operator matches any of the values included in the embedded array. For instance, the following <code>find<\/code> statement returns any document whose <code>airTemperature.value<\/code> field has a value of <code>5<\/code>, <code>10<\/code>, <code>15<\/code>, or <code>20<\/code>:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"airTemperature.value\": { $in: [ 5, 10, 15, 20 ] } },\n  { \"callLetters\": 1, \"airTemperature\": 1 }\n).sort( { \"callLetters\": 1 } );<\/pre>\n<p>You can also include multiple operators in your queries. The following <code>find<\/code> statement contains both the <code>$gt<\/code> (greater than) operator and the <code>$lt<\/code> (less than) operator:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \"airTemperature.value\": { $gt: -1, $lt: 1 } },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"callLetters\": 1 } );<\/pre>\n<p>The statement returns only those documents whose <code>airTemperature.value<\/code> field has a value between <code>-1<\/code> and <code>1<\/code>. Only seven documents match this search condition.<\/p>\n<p>Not all operators are comparison operators. For instance, MongoDB also supports element operators. One such operator is <code>$exists<\/code>, which returns documents that either have or don\u2019t have the specified field. The following example demonstrates how this works:<\/p>\n<pre class=\"lang:none theme:none\">db.reports.find( \n  { \n    \"airTemperature.value\": { $gt: 5 },\n    \"skyConditionObservation\": { $exists: false } \n  },\n  { \"callLetters\": 1, \"airTemperature\": 1 }  \n).sort( { \"airTemperature.value\": -1 } );<\/pre>\n<p>The filter parameter defines two search conditions, which are separated by a comma. The first uses the <code>$gt<\/code> (greater than) operator to return only those documents whose <code>airTemperature.value<\/code> field has a value greater than <code>5<\/code>. The second condition uses the <code>$exists<\/code> operator to check whether the <code>skyConditionObservation<\/code> field exists. Because the operator\u2019s value is set to <code>false<\/code>, the results will include only those documents that do not contain this field. Only two documents meet both conditions.<\/p>\n<h2>Getting started with MongoDB queries<\/h2>\n<p>I\u2019ve covered a lot of territory in this article, yet what I\u2019ve shown you here represents only a small sampling of the many ways you can query a MongoDB collection. Not surprisingly, there is much more that you can do with your queries, especially when it comes to defining the filters, whether using MongoDB Shell or the Compass GUI.<\/p>\n<p>I highly recommend that you check out the MongoDB documentation to learn more about each aspect of building a query. A good place to start is with the topic <a href=\"https:\/\/www.mongodb.com\/docs\/manual\/reference\/method\/db.collection.find\/\">db.collection.find()<\/a>. The better you understand how the <code>find<\/code> statement works, the more equipped you\u2019ll be to move onto to other aspects of querying MongoDB data.<\/p>\n<h2>Appendix: Preparing your MongoDB environment<\/h2>\n<p>For the examples in this article, I used MongoDB Atlas for storing the data and MongoDB Compass to work with that data. This is the same approach I used for the previous articles in this series. The first of these articles explains how to set up the environments.<\/p>\n<p>The examples in this article are based on a collection that I created from the <code>sample_weatherdata<\/code> database available through MongoDB Atlas. If you want to try out these examples for yourself, you\u2019ll need to <a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/RobertSheldon_WeatherJSON.zip\">download the document from this site and save as <\/a><strong><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/RobertSheldon_WeatherJSON.zip\">weather.json<\/a><\/strong><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2023\/12\/RobertSheldon_WeatherJSON.zip\"> file<\/a> to a folder that you can access from within MongoDB Compass. You\u2019ll then need to take the following steps to import the data into your collection:<\/p>\n<ol>\n<li>In MongoDB Compass, connect to your cluster on MongoDB Atlas, if you\u2019re not already connected.<\/li>\n<li>In the left panel, click the <strong>Create<\/strong> <strong>database<\/strong> button (plus sign), which is located to the right of the <strong>Databases<\/strong> node.<\/li>\n<li>In the <strong>Create<\/strong> <strong>Database<\/strong> dialog box, type <strong>weather<\/strong> in the <strong>Database<\/strong> <strong>Name<\/strong> text box, type <strong>reports<\/strong> in the <strong>Collection Name<\/strong> text box, and click <strong>Create Database<\/strong>.<\/li>\n<li>After the database and collection have been created, select the <strong>reports<\/strong> collection node in the left panel if it\u2019s not already selected.<\/li>\n<li>In the main window, click the <strong>Add<\/strong> <strong>Data<\/strong> drop-down arrow and click <strong>Import JSON or CSV file<\/strong>.<\/li>\n<li>When your system\u2019s file manager window appears, navigate to the folder that contains the <code>weather.json<\/code> file, select the file, and click <strong>Select<\/strong>. Compass will load the data into the <code>reports<\/code> collection.<\/li>\n<\/ol>\n<p>That\u2019s all you need to do to try out the examples in this article. I plan to go into more detail about both importing and exporting data later in the series.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MongoDB provides an efficient environment for storing document data at scale. However, most of your interactions with MongoDB will not be related to storing data but rather to querying data. The better you understand how to retrieve the data you need, the more effectively you can interact with MongoDB and support your data-driven applications. To&#8230;&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":104578,"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-100940","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\/100940","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=100940"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/100940\/revisions"}],"predecessor-version":[{"id":104579,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/100940\/revisions\/104579"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/104578"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=100940"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=100940"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=100940"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=100940"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}