# MogoDB
Reference
https://www.youtube.com/watch?v=ExcRbA7fy_A&list=PL4cUxeGkcC9h77dJ-QJlwGlZlTd4ecZOA
# Introduction
(No related Database)

- Collections (similar to tables)
- Documents (similar to records)
## Documents

A document is the data, similar to a JSON file. It can include other documents, creating relationships between them
# Installing MongoDB
Download MongoDB
https://www.mongodb.com/try/download/community



## Mongo DM compass (GUI)

## MongoDB Shell (CLI)


# Collection & Document
Database can have many collection
e.g. User collection, Post collection, Comment
- Collection

- Document

Documents appear as JSON object, but actually, the date is store as BSON (binary json)

## Nest Document

# MongoDB compass
## Connecting to MongoDB
### Local DataBase


### start_LOG
/local->start_log

Every time we start the DB, this action will be recording in the log file.
## Create Database



## Adding a document



A document can be represent as a JOSN object
When we want insert multiple documents, you can use an array [] to insert them.
```json
{
"gunname": "AK-47",
"owner": "firearmlover",
"price": 1200,
"tags": [
"rifle",
"firearms"
],
"rating": 8
},
{
"gunname": "Glock 19",
"owner": "gunenthusiast",
"price": 600,
"tags": [
"handgun",
"guns"
],
"rating": 9
},
{
"gunname": "Remington 870",
"owner": "shootingpro",
"price": 800,
"tags": [
"shotgun",
"firearms"
],
"rating": 7.5
}
]
```

## Filter

# MongoDB shell
Fetch
Create
Delete
Update
```
PS C:\Users\USER> mongosh
Current Mongosh Log ID: 653b909bfcab94a7cf4c6659
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.10.6
Using MongoDB: 6.0.7
Using Mongosh: 1.10.6
mongosh 2.0.2 is available for download: https://www.mongodb.com/try/download/shell
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2023-10-20T15:41:17.416+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
------
```
### use {database}
```
test> show dbs
admin 40.00 KiB
config 108.00 KiB
gunShops 72.00 KiB
local 88.00 KiB
test>
```
```
test> use gunShops
switched to db gunShops
```
```
gunShops> use notExistsDB
switched to db notExistsDB
```
If the database does not exists, it will switch to a non-existent DB.
### DB
```
gunShops> db
gunShops
```
### show collections
```
gunShops> show collections
handgun
```
### Variable
```
gunShops> var name = "meowhecker"
gunShops> name
meowhecker
```
# Adding New Documents
```
gunShops> db
gunShops
gunShops> db.handgun //database.collection
gunShops.handgun
```
## insertOne()
Syntax
```
database.collection.insertOne("JSON file")
```
```
{
"gunname": "M4A1",
"owner": "tacticalshooter",
"price": 1500,
"tags": [
"rifle",
"firearms"
],
"rating": 9
}
```
```
gunShops> db.handgun.insertOne({"gunname": "M4A1","owner": "tacticalshooter","price": 1500,"tags": ["rifle","firearms"],"rating": 9})
{
acknowledged: true,
insertedId: ObjectId("653b985cfcab94a7cf4c665c")
}
```

## Inset document to non exists Collections
```
gunShops> db.admin.insertOne({"name":"meowhecker","age":18})
{
acknowledged: true,
insertedId: ObjectId("653b9ab7fcab94a7cf4c665d")
}
```
The monogoDB will automatic create the collection


## insertMany()
db -> current use database
```json
db.collectionName.insertMany([{"key":"value"},{"key":"value"}])
```

# Finding Documents
find -> query
```
gunShops> db.handgun.find()
```
find method -> only show the 20 document, if want to show more have to type "it" to iterate it

