首先导入:
from pymongo import MongoClient
连接mongodb:
没有密码的连接方式
mongo_client = MongoClient(mongo_host, mongo_port, connect=False)
有密码的认证登录方式:
self.client = pymongo.MongoClient(host="127.0.0.1", port=27017, username="user name", password="pass/word")
连接数据库:例如连接my_db数据库,没有则自动创建
mongo_db = mongo_client["my_db"]
# 或者下面这样也可以
mongo_db = mongo_client.my_db
使用集合:例如使用my_set集合,没有则自动创建
coll = mongo_db["my_set"]
# 或者下面这样也可以
coll = mongo_db.my_set
接下来是集合里面的操作
1、基本操作
(1)查找
parmas = {"age": 16, "address": "beijing"}
if params is None:
cursors = coll.find()
else:
cursors = coll.find(params)
find()内不传参时是查找的整个集合的数据,也可以通过字典传参精确查找,精确查找出来的可能没有,可能是一个,也可能是多个,无论一个还是多个,都是列表生成器对象,需要按照列表的操作方法取出来(也可以使用list方法强转列表)。
for cursor in cursors:
通过循环每一条数据进行操作
也可以按列表索引取值
条件查找操作符
符号 | 含义 | 示例 | 示例含义 |
$lt | 小于 | {‘age’: {’$lt’: 20}} | 年龄小于20 |
$gt | 大于 | {‘age’: {’$gt’: 20}} | 年龄大于20 |
$lte | 小于等于 | {‘age’: {’$lte’: 20}} | 年龄小于等于20 |
$gte | 大于等于 | {‘age’: {’$gte’: 20}} | 年龄大于等于20 |
$ne | 不等于 | {‘age’: {’$ne’: 20}} | 年龄不等于20 |
$in | 在范围内 | {‘age’: {’$in’: [20, 23]}} | 年龄在20到30的范围内 |
$nin | 不在范围内 | {‘age’: {’$nin’: [20, 23]}} | 年龄不在20到30的范围内 |
$or | 或条件 | {"$or":[{“age”:30},{“address”: “nanjing”}]} | 年龄30岁或者地址是nangjing的 |
$and | 且条件 | and基本不用,因为相当于find()内传字典时,传入多对键值对而已,例{“name”: “laowang”, “age”: 40} |
查找集合中年龄大于15小于20的所有数据
cursors = coll.find({"age": {"$gt": 15, "$lt": 20}})
功能符号归类如下:
符号 | 含义 | 示例 | 示例含义 |
$regex | 匹配正则 | {‘name’: {’$regex’: ‘^M.*’}} | name以M开头 |
$exists | 属性是否存在 | {‘name’: {’$exists’: True}} | name属性存在 |
$type | 类型判断 | {‘age’: {’$type’: ‘int’}} | age的类型为int |
$mod | 数字模操作 | {‘age’: {’$mod’: [5, 0]}} | 年龄模5余0 |
$text | 文本查询 | {"$text": {"$search’: ‘Mike’}} | text类型的属性中包含Mike字符串 |
$where | 高级条件查询 | {’$where’: ‘obj.fans_count == obj.follows_count’} | 自身粉丝数等于关注数 |
正则匹配name字段以M开头的数据
例如查询名字以M开头的学生数据,示例如下:
result = coll.find({“name”: {"$regex": “^M.*”}})
查找某个字段是某种类型的
#找出name的类型是String的
cursors = coll.find({"name": {'$type': 2}})
#类型 值
Double 1
String 2
Object 3
Array 4
Binary data 5
Undefined 6 已废弃
Object id 7
Boolean 8
Date 9
Null 10
Regular Expression 11
JavaScript 13
Symbol 14
JavaScript (with scope) 15
32-bit integer 16
Timestamp 17
64-bit integer 18
Min key 255 Query with -1.
Max key 127
find_one: 查找一条数据,用法和find相同,但是结果返回的是这条数据的字典结构
对查找出来的数据进行排序
使用sort()方法对数据进行排序,sort()方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序,-1为降序。
这里升序的1也可以使用pymongo.ASCENDING,降序的-1也可以使用pymongo.DESCENDING
cursors = coll.find().sort([("age", 1), ("student_id", -1)])
cursors = coll.find().sort([("age", pymongo.ASCENDING), ("student_id", pymongo.DESCENDING)])
偏移:某些情况下,我们想取查询出来的数据中忽略掉前几个,可以使用skip()
偏移
cursors = coll.find().skip(2)
注:在数据量非常庞大的时候,如千万、亿级,最好不要使用大的偏移量来查询数据,很可能会导致内存溢出,可以使用类似
cursors = coll.find({"_id": {"$gt": ObjectId(“5c6a52868b8c3c6f24ea5edb”)}})
这样的方法来查询,记录好上次查询的_id
限制数据条数:某些情况下我们只想取查出来的前几个,可以使用limit()
值得注意的是,在数据库数量非常庞大的时候,如千万、亿级别,最好不要使用大的偏移量来查询数据,很可能会导致内存溢出,可以使用类似find({’_id’: {’$gt’: ObjectId(‘593278c815c2602678bb2b8d’)}}) 这样的方法来查询,记录好上次查询的_id
只取前10条数据
cursors = coll.find().limit(10)
计数统计
nums = coll.find().count()
以上方法可以组合使用
(2) 插入数据
insert、insert_one、insert_many
insert: 可以插入一条数据,也可以插入多条数据,拥有insert_one和insert_many的功能,但是官方在python3的版本中已经不推荐使用了,推荐使用后两个,当然仍然使用也没问题,insert在插入一条数据的时候,会返回插入数据的_id,插入多条时候,会返回一个_id列表。
result = coll.insert({“name”: “laowang”, “age”: 40}) # 结果会返回插入数据的_id
result = coll.insert([{“name”: “laowang”, “age”: 40}, {“name”: “lisi”, “age”: 41}, {“name”: “wangwu”, “age”: 42}])
结果返回一个列表,里面包含插入所有数据的_id
insert_one: 插入一条数据,和insert插入一条数据用法相同,只不过返回的结果是个InsertOneResult对象,我们可以调用inserted_id属性获取_id。
insert_many: 插入多条数据,和insert插入多条数据用法相同,只不过返回的结果是个InsertOneResult对象,我们可以调用inserted_ids属性获取_id列表
(3)更新
update()、update_one()、update_many() 更新时如无此字段,则会添加
update() 同insert一样,它兼具了后两个的功能,也是官方已经不推荐使用了,推荐使用后两个
这里讲下update_one和update_many的使用吧
update_one(): 此方法只匹配查出来的第一条数据去进行更新
把laowang的年龄改为42,address改为nanjing
condition = {"name": "laowang"}
update = {"$set": {"age": 42, "address": "nanjing"}}
result = coll.update(filter=condition, update=update)
返回的结果是UpdateResult类型,调用match_count和modified_count属性分别可以获得匹配的数据条数和影响的数据条数
高级一点的用法:
把老王的年龄加1
condition = {"name": "laowang"}
update = {"$inc": {"age": 1}}
result = coll.update(filter=condition, update=update)
update_many(): 使用同update_one(), 但是它会更新所有匹配出来的数据
(4)删除
remove: 使用比较简单,调用时会把符合条件的所有数据全部删除,同insert一样,也有两个新的推荐使用方法,delete_one和delete_many
remove会删除所有匹配到的数据,返回结果是执行结果状态和执行的条数
result = coll.remove({"age": 20})
delete_one:只删除匹配的第一条数据,返回结果是DeleteResult对象,可以调用deleted_count属性获取删除数据的条数
result = coll.delete_one({"age": 20})
delete_many:只删除匹配的第一条数据,返回结果是DeleteResult对象,可以调用deleted_count属性获取删除数据的条数
result = coll.delete_many({"age": 20})
(5)distinct
查找某个字段有多少种类
查找数据表中,所有人中,一共有多少个省份的人,假如50人,有20个省份的人,则查询后返回的是一个列表,列表中包含所有的省份,但不重复
result = coll.distinct("address")
2 高级用法
(1)高级查找: aggregate
query_param = {}
match_params = {"$match": query_param}
group = {"_id": {},
"total_integral": {"$sum": "$integral"},
}
group_params = {"$group": group}
sort = {
"_id.student_id": pymongo.ASCENDING,
"_id.age": pymongo.ASCENDING
}
sort_params = {"$sort": sort}
result = coll.aggregate([match_params, group_params, sort_params])
(2)高级操作
bulk_write
待完成
3 加索引
为字段创建索引, 其中的1和-1分别表示正序与负序排列,创建唯一索引,不加unique=True的话默认是普通的索引,即unique=False
create_index 和 ensure_index,用法相同,ensure_index在pymongo3.0已弃用,推荐使用create_index
key_list = [(“索引字段名1”, 1), (“索引字段名2”, 1), (“索引字段名3”, 1),]
coll.create_index(key_list, unique=True)
使用create_index或则ensure_index创建与之前“唯一性unique”不同的同名索引,会出现“OperationFailure”错误。
解决方法:
首先,判断有无同名索引;然后判断同名索引是否为唯一索引;
若有同名索引,且非唯一索引,则删除已有的同名索引,然后重新建立索引。
from pymongo import MongoClient
def create_unique_index():
"""
创建唯一索引
:return:
"""
coll = MongoClient('localhost').get_database('test_db').get_collection('test_col_1')
all_index = coll.index_information()
print
all_index # 打印所有索引信息
has_id_index = all_index.get("id_1", False) # 判断有无“id”索引
if has_id_index:
if all_index['id_1'].get('unique', False): # id为唯一索引
pass
else:
coll.drop_index([("id", 1)])
coll.create_index([("id", 1)], unique=True) # 尝试创建唯一索引
else:
coll.create_index([("id", 1)], unique=True) # 尝试创建唯一索引
if __name__ == "__main__":
create_unique_index()
未完,待续。。。。。。。。