お仕事の備忘録(pymongo)  その1.   基本的な操作編

# <a name="top"><a>この記事について</a>
仕事でpymongoを使ったので備忘録としてこの記事を作成しました。
下記に分けて書いていこうと思います。

0. 基本操作編(このページ)
    0. [MongoDBとは](#tuto),[pymongoとは](#pymongo)
    0. [接続方法](#connect)
    0. [挿入方法](#insert)
    1. [検索方法](#find)
    0. [更新方法](#update)
    1. [削除方法](#delete)
0. [割と便利な操作(bulk_write)編](https://qiita.com/rsm223_rip/items/cdcb27c80de24566bd84)
    0. bulk_write  
       参照：[pymongo ドキュメント Bulk_Write](https://api.mongodb.com/python/current/examples/bulk.html)
0. [あまり使わなかったけど調べ直したくないからメモしとくやつ(aggregate)編](https://qiita.com/rsm223_rip/items/8bb76244e84b31b80191)
    0. aggregate  
       参照：[MongoDB ドキュメントaggregate pipeline](https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/)

### 動作環境
 
~~~
OS: Mac OS
MongoDB: 4.2
Python 3.6.8 :: Anaconda, Inc.
pymongo: 3.9.0
~~~

---

# <a name="tuto"><a>MongoDBとは?</a>


- MongoDBの特徴として下記が挙げられる。
    - NoSQL
    - **JSON形式のデータであればスキーマの設定なしに登録できる。**  
      　Rest APIのレスポンスをそのままインサートしたりできたり、スキーマが異なっていてもDBに登録できて便利です。
    - DBへの書き込みなどが早い
    - 集計などの処理が独特  
        jsonのデータを格納できるため、配列の集計などもできますが、SQLよりわかりにくいです...
    - トランザクションなどが弱いRDBに慣れた方には異色な感じのDBかもしれません


# <a name="pymongo"><a> pymongoとは?</a>
名前から推測できるかと思いますが、pythonで動かすMongoDBのライブラリです。

# <a name="howToUse"><a>pymongoの操作方法</a>
基本的に下記を参考にざっくりとしたメモを作成していきます。
 参考：[pymongo ドキュメント](https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.insert_many)


# <a name="connect"><a>MongoDBとの接続</a>

```python:main.py
import pymongo
from pymongo import MongoClient
# デフォルト値のパラメータでの接続 (host=localhost,port = 27017)
# 実際は接続できるかどうかは保証できない
# findなどのDB読み書きでエラーが発生するっぽい
client = MongoClient() # DBの接続()
db = client.DB名 # DBの取得
collection = db.コレクション名 # コレクション(tableみたいなもの)の取得
```
---
# <a name="insert"><a>挿入方法</a>

- json形式のデータを挿入を行う
- 挿入されるデータは,_idが追加されてコレクションに追加される。

```python:main.py
# コレクションへの挿入(引数にjson形式のデータを渡すだけ)

# データの作成
json_list = [{"x":i,"y":i*2,"z":i*3} for i in range(0,5)]

# document or documentsの挿入(非推奨らしい)
collection.insert(json_lsit) 
 
# 1つのドキュメントだけ挿入
collection.insert_one({"x":255,"y":255,"z":255})

# データの作成
json_list = [{"x":i,"y":i*2,"z":i*3,"a":i*4} for i in range(0,5)]
# 複数のドキュメントの挿入
collection.insert_many(json_list) 
```

# <a name="find"><a>検索方法</a>
- ざっくりとしたイメージですが、SQLのselect句がprojection,where句がfilterと対応する感じです  
参照:[検索、表示のoperation](https://docs.mongodb.com/manual/reference/operator/query/)

```python:main.py
# 全件検索(filterに何も指定しなければ全件取得できる)
data = collection.find(filter={})
for i in data:
    pprint.pprint(i)

# 検索(projectionで必要ないカラムを0にセットするだけ
# 0,1じゃなくてもTrue or False で表示のオンオフができるらしい
data = collection.find(filter={"x":{"$gt":1,  # $gt:1 -> 1より大きい
                                   "$lt":3}}, # $lt:3 -> 3より小さい
                        projection={"_id":0}
                       )
for i in data:
    pprint.pprint(i)

```
# <a name="delete"><a>削除方法</a>
条件式のクエリはfindと同じ感じで使えるっぽい

```python:main.py
# 基本的にシンプルに条件式を渡すだけ

# 条件に一致する一件のドキュメントを削除
collection.delete_one({"x":1}) 

# 条件に一致するドキュメントの削除(xが3以下のドキュメントの削除)
collection.delete_many({"x":{"$lt":3}}) 

# 条件式の指定なしで全件削除ができる(空のdictを渡すだけ)
# collection.delete_many({}) # 条件に一致するドキュメントの削除
```
# <a name="update"><a>更新方法</a>
- upsertを指定することで、filterの条件に引っかからない場合、ドキュメントを挿入することもできる。    
参照:[更新のoperations](https://docs.mongodb.com/manual/reference/operator/update/)

```python:main.py
# filterで指定した条件に一致する1つのドキュメントをupdateに従って更新する
collection.update_one(filter, 
                        update, 
                        upsert=False
                         )
# filterで指定した条件に一致するドキュメントをupdateに従って更新する
collection.update_many(filter, 
                        update, 
                        upsert=False
                         )
```

---
ざっくりした説明ですが、基本的な操作はこんな感じです。
今度、気が向いたらbulk_write,aggregateとかもうちょっと丁寧に書いてみようと思います。