1. 程式人生 > >MongoDB-增、刪、改、查

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