LoginSignup
37
33

More than 3 years have passed since last update.

Pythonでmongodbを操作する~その2:find編~

Last updated at Posted at 2019-08-08

当記事の記載範囲

この記事ではPythonでmongodbに接続してから、find(SQLで言うところのSELECT)の使い方について記載します。
mongodbの起動やpymongoのインストール方法については以下の記事をご覧いただければ幸いです。
https://qiita.com/bc_yuuuuuki/items/2b92598434f6cc320112

準備データ

mongodbの準備データは以下のとおりです。

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
> show collections
employee
log
salary
> db.salary.find()
{ "_id" : ObjectId("5d4acf84de925ae437e2c123"), "name" : "山田", "salary" : 300000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 400000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000 }
{ "_id" : ObjectId("5d4b81a4de925ae437e2c126"), "name" : "山田", "salary" : 500000 }

Pythonでmongodbのfindを使ってみる

早速、mongodbにfindOneとfindを実行してみます。

MongoFindSample.py
from pymongo import MongoClient
from pymongo import DESCENDING
from pymongo import ASCENDING

class MongoFindSample(object):

    def __init__(self, dbName, collectionName):
        self.client = MongoClient()
        self.db = self.client[dbName] #DB名を設定
        self.collection = self.db.get_collection(collectionName)

    def find_one(self, projection=None,filter=None, sort=None):
        return self.collection.find_one(projection=projection,filter=filter,sort=sort)

    def find(self, projection=None,filter=None, sort=None):
        return self.collection.find(projection=projection,filter=filter,sort=sort)

mongo = MongoFindSample('test', 'salary')
findOne = mongo.find_one()
print('-----------------find_One-----------------')
print(type(findOne))
print(findOne)

find = mongo.find()
print('-------------------find-------------------')
print(type(find))
for doc in find:
    print(doc)

実行結果

-----------------find_One-----------------
<class 'dict'>
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
-------------------find-------------------
<class 'pymongo.cursor.Cursor'>
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}

mongoDBだと以下のコマンドと同じ結果が得られました。

> db.salary.findOne()
{
        "_id" : ObjectId("5d4acf84de925ae437e2c123"),
        "name" : "山田",
        "salary" : 300000
}
> db.salary.find()
{ "_id" : ObjectId("5d4acf84de925ae437e2c123"), "name" : "山田", "salary" : 300000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 400000 }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000 }
{ "_id" : ObjectId("5d4b81a4de925ae437e2c126"), "name" : "山田", "salary" : 500000 }

findOneは実行結果がdict形式でfindだとpymongo.cursor.Cursorクラス形式で取得出来ることが分かりました。
このCursor形式はでは色々なデータの取り出し方法があります。

インデックスを指定した取得方法

(抜粋)MongoFindSample.py
find = mongo.find()
print('-------------------find-------------------')
print(type(find))
for i in range(find.count()):
    print(find[i])

実行結果

-------------------find-------------------
<class 'pymongo.cursor.Cursor'>
c:\Users\crypr\Documents\study\python\MongoFindSample.py:30: DeprecationWarning: count is deprecated. Use Collection.count_documents instead.
  for i in range(find.count()):
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}

どうもCursorクラスのcount()は非推奨みたいです。
Collection.count_documentsを使うようにとのことです。
取得したデータを1件ずつ処理する場合はこのやり方は向いてなさそうですね。
インデックスを指定して処理が出来るということだけ押さえておけばいいかなと思います。

Cursor.next()を使用した取得方法

(抜粋)MongoFindSample.py
try:
    doc = find.next()
    while doc != None:
        print(doc)
        doc = find.next()
except StopIteration:
    pass

実行結果

-------------------find-------------------
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}

JavaのIteratorのhasNextみたいな関数を見つけることが出来ず、こんな書き方になりました。
もっと良い方法ありそう。。

条件を指定して取得する

SQLで言うところのWHEREの条件を指定して取得します。

(抜粋)MongoFindSample.py
find = mongo.find(filter={'name':'山田'})
for doc in find:
    print(doc)

実行結果

{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}
{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}

複数の条件を指定する
名前が"山田"で給料が"400,000"以上のデータを取得してみます。

(抜粋)MongoFindSample.py
find = mongo.find(filter={'name':'山田','salary':{'$gte':400000}})
for doc in find:
    print(doc)

実行結果

{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}

並べ替えをする

SQLで言うところのORDER BYをしてみます。
試しに、給料の降順、名前の昇順でデータを取得します。

(抜粋)MongoFindSample.py
find = mongo.find(sort=[('salary',DESCENDING),('name',ASCENDING)])
for doc in find:
    print(doc)

実行結果

{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}

coursolを使って並べ替えをする
データ取得後にcursor側で並べ変えをすることも出来るようです。

(抜粋)MongoFindSample.py
find = mongo.find()
for doc in find.sort([('salary',DESCENDING),('name',ASCENDING)]):
    print(doc)

実行結果

{'_id': ObjectId('5d4b81a4de925ae437e2c126'), 'name': '山田', 'salary': 500000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 400000.0}
{'_id': ObjectId('5d4acf84de925ae437e2c123'), 'name': '山田', 'salary': 300000.0}

フィールド名を指定して取得する

最後に指定したフィールドのみを取得します。
名前と給料のみを取得します。

(抜粋)MongoFindSample.py
find = mongo.find(projection={'_id':0, 'name':1, 'salary':1},sort=[('salary',DESCENDING),('name',ASCENDING)])
for doc in find:
    print(doc)

実行結果

{'name': '山田', 'salary': 500000.0}
{'name': '田中', 'salary': 500000.0}
{'name': '佐藤', 'salary': 400000.0}
{'name': '山田', 'salary': 300000.0}

感想

Pythonで一通りfindを使用してデータ取得が出来ました。
かなり簡単に出来たなという印象です。

37
33
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
33