MongoDB-增、刪、改、查
MongoDB
MongoDB操作
在 Python 中, 如果想要和 MongoDB 進行互動 ,就需要藉助於 PyMongo 庫:pip install pymongo
使用python 進行簡單的插入和查詢。
# -*- coding: utf-8 -*-
# @Date : 2018-11-13 16:37:59
# @Author : Your Name ([email protected])
# @Link : http://example.org
from pymongo import MongoClient
client = MongoClient('localhost', 27017)
# client = MongoClient('mongodb://localhost:27017/')
db = client.test
# db = client['test']
collection = db.students
# collection = db['students']
student1 = {
'id': '20170101',
'name': 'Jordan',
'age': 22,
'gender': 'male'
}
student2 = {
'id': '20170202',
'name': 'Mike',
'age': 21,
'gender': 'male'
}
# result = collection.insert(student1)
result = collection.insert_many( [student1, student2])
print(result)
results = collection.find({'age': 20})
print(results)
for result in results:
print(result)
簡單的插入和查詢。結果:
5bea8f3f8c70ac282070ff43
<pymongo.cursor.Cursor object at 0x7f5062f5c358>
{'_id': ObjectId('5bea8e728c70ac26b5a547dd'), 'id': '20170101', 'name': 'Jordan', 'age': 20, 'gender': 'male'}
[Finished in 0.6s]
建立資料庫
MongoDB 中預設的資料庫為 test,如果你沒有建立新的資料庫,集合將存放在 test 資料庫中。在 MongoDB 中,集合只有在內容插入後才會建立! 就是說,建立集合(資料表)後要再插入一個文件(記錄),集合才會真正建立。
import pymongo
client = pymongo.MongoClient(host='localhost', port=27017)
# 建立資料庫 只有在內容插入後才會建立
db = client['first_demo']
# 返回當前資料庫列表
dblist = client.list_database_names()
print(dblist)
if 'first_demo' in dblist:
print('資料庫已存在')
# 建立集合 集合只有在內容插入後才會建立
col = db['sites']
# 返回資料庫內集合
collist = db.list_collection_names()
if 'sites' in collist:
print('集合已存在')
新增資料
文件的資料結構和JSON基本一樣。
所有儲存在集合中的資料都是BSON格式。
BSON是一種類json的一種二進位制形式的儲存格式,簡稱Binary JSON。
集合中插入文件使用insert_one()
方法,第一引數是字典 name => value 對, 集合中插入多個文件使用 insert_many() 方法,該方法的第一引數是字典列表
db = client['first_demo']
col = db['sites']
# 集合內插入
d1 = {'name': 'google', 'id': 2, 'url': 'https://www.google.com'}
x = col.insert_one(d1)
# 方法返回 InsertOneResult 物件,該物件包含 inserted_id 屬性,它是插入文件的 id 值
print(x) # <pymongo.results.InsertOneResult object at 0x7fec2a5f3888>
print(x.inserted_id) # 5c00af888c70ac6346a4ab25
插入多條
insert_many()
插入多條文件:
# 插入多條資料
mylist = [
{"name": "Taobao", "alexa": "100", "url": "https://www.taobao.com"},
{"name": "QQ", "alexa": "101", "url": "https://www.qq.com"},
{"name": "Facebook", "alexa": "10", "url": "https://www.facebook.com"},
{"name": "知乎", "alexa": "103", "url": "https://www.zhihu.com"},
{"name": "Github", "alexa": "109", "url": "https://www.github.com"},
]
x = col.insert_many(mylist)
# 輸出插入的所有文件對應的 _id 值
print(x.inserted_ids)
所有文件的id:
[ObjectId('5c00b2068c70ac67e3a197fe'), ObjectId('5c00b2068c70ac67e3a197ff'),
ObjectId('5c00b2068c70ac67e3a19800'), ObjectId('5c00b2068c70ac67e3a19801'),
ObjectId('5c00b2068c70ac67e3a19802')]
自定義_id插入
也可以自己指定'_id'
進行插入:
mylist_2 = [
{'_id': 1, 'name': 'Jack', 'num': 1233},
{'_id': 2, 'name': 'Tom', 'num': 1233},
{'_id': 3, 'name': 'Candy', 'num': 1233},
{'_id': 4, 'name': 'Ana', 'num': 1233},
]
x = col.insert_many(mylist_2)
print(x.inserted_ids)
# [1, 2, 3, 4]
查詢
使用find(self, *args, **kwargs)
進行查詢,類似 SQL 中的 SELECT * 操作:
db = client['first_demo']
col = db['sites']
for x in col.find():
print(x)
查詢到’sites’內的所有文件:
{'_id': ObjectId('5c00ad0c8c70ac5e7746832d'), 'name': 'google', 'id': 1, 'url': 'https://www.google.com'}
{'_id': ObjectId('5c00ad1b8c70ac5e8b08ce09'), 'name': 'google', 'id': 1, 'url': 'https://www.google.com'}
{'_id': ObjectId('5c00af888c70ac6346a4ab25'), 'name': 'google', 'id': 2, 'url': 'https://www.google.com'}
...
{'_id': 1, 'name': 'Jack', 'num': 1233}
{'_id': 2, 'name': 'Tom', 'num': 1233}
{'_id': 3, 'name': 'Candy', 'num': 1233}
{'_id': 4, 'name': 'Ana', 'num': 1233}
查詢指定欄位
使用find查詢指定欄位的資料,將要返回的欄位對應值設定為1
:
for x in col.find({}, {"_id": 0, 'name': 1, 'url': 1}):
print(x)
{'name': 'google', 'url': 'https://www.google.com'}
{'name': 'Taobao', 'url': 'https://www.taobao.com'}
{'name': 'QQ', 'url': 'https://www.qq.com'}
{'name': 'Facebook', 'url': 'https://www.facebook.com'}
{'name': '知乎', 'url': 'https://www.zhihu.com'}
...
{'name': 'Jack'}
{'name': 'Tom'}
{'name': 'Candy'}
{'name': 'Ana'}
除了_id
不能在一個物件中同時
指定 0 和 1,如果設定了一個欄位為 0,則其他都為 1,反之亦然。
指定條件查詢
在 find() 中設定引數來過濾資料, 類似sql的where:
操作 | 格式 | RDBMS中的類似語句 |
---|---|---|
等於 | {key:value} | where by = ‘菜鳥教程’ |
小於 | {key:{$lt:value}} | where xxx < 50 |
小於或等於 | {key:{$lte:value}} | where xxx <= 50 |
大於 | {key:{$gt:value}} | where xxx > 50 |
大於或等於 | {key:{$gte:value}} | where xxx >= 50 |
不等於 | {key:{$ne:value}} | where xxx != 50 |
AND | {key1:value1, key2:value2} | where xxx= and yyy= |
OR | {"$or":[{key1:value1}, {key2:value2}] } | where xxx= or yyy= |
AND條件:
# 指定條件查詢 類似 sql where name = googel and id =1
query_1 = {'name': 'google', 'id': 1}
doc_1 = col.find(query_1)
for x in doc_1:
print(x)
# {'_id': ObjectId('5c00ad0c8c70ac5e7746832d'), 'name': 'google', 'id': 1, 'url': 'https://www.google.com'}
# {'_id': ObjectId('5c00ad1b8c70ac5e8b08ce09'), 'name': 'google', 'id': 1, 'url': 'https://www.google.com'}
OR條件:
# or where name = Jack or _id = 2
query_2 = {"$or": [{'name': 'Jack'}, {'_id': 2}]}
doc_2 = col.find(query_2)
for x in doc_2:
print(x)
# {'_id': 1, 'name': 'Jack', 'num': 1233}
# {'_id': 2, 'name': 'Tom', 'num': 1233}
大於:
# 大於 where _id > 2
query_3 = {'_id': {'$gt': 2}}
doc_3 = col.find(query_3)
for x in doc_3:
print(x)
# {'_id': 3, 'name': 'Candy', 'num': 1233}
# {'_id': 4, 'name': 'Ana', 'num': 1233}
條件聯用:
# where name='QQ' or (id > 1 and name = 'google')
query_4 = {'$or': [{"name": "QQ"}, {"id": {"$gt": 1}, "name": "google"}]}
doc_4 = col.find(query_4)
for x in doc_4:
print(x)
# {'_id': ObjectId('5c00af888c70ac6346a4ab25'), 'name': 'google', 'id': 2, 'url': 'https://www.google.com'}
# {'_id': ObjectId('5c00b2068c70ac67e3a197fd'), 'name': 'google', 'id': 2, 'url': 'https://www.google.com'}
# {'_id': ObjectId('5c00b2068c70ac67e3a197ff'), 'name': 'QQ', 'alexa': '101', 'url': 'https://www.qq.com'}
# {'_id': ObjectId('5c01d7ed8c70ac1f294fb30a'), 'name': 'google', 'id': 2, 'url': 'https://www.google.com'}
# {'_id': ObjectId('5c01d7ed8c70ac1f294fb30c'), 'name': 'QQ', 'alexa': '101', 'url': 'https://www.qq.com'}
type型別查詢
$type操作符是基於BSON型別來檢索集合中匹配的資料型別,並返回結果,MongoDB支援的資料型別有double, string, JavaScript和Timestamp等, 具體檢視: https://docs.mongodb.com/manual/reference/bson-types/
col_2 = db['student']
stu_list = [
{'_id': 1, 'name': 'Jack', 'socre': 90},
{'_id': 2, 'name': 'Tom', 'socre': 85},
{'_id': 3, 'name': 'Candy', 'socre': "A"},
{'_id': 4, 'name': 'Ana', 'socre': "B"},
]
# col_2.insert_many(stu_list)
for x in col_2.find():
print(x)
print('-----')
query_5 = {'socre': {"$type": "string"}}
doc_5 = col_2.find(query_5)
for x in doc_5:
print(x)
# -------------
# {'_id': 1, 'name': 'Jack', 'socre': 90}
# {'_id': 2, 'name': 'Tom', 'socre': 85}
# {'_id': 3, 'name': 'Candy', 'socre': 'A'}
# {'_id': 4, 'name': 'Ana', 'socre': 'B'}
# -----
# {'_id': 3, 'name': 'Candy', 'socre': 'A'}
# {'_id': 4, 'name': 'Ana', 'socre': 'B'}
正則表示式查詢
還可以使用正則表示式作為修飾符,正則表示式修飾符只用於搜尋字串的欄位,類比SQL中的REGEX, 使用$regex
關鍵字:
# 正則表示式 查詢 只能用於字串
query_6 = {"name": {"$regex": "^g\w+e$"}}
doc_6 = col.find(filter=query_6, projection={"_id": 0, 'url': 0})
for x in doc_6:
print(x)
# {'name': 'google', 'id': 1}
# {'name': 'google', 'id': 1}
# {'name': 'google', 'id': 2}
# {'name': 'google', 'id': 2}
# {'name': 'google', 'id': 2}
指定查詢返回數
使用limit引數,或在查詢後使用limit()函式,可以限定條數:
# 指定查詢返回條數
# doc_7 = col.find(filter={'name': "google"}, projection={"url": 0}, limit=3)
doc_7 = col.find(filter={'name': "google"}, projection={"url": 0}).limit(3)
for x in doc_7:
print(x)
# {'_id': ObjectId('5c00ad0c8c70ac5e7746832d'), 'name': 'google', 'id': 1}
# {'_id': ObjectId('5c00ad1b8c70ac5e8b08ce09'), 'name': 'google', 'id': 1}
# {'_id': ObjectId('5c00af888c70ac6346a4ab25'), 'name': 'google', 'id': 2}
修改文件
update_one()
方法修改文件中的記錄。該方法第一個引數為查詢的條件,第二個引數為要修改的欄位。如果查詢到的匹配資料多餘一條,則只會修改第一條。
update_one(self, filter, update, upsert=False,bypass_document_validation=False,
collation=None, array_filters=None, session=None)
for x in col.find():
print(x)
# {'_id': 1, 'name': 'Jack', 'socre': 90}
# {'_id': 2, 'name': 'Tom', 'socre': 85}
# {'_id': 3, 'name': 'Candy', 'socre': 'A+'}
# {'_id': 4, 'name': 'Ana', 'socre': 'B'}
#
result = col.update_one(filter={'socre': {"$type": 'string'}},
update={'$set': {"socre": "S+"}})
print(result.matched_count)
print(result.modified_count)
# 1
# 1
#
for x in col.find():
print(x)
# {'_id': 1, 'name': 'Jack', 'socre': 90}
# {'_id': 2, 'name': 'Tom', 'socre': 85}
# {'_id': 3, 'name': 'Candy', 'socre': 'S+'}
# {'_id': 4, 'name': 'Ana', 'socre': 'B'}
update_one方法只能修匹配到的第一條記錄,如果要修改所有匹配到的記錄,可以使用 update_many()
for x in col.find():
print(x)
# {'_id': 1, 'name': 'Jack', 'socre': 90}
# {'_id': 2, 'name': 'Tom', 'socre': 85}
# {'_id': 3, 'name': 'Candy', 'socre': 'S+'}
# {'_id': 4, 'name': 'Ana', 'socre': 'B'}
result = col.update_many(filter={'score': {'$type': "int"}},
update={"$inc": {'score': 1}})
print(result.matched_count)
print(result.modified_count)
# 2
# 2
for x in col.find():
print(x)
# {'_id': 1, 'name': 'Jack', 'score': 91}
# {'_id': 2, 'name': 'Tom', 'score': 86}
# {'_id': 3, 'name': 'Candy', 'score': 'S+'}
# {'_id': 4, 'name': 'Ana', 'score': 'B'}
replace_one 可以替換當前滿足條件的一個文件:
for x in col.find():
print(x)
# {'_id': 1, 'name': 'Jack', 'score': 92}
# {'_id': 2, 'name': 'Tom', 'score': 87}
# {'_id': 3, 'name': 'Candy', 'score': 'S+'}
# {'_id': 4, 'name': 'Ana', 'score': 'B'}
ret = col.replace_one({'name': 'Jack'}, {'name': 'John'})
print(ret.matched_count)
print(ret.modified_count)
# 1
# 1
for doc in col.find():
print(doc)
# {'_id': 1, 'name': 'John'}
# {'_id': 2, 'name': 'Tom', 'score': 87}
# {'_id': 3, 'name': 'Candy', 'score': 'S+'}
# {'_id': 4, 'name': 'Ana', 'score': 'B'}
其他:
- find_one_and_update:查詢單個文件並修改,返回值可選擇為修改之前的文件或修改之後的文件;
- find_one_and_replace:查詢單個文件並替換,返回值可選擇為替換之前的文件或替換後的新文件;
刪除資料
使用delete_one方法來刪除一個文件,該方法第一個引數為查詢物件,指定要刪除哪些資料
for doc in col.find():
print(doc)
# {'_id': 1, 'name': 'John'}
# {'_id': 2, 'name': 'Tom', 'score': 87}
# {'_id': 3, 'name': 'Candy', 'score': 'S+'}
# {'_id': 4, 'name': 'Ana', 'score': 'B'}
print('--------')
col.delete_one({'name': 'Ana'})
for doc in col.find():
print(doc)
# {'_id': 1, 'name': 'John'}
# {'_id': 2, 'name': 'Tom', 'score': 87}
# {'_id': 3, 'name': 'Candy', 'score': 'S+'}
delete_many可以刪除多個文件:
query = {'$or': [{'_id': 2}, {'_id': 3}]}
ret = col.delete_many(query)
print(ret.deleted_count)
# 2
for doc in col.find():
print(doc)
# {'_id': 1, 'name': 'John'}
find_one_and_delete:尋找並刪除單個文件,返回這個文件的值:
query = {'name': 'John'}
ret = col.find_one_and_delete({'name': 'John'})
print(ret)
# {'_id': 1, 'name': 'John'}
print(col.count_documents(query))
# 0
可以使用 drop() 方法來刪除一個集合
db = client['first_demo']
col = db['student']
col.drop()
可以在終端進入資料庫查詢
> use first_demo
switched to db first_demo
> show tables
sites