在 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
{'_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) #
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'
进行插入:
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操作符是基于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'}
其他:
使用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