4. Mongo Queries
4.1. find()
The find command allows us to retrieve the documents from a collection that match a specified criteria as a JSON document. Its basic syntax is as follows:
| JavaScript | |
|---|---|
We must take into account aspects such as the types of data that we use, which is important, since the document {edad:20} is not the same as {edad:"20"}.
On the other hand, we must also consider that the empty document {} matches all documents, so that the query
db.collection.find({}) would return all the objects in the collection.
4.1.1. What keys to retrieve?
The find command returns the complete documents that match the selection criteria. If we don't want to get all the keys, we can specify which keys we want to query for, by enclosing them in a second parameter:
| JavaScript | |
|---|---|
As we can see, this second parameter is also expressed in JSON format (again) and is made up of two keys (key_1 and key_2), both with a value of 4. This numerical value is also interpreted with the value true. That is, we specify here which are the fields that we want to show. In case we want to show all the fields and hide some, we would use the same syntax, but now using a 0 for those fields that we want to hide.
4.1.2. Comparison operations
MongoDB allows us to perform comparisons with numeric data, always using the JSON document format
db.collection.find({key: {$operator:value} });
The comparison operators that we can use in MongoDB are:
$lt→ Less Than$lte→ Less than or equal to$gt→ Greater than$gte→ Greater than or equal to
4.1.3. OR operation
If we want to perform a filter or query where several conditions are met (an AND operation), we will only have to separate them by commas in the same JSON document that we use as criteria. On the other hand, if what we want is to carry out an OR operation, we must use a special operator.
4.1.4. $IN and $NIN operators
A special case of OR is when we want to check if a field is within a specific set of values. That is, if it is one or another value. For this we use the $in operator, as follows:
| JavaScript | |
|---|---|
Similarly, there is the operator $nin (Not In), which gets the documents, where the specified value is not found in the list. We must bear in mind that in this last case those documents that have a null value for the key will also be shown.
4.1.5. The $OR operator
When we want to perform the OR operation on different fields of the document, we will use the $OR operator, to which we pass a vector of possible conditions, as follows:
| JavaScript | |
|---|---|
Attention
Any of last condition is a json condition
4.1.6. The $NOT operator
The $NOT operator is a metaconditional operator, that is, it is always applied to another criterion, inverting its certainty value. Your syntax would be:
| JavaScript | |
|---|---|
The $EXISTS operator
Let's remember that in MongoDB, the documents do not have a common structure or schema, so it is possible that there are keys defined in only some of them. The $exists operator is used to check the existence or not of a certain key.
The syntax to use would be:
| JavaScript | |
|---|---|
With which we obtain the documents for which the key exists or not, depending on whether we have indicated true or false in the query.
4.2. Query results and data types
Data types in MongoDB can have some special behaviors. We are going to see some cases, to know what to do in certain situations.
4.2.1. null values
The null value matches the following situations:
- When the value of the key is null, or
- When the key does not exist in the document (in this case, it is usually said that the field is not informed)
4.2.2. Regular expressions and character strings
When we apply a document filter by a text field, we may not know exactly the value of the field we want to filter by. Regular expressions offer a very powerful mechanism for matching strings.
MongoDB allows us to use these expressions in several ways, either by using regular Javascript expressions or by using the $regex operator, which uses Perl Compatible Regular Expressions (PCRE). Javascript regular expressions are expressed using the following syntax:
| JavaScript | |
|---|---|
As we can see, we use a pattern similar to a text string, but using the slash / as the delimiter instead of the quotes ('). For its part, if we use the $regex operator, we can use the following syntax:
| JavaScript | |
|---|---|
We could find several options for regular expressions:
i→ Matches are case-insensitive:{name:/john/i}{name: { $regex: 'john',$options: 'i'}}m→ Allows you to include characters such as^or$, to match at the beginning or end, in strings with multiple lines.{name:/^John/m}{name: { $regex: 'John', $options: 'm'}}xIgnores whitespace in the$regexpattern, as long as it is not escaped or included in a character class{name: { $regex: ' J oh n',$options: 'x'}}sAllows the period character (.) to represent any character, including the new line character.{name:/ju.n/s}{name: { $regex: 'thu.n',$options: 's'}}
You can find more information regarding regular expressions and particular cases in which it is recommended to use one type of expression or another in the official MongoDB documentation about $regex here.
4.3. Query data type considerations
4.3.1. Queries with arrayas
To search for matching elements within an array, we proceed with the same syntax as if it were any other key, using the query document {key:value}, the key being an array, and the value, either n value that must contain the array, or another ordered vector that we want it to match exactly.
For instance:
db.collection.find({ my_vector : value })→ It matches all the documents in whose vectormy_vectorappears, in the position that is the indicated value.db.users.find({roles:"admin"})show users that inrolesarray has admin role (or others).db.collection.find({ my_vector : [value] })→ Matches all documents whose vectormy_vectorappears only the indicated value.db.users.find({roles:["admin"]})show users who has exactely admin role.
In addition, we can also use regular expressions or the rest of the operators that we have seen as conditions.
On the other hand, we can also refer to a specific element of the vector by its index, using the dot notation and between quotes:
db.collection.find({"my_vector.position" :[value]})db.users.find({"roles.2":["admin"]})show user who third role is admin
4.3.2. The $all operator
With $all we can specify more than one matching element within the array:
db.collection.find({ my_vector : {$all:[value1, value2,...]}})db.users.find({roles:{$all:["mod","admin"]}})show users who have mod and admin role (and possibly more).
4.3.3. The $size operator
Using $size we can include conditions on the length of the vectors:
db.collection.find({ my_vector : {$size:size} })
4.3.4. The $slice operator
The slice operator allows us to obtain a subset of the elements of the vector, with the following syntax:
key: {$slice: x}:- if x>0 gets the first x elements
- if x<0, get the last x elements
key: {$slice: [ x , y ] }Gets y elements from the element at position x embedded document
To query embedded documents, simply specify the full key path, enclosed in quotes and separated by dots:
db.collection.find({"path.to.key":value_or_condition})
4.4. Cursors
When we perform a query, MongoDB returns the results using cursors, which are pointers to the query results, like connectors in unit 2. Clients using Mongo iterate over these cursors to retrieve the results, and offer a set of functionality, such as limiting the results, etc.
When we perform a query on a database with many results, the client (mongosh) returns only 20 results and the message Type "it" for more, to continue iterating the cursor.
Limit, Skip and Sort
MongoDB allows us to make certain limitations on the results. Among them, we can highlight:
limit→ To limit the number of resultsskip→ Skips a specific number of results.sort→ Sorts the results. You need a JSON object with the keys to sort, and a value of 1 to sort ascending or -1 to sort descending.
4.5. Introduction to the Aggregation Framework
The aggregation queries that we performed with operators such as GROUP BY, SUM, or COUNT in SQL can be performed with the MongoDB Aggregation Framework. Aggregate queries have the following syntax:
| JavaScript | |
|---|---|
The pipeline or pipe has a concept similar to Unix pipes: the results of an order are passed as input to another, to obtain results jointly.
The operations that we can perform within these aggregate queries are:
$project→ To perform a projection on an input data set, adding, removing or recalculating fields so that the output is different.$match→ Filters the input to reduce the number of documents, leaving only those that meet certain conditions.$limit→ Restricts the number of results.$skip→ Skip a certain number of records.$unwind→ Converts an array to return it separated in documents.$group→ Groups documents according to a certain condition.$sort→ Sorts a set of documents, according to the specified field.$geoNear→ It is used as geospatial data, returning the documents ordered by proximity according to a geospatial point.
To perform calculations on the data produced by the pipes, we will use expressions. Expressions are functions that perform a certain operation on a group of documents, vector or specific field. Some of these expressions are $max, $min, $divide, or $substr.
You can find much more information about the Aggregation Framework in the official MongoDB documentation.
4.6. Exercises
We are still working on the movie collection. In this case, we are going to use the mongosh terminal (or robo3t as you prefeer), and perform the following queries on this collection.
- Obtain all the productions that either premiered in
2015or are of theseriestype. - Get all the movies NOT released between the years
2000and2002. - Get all movies for which the "directors" key is not defined
- Get the title of all movies that start with the string
star wars, regardless uppercase. - Get the title of all movies that contain the comedy genre (
Comedy) - Show the title and genres of the movies that contain either the comedy genre (
Comedy) or adventure (Adventure). - Get the title and genres of movies that have three genres.
- Get the movies whose
Rotten Tomatoesrating is higher than4 - Make the same query as before, but limiting the number of documents to 10.
- Now shows the title and rating of those movies with more than a 4 rating, ordered by rating (highest to lowest) and limiting the results to 10.