## Filter
find(parameter 1,parameter 2,......)
parameter -> filter
```
gunShops> db.handgun.find({"owner":"meowhecker"})
[
{
_id: ObjectId("653b88c40aaa5623dde125b9"),
gunname: 'P90',
owner: 'meowhecker',
price: 900,
tags: [ 'handgub', 'guns' ],
rating: 7
}
]
```
### Multi-condition
```
gunShops> db.handgun.find({"rating": 9,"price":600})
[
{
_id: ObjectId("653b8b400aaa5623dde125bc"),
gunname: 'Glock 19',
owner: 'gunenthusiast',
price: 600,
tags: [ 'handgun', 'guns' ],
rating: 9
}
]
```
```
db.handgun.find({"rating": 9},{"gunname":1,"price":1})
```

```
gunShops> db.handgun.find({},{"gunname":1,"price":1})
```

## find single document by the object ID
```
db.handgun.find({_id:ObjectId("653b8b400aaa5623dde125bc")})
```

# Sorting & Limiting Data
## Count
```
gunShops> db.handgun.find({}).count()
5
```
## Limit

## Sort
```
db.handgun.find().sort({"price":1})
```

# Nested Documents

Insert

---

Insert

# Operators & complex queries
## query Operators
### great then ($gt
```
db.handgun.find({"rating":{$gt:8}})
```

### less then ($lt
```
db.handgun.find({"rating":{$lt:8}})
```

### grate/less equal ($lte
```
db.handgun.find({"rating":{$lte:8}})
```

## or Operator ($or)
or -> multi-condition
we have to use Array to do filter match
```
db.handgun.find({$or:[{"rating":8},{"owner":"meowhecker"}]})
```

## And Operator ($and
```
gunShops> db.handgun.find({$and:[{"rating":{$gte:8}},{"price":{$lte:1000}}]})
```

## Using $in and $nin
```
gunShops> db.handgun.find({"rating":{$in:[7,9]}})
```

```
gunShops> db.handgun.find({"rating":{$nin:[7,9]}})
```

## $where
Match document satisfy the javascript expression
Syntax:
```
$where:javascript Expression
```
```
gunShops> db.handgun.find({$where:function(){return this.price === 1200}})
[
{
_id: ObjectId("653b8b400aaa5623dde125bb"),
gunname: 'AK-47',
owner: 'firearmlover',
price: 1200,
tags: [ 'rifle', 'firearms' ],
rating: 8
}
]
```
### Null byte
Null byte -> "%00"
```javascript
db.admin.find({$where:function(){
return this.username === "meowhecker" && this.password === "meowmeow"
}})
```
db.admin.find({$where:function(){return this.username === "meowhecker" && this.password === "meowmeow"}})

Using a Null byte to ignore the character after it (But it appears to work in old mongodb version)
```
gunShops> db.admin.find({ $where: function () {return this.username === 'meowhecker'\u0000' && this.password === 'meowmeow';}})
Uncaught:
SyntaxError: Invalid Unicode escape. (1:74)
> 1 | db.admin.find({ $where: function () {return this.username === 'meowhecker'\u0000' && this.password === 'meowmeow';}})
| ^
2
```
### $ne
"We can attempt to inject '$ne' into the password field to bypass authentication.
```
gunShops> db.admin.find({"username":"meowhecker","password":{$ne:"hacker"}})
[
{
_id: ObjectId("653b9ab7fcab94a7cf4c665d"),
name: 'meowhecker',
age: 18,
password: 'meowmeow',
superadmin: 1,
username: 'meowhecker'
}
]
```
# Querying Array
```
gunShops> db.handgun.find({tags:"rifle"})
```

## Restrict Match
```
gunShops> db.handgun.find({tags:["rifle","firearms"]})
```
## $all


## Retrieve sub document


# Delete Document
## deleteOne

```
gunShops> db.handgun.deleteOne({_id: ObjectId("653b985cfcab94a7cf4c665c")})
{ acknowledged: true, deletedCount: 1 }
```

## deleteMany()'
# Update Document
# $set

```
gunShops> db.admin.updateOne({ "name": "meowhecker"}, { $set: { "username": "meowhecker", "password": "meowmeow", "superadmin": 1 } })
{
acknowledged: true,
insertedId: null,
matchedCount: 1,
modifiedCount: 1,
upsertedCount: 0
}
```
```
gunShops> db.admin.find()
[
{
_id: ObjectId("653b9ab7fcab94a7cf4c665d"),
name: 'meowhecker',
age: 18,
password: 'meowmeow',
superadmin: 1,
username: 'meowhecker'
}
]
```
## MongoDB drivers
Application(python,node)<--> MongoDB Drivers <--> MongoDB

