#当記事の記載範囲
この記事ではPythonでmongodbに接続後、findを使った様々な検索方法を記載しています。
- AND
- OR
- 部分一致
- 前方一致
- 後方一致
- 範囲検索(BETWEEN)
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("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 450000, "depId" : "A0001" }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000, "depId" : "A0001" }
{ "_id" : ObjectId("5d4f814c950945628d663d95"), "name" : "加藤", "salary" : 400000, "depId" : "B0001" }
{ "_id" : ObjectId("5d4f814c950945628d663d96"), "name" : "松井", "salary" : 500000, "depId" : "C0001" }
{ "_id" : ObjectId("5d5179f76427f268db46299f"), "name" : "山田", "salary" : 500000, "depId" : "A0002" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
#様々な検索方法
検索方法がmongodbのコマンドと結構違っているところがあったので、mongodbのコマンドと比較しながら記載します。
pymongoを使ったコードは以下の内容を使用しています。
from pymongo import MongoClient
from pymongo import DESCENDING
from pymongo import ASCENDING
from matplotlib import pyplot
class MongoFindSample(object):
def __init__(self, dbName, collectionName):
self.client = MongoClient()
self.db = self.client[dbName]
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)
def count_documents(self, filter=None):
return self.collection.count_documents(filter)
mongo = MongoFindSample('test', 'salary')
##ANDの使い方
collection"salary"からnameフィールドが"山田" かつ depIdフィールドが"C0002"のデータを取得します。
まずは、mongodbのコマンド
> db.salary.find({$and:[{'name':'山田'},{'depId':'C0002'}]})
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
次はpymongoを使った書き方
result1 = mongo.find(filter={'$and':[{'name':'山田'},{'depId':'C0002'}]})
for doc in result1:
print(doc)
実行結果
{'_id': ObjectId('5d5216ab61aa9ee6159ad4d8'), 'name': '山田', 'salary': 300000, 'depId': 'C0002'}
ANDについては$andをシングルクォーテーションで囲むか囲まないかという違いしかありませんでした。
##ORの使い方
collection"salary"からnameフィールドが"山田" または depIdフィールドが"B0001"のデータを取得します。
まずは、mongodbのコマンド
> db.salary.find({$or:[{'name':'山田'},{'depId':'B0001'}]})
{ "_id" : ObjectId("5d4f814c950945628d663d95"), "name" : "加藤", "salary" : 400000, "depId" : "B0001" }
{ "_id" : ObjectId("5d5179f76427f268db46299f"), "name" : "山田", "salary" : 500000, "depId" : "A0002" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
pymongoを使った書き方
result1 = mongo.find(filter={'$or':[{'name':'山田'},{'depId':'B0001'}]})
for doc in result1:
print(doc)
実行結果
{'_id': ObjectId('5d4f814c950945628d663d95'), 'name': '加藤', 'salary': 400000, 'depId': 'B0001'}
{'_id': ObjectId('5d5179f76427f268db46299f'), 'name': '山田', 'salary': 500000, 'depId': 'A0002'}
{'_id': ObjectId('5d5216ab61aa9ee6159ad4d8'), 'name': '山田', 'salary': 300000, 'depId': 'C0002'}
ORはANDと同じくシングルクォーテーションで囲むか囲まないかという違いだけでした。
##部分一致の使い方
nameに"田"を含むデータを取得してみます。
> db.salary.find({"name":/田/}))
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000, "depId" : "A0001" }
{ "_id" : ObjectId("5d5179f76427f268db46299f"), "name" : "山田", "salary" : 500000, "depId" : "A0002" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
次はpymongoの使い方
result1 = mongo.find(filter={'name':{'$regex':'田'}})
for doc in result1:
print(doc)
実行結果
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000, 'depId': 'A0001'}
{'_id': ObjectId('5d5179f76427f268db46299f'), 'name': '山田', 'salary': 500000, 'depId': 'A0002'}
{'_id': ObjectId('5d5216ab61aa9ee6159ad4d8'), 'name': '山田', 'salary': 300000, 'depId': 'C0002'}
これは書き方がかなり違いますね。
pymongoの方の書き方は"name"に対して正規表現を使いますというような書き方になっています。
また、正規表現のパターンの前後のスラッシュもpymongoでは不要なようです。
##前方一致の使い方
"depId"がAで始まるデータを取得してみます。
まずはmongodbのコマンド
> db.salary.find({"depId":/^A/})
{ "_id" : ObjectId("5d4acf84de925ae437e2c124"), "name" : "佐藤", "salary" : 450000, "depId" : "A0001" }
{ "_id" : ObjectId("5d4acf84de925ae437e2c125"), "name" : "田中", "salary" : 500000, "depId" : "A0001" }
{ "_id" : ObjectId("5d5179f76427f268db46299f"), "name" : "山田", "salary" : 500000, "depId" : "A0002" }
次はpymongoの使い方
result1 = mongo.find(filter={'depId':{'$regex':'^A'}})
for doc in result1:
print(doc)
実行結果
{'_id': ObjectId('5d4acf84de925ae437e2c124'), 'name': '佐藤', 'salary': 450000, 'depId': 'A0001'}
{'_id': ObjectId('5d4acf84de925ae437e2c125'), 'name': '田中', 'salary': 500000, 'depId': 'A0001'}
{'_id': ObjectId('5d5179f76427f268db46299f'), 'name': '山田', 'salary': 500000, 'depId': 'A0002'}
前方一致の場合は^が最初に必要になります。
##後方一致の使い方
"depId"が"2"で終わるデータを取得してみます。
まずは、mongodbのコマンド
> db.salary.find({"depId":/2$/})
{ "_id" : ObjectId("5d5179f76427f268db46299f"), "name" : "山田", "salary" : 500000, "depId" : "A0002" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
次はpymongoの使い方
result = mongo.find(filter={'depId':{'$regex':'2$'}})
for doc in result:
print(doc)
実行結果
{'_id': ObjectId('5d5179f76427f268db46299f'), 'name': '山田', 'salary': 500000, 'depId': 'A0002'}
{'_id': ObjectId('5d5216ab61aa9ee6159ad4d8'), 'name': '山田', 'salary': 300000, 'depId': 'C0002'}
後方一致の場合は末尾に$マークが必要です。
##範囲検索(BETWEEN)
mongodbにはBETWEENが無いみたいなので、AND条件を組み合わせて行う必要があります。
salaryフィールドが300000以上、400000以下のデータを取得してみます。
> db.salary.find({$and:[{'salary':{$gte:300000}},{'salary':{$lte:400000}}]})
{ "_id" : ObjectId("5d4f814c950945628d663d95"), "name" : "加藤", "salary" : 400000, "depId" : "B0001" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
次はpymongoの使い方
result1 = mongo.find(filter={'$and':[{'salary':{'$gte':300000}},{'salary':{'$lte':400000}}]})
for doc in result1:
print(doc)
実行結果
{'_id': ObjectId('5d4f814c950945628d663d95'), 'name': '加藤', 'salary': 400000, 'depId': 'B0001'}
{'_id': ObjectId('5d5216ab61aa9ee6159ad4d8'), 'name': '山田', 'salary': 300000, 'depId': 'C0002'}
長いな。。
次の書き方でも同じ結果を得られました。
> db.salary.find({'salary':{$gte:300000,$lte:400000}})
{ "_id" : ObjectId("5d4f814c950945628d663d95"), "name" : "加藤", "salary" : 400000, "depId" : "B0001" }
{ "_id" : ObjectId("5d5216ab61aa9ee6159ad4d8"), "name" : "山田", "salary" : 300000, "depId" : "C0002" }
result1 = mongo.find(filter={'salary':{'$gte':300000,'$lte':400000}})
内部の動きまでは分かりませんが、こちらの方が書き方がシンプルで分かり易いですね。
#感想
部分一致以外はmongodbのコマンドと同じものをpymongoで使えました。
ANDのは複数の書き方が出来るみたいなので、違いを細かく調べる必要がありそうです。
#関連記事