Read Operation - I / MongoDB
Tags: mongodb, node, database, nosql
Published: 2020-11-23 14:32:29

##Query Operator -- Comparision

`db.<collection>.find({runtime: {$eq: 60}}) == db.<collection>.find({runtime: 60})`
The above is an equality operator. Without the comparison, it just works fine.

`db.<collection>.find({runtime: {$ne: 60}})`
`db.<collection>.find({runtime: {$gt: 60}})`
`db.<collection>.find({runtime: {$lt: 60}})`
The above is a non equality operator. Respectively, greater than, lesser than. For other operators, have a look here.

In case we have to query embedded documents, we have to use the dot notation within inverted commas, otherwise the dot notation will not be accepted and understood. Lets take a doc for example,
```
{
	"rating" : {
		"average" : 3
		"channels" : ["CBS", "NBC", "Fox"]
	}
}
```
The query would be ...
`db.<collection>.find({"rating.average" : 3})`
We can use other operators as well with this type of querying.

For arrays (if embedded, similar dot notation would be used..), the querying has a trick. If we want to match just one of the string in the array set,
`db.<collection>.find({"rating.channels": "CBS"})`
If we intend to match the entire array, then we have to set and look for the entire array..,
`db.<collection>.find({"rating.channels": ["CBS", "NBC", "Fox"]})`

`db.<collection>.find({"runtime": {$in: [30, 42]}})`
The $in operator takes in an array of values but does not look for an array. It matches for discrete values in the dataset and will only return those that matched. Just opposite to this is the $nin, which will return values but the ones specified in the array.


=============================
##Query Operator -- Logical

>$or || $nor

The $or operator works exactly like how logically it should. Its just the syntax we have to keep in mind.

`db.movies.find({$or: [{"rating.average": {$lt: 5}}, {"rating.average": {$gt: 9.3}}]})`

Essentially we write the $or in the beginning of the query and use array to conjugately search for all the conditions. The $nor operator has a similar syntax and returns exactly what $or returns.

`db.movies.find({$nor: [{"rating.average": {$lt: 5}}, {"rating.average": {$gt: 9.3}}]})`

>$and

The $and operator works similarly.

`db.movies.find({$and: [{genres: "Horror"}, {genres: "Drama"}]})
db.movies.find({$and: [{genres: "Horror"}, {"rating.average": {$gt: 8}}]})`

Again, it conjugates the different conditions and returns a matching result.

>$not

You may assume the $not operator works like $ne, and you are correct. Although we can write the query as follows,

`db.movies.find({runtime: {$not: {$eq: 60}}})` is the same as `db.movies.find({runtime: {$ne : 60}})`


=============================
##Query Operator -- Elements

>$exists

Lets say in our collection we wanna find all persons who have a 'age' field..
`db.users.find({age: {$exists : true}})`
`db.users.find({age: {$exists : true, $ne : null}})`

The strange way of passing two operators at the sametime is because mongodb implicitly uses and to concatenates values separated by comma. It uses "AND" implicitly.

>$type

All kind of types in mongodbo official webpage.
However it works pretty straight forward.
`db.users.find({phone: {$type : "double"}})`

since the shell is written in JS, passing double or number would behave the same way in most cases.

We can also use type a bit differently to check for multiple types.
`db.users.find({phone: {$type : ["double", "string"]}})`


=============================
##Query Operator -- Arrays

Lets say we have a collection as follows : 
```
{
	"hobbies": [
			{
				"title" : "Sports",
				"freq" : 3
			},
			{
				"title" : "Yoga",
				"freq" : 4
			}
		]
},
{
	"hobbies": [1,2,3]
},
{
	"hobbies": ['Cooking', 'Soccer']
},
{
	"hobbies": ['Soccer', 'Cooking']
},
{
	"hobbies": [
			{
				"title" : "Yoga",
				"freq" : 3
			},
			{
				"title" : "Cooking",
				"freq" : 5
			}
		]
}
```

In order to find a person with hobby as Sports, we have to write the following query : 
`db.<collection>.find({"hobbies.title" : "Sports"})`

Although we treat the array of embedded docs as single embedded doc, but eventually the above query will look for title field in all of the embedded docs and match it to "Sports"..

>$size

Now in order to find the result with the maximum number of hobbies, we could write a query that looks like this..

`db.<collection>.find({hobbies : {$size : 3}})`

This will essentially return the document/s where the hobbies array has length: 3. By the way this is a strict quality and mongo db currently do not support for comparision.


>$all

In order to find a document that contains multiple fields/values in an array, we can use the following query: 
`db.<collection>.find({hobbies: ['Cooking', 'Yoga']})`

This would work, in the way that the query will be looking for the exact match. It would return the 3rd document from the above collection. But should we want documents that contain the above information in any order we must write the following query:
`db.<collection>.find({hobbies: {$all: ['Cooking', 'Yoga']}})`

>$elemMatch

Now, when our array field is an array of documents, and we are looking for specific sets of field in that array of documents, then we use $elemMatch. In the above example if we use the following query it would not work as expected : 
`db.<collection>.find({$and: {"hobbies.title": "Yoga", "hobbies.freq": {$gt : 4}}})`

This would actually return the last document, even though there is no one doing Yoga at a freq of 4. This happens because mongodb is trying to find the document where the above condition exists, maybe not together, but definitely there. You see Cooking has a frequency of 5.

But in order to make the query work perfectly fine, we use $elemMatch
`db.<collection>.find({hobbies : {$elemMatch: {"title": "Yoga", "freq": {$gt: 4}}}})`
The above will return nothing.

But the below will return the last document..
`db.<collection>.find({hobbies : {$elemMatch: {"title": "Yoga", "freq": {$gte: 4}}}})`

Why? If you get the answer, write in the comments.