## Node
```
npm init
```

```
touch app
npm install express --save
```
Testing
```javascript
const express = require('express')
const app = express()
app.listen(3000,()=>{
console.log("meowhecker")
})
app.get('/gunshop',(req,res)=>{
res.json({"message":"gun shop api"})
})
```
```
nodemon app
```

## install mongoDB in node js
```
npm install mongodb --save
```
# Connect to MongoDB
db.js
```javascript
const { MongoClient } = require('mongodb')
let dbConnection
module.exports = {
connectToDb: (cb) => {
MongoClient.connect('mongodb://localhost:27017/gunShop')
.then(client => {
dbConnection = client.db()
return cb()
})
.catch(err => {
console.log(err)
return cb(err)
})
},
getDb: () => dbConnection
}
```
app.js
```javascript
const express = require('express')
const app = express()
//import DB
const {connectToDB,getDB} = require('./db')
//Connect to DataBase
let db
connectToDB((err)=>{
if (!err){
app.listen(3000,()=>{
console.log("meowhecker")
})
mongoDB = getDB()
}
})
app.get('/gunshop',(req,res)=>{
res.json({"message":"gun shop api"})
})
```

# Cursors & fetching Data
## app.js
```javascript
const express = require('express')
const app = express()
//import DB
const {connectToDB,getDB} = require('./db')
//Connect to DataBase
let mongoDB
connectToDB((err)=>{
if (!err){
app.listen(3000,()=>{
console.log("meowhecker")
})
mongoDB = getDB() // mongoDB = db(gunShop)
}
})
app.get('/gunshop',(req,res)=>{
let guns=[]
// Find method will return a cursors . we have to use ForeEach to enumrate them(property)
mongoDB.collection('handgun')
.find()
.sort({price:1})
.forEach(gun => {
guns.push(gun)
}).then(()=>{
res.status(200).json(guns)
}).catch(()=>{
res.status(500).json({error:"Could not to fetch documents"})
})
//res.json({"message":"gun shop api"})
})
```

# Finding single Document
```javascript
app.get('/gunshops/:id', (req, res) => {
console.log(req.params.id);
const objectId = new ObjectId(req.params.id); // 轉換為有效的 ObjectId
mongoDB.collection('handgun')
.find({ _id: objectId })
.toArray() // cursors to Arrat
.then((guns) => {
res.status(200).json(guns);
})
.catch(() => {
res.status(500).json({ "error": "Could not fetch the data" });
});
});
```

Invalid Document ID

```javascript
app.get('/gunshops/:id', (req, res) => {
if(ObjectId.isValid(req.params.id)){
console.log(req.params.id);
const objectId = new ObjectId(req.params.id);
mongoDB.collection('handgun')
.find({ _id: objectId })
.toArray()
.then((guns) => {
res.status(200).json(guns);
})
.catch(() => {
res.status(500).json({ "error": "Could not fetch the data" });
});
}else {
res.status(500).json({"error":"could not found the doc"})
}
});
```

# Login Authentication
```javascript
//Hard Code Database
const users = [
{ username: 'user1', password: 'password1' },
{ username: 'user2', password: 'password2' },
];
// Using body Parse to Parse the pose request
app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
//Middle SoftWare
const authenticateUser = (req,res,next)=>{
const {username,password} = req.body
console.log(username,password)
const user = users.find(u=>u.username === username && u.password===password)
console.log(user)
if (user){
next();
}else{
res.status(401).json({error:"Authentication failed"})
}
}
//loging EndPing
app.post("/login",authenticateUser, (req,res)=>{
console.log(1)
res.status(200).json({Messages:"Authntication successful"})
})
```

Post Request
```
POST /login HTTP/1.1
Host: 127.0.0.1:3000
content-type:application/json
Connection: keep alive
Content-Length: 55
{
"username": "user1",
"password": "password1"
}
```
