上一篇文章已经介绍了pymongo的基本操作,这里我们介绍一个pymongo高级一些的操作,比如内嵌域和数组的查询,条件符号查询以及查询结果的排序。聚集操作和map-reduce。废话就不多说了,直接看代码:
查询和排序
import pymongo
from pymongo import MongoClient
#连接字符串 mongodb://[username:password@]host1[:port1]]][/[database][?options]]
client = MongoClient("mongodb://test:test@192.168.1.235:27017/test?authMechanism=SCRAM-SHA-1") #MONGODB-CR
db = client["test"]
#插入
db.restaurants.remove()
db.restaurants.insert([
{
"address": { "zipcode": "10075", },
"borough": "Manhattan",
"cuisine": "Italian",
"grades": [ {"grade": "A", "score":30},
{"grade": "B", "score":15}],
},
{
"address": { "zipcode": "10075", },
"borough": "Queens",
"cuisine": "Brazilian",
"grades": [ {"grade": "A", "score":30},
{"grade": "B", "score":15} ],
},
])
#顶级属性的查询
cursor = db.restaurants.find({"name":"Vella"})
for doc in cursor:
print(doc)
#内嵌属性的查询
cursor = db.restaurants.find({"address.zipcode":"10075"})
for doc in cursor:
print(doc)
#数组的查询
cursor = db.restaurants.find({"grades.grade": "B"})
for doc in cursor:
print(doc)
#条件符号查询
cursor = db.restaurants.find({"grades.score": {"$gt": 30}})#gt
for doc in cursor:
print(doc)
cursor = db.restaurants.find({"grades.score": {"$lt": 10}})#lt
for doc in cursor:
print(doc)
cursor = db.restaurants.find({"cuisine": "Italian", "address.zipcode": "10075"})#and
for doc in cursor:
print(doc)
cursor = db.restaurants.find({"$or": [{"cuisine": "Italian"}, {"address.zipcode": "10075"}]})#or
for doc in cursor:
print(doc)
#查询结果排序
cursor = db.restaurants.find().sort([("borough", pymongo.ASCENDING), ("address.zipcode", pymongo.ASCENDING) ])
for doc in cursor:
print("sort:",doc)
client.close()
输出结果如下:
{'address': {'zipcode': '10075'}, 'cuisine': 'Italian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1d'), 'borough': 'Manhattan'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Brazilian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1e'), 'borough': 'Queens'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Italian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1d'), 'borough': 'Manhattan'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Brazilian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1e'), 'borough': 'Queens'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Italian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1d'), 'borough': 'Manhattan'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Italian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1d'), 'borough': 'Manhattan'}
{'address': {'zipcode': '10075'}, 'cuisine': 'Brazilian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1e'), 'borough': 'Queens'}
sort: {'address': {'zipcode': '10075'}, 'cuisine': 'Italian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1d'), 'borough': 'Manhattan'}
sort: {'address': {'zipcode': '10075'}, 'cuisine': 'Brazilian', 'grades': [{'grade': 'A', 'score': 30}, {'grade': 'B', 'score': 15}], '_id': ObjectId('59829dd5762c3126d4957e1e'), 'borough': 'Queens'}
聚集操作
import pymongo
from pymongo import MongoClient
#连接字符串 mongodb://[username:password@]host1[:port1]]][/[database][?options]]
client = MongoClient("mongodb://test:test@192.168.1.235:27017/test?authMechanism=SCRAM-SHA-1") #MONGODB-CR
db = client["test"]
#插入
db.restaurants.remove()
db.restaurants.insert([
{
"address": { "zipcode": "10075", },
"borough": "Manhattan",
"cuisine": "Italian",
"grades": [ {"grade": "A", "score":30},
{"grade": "B", "score":15}],
},
{
"address": { "zipcode": "10075", },
"borough": "Queens",
"cuisine": "Brazilian",
"grades": [ {"grade": "A", "score":30},
{"grade": "B", "score":15} ],
},
])
#聚集操作
#根据属性分组并计算数量
cursor = db.restaurants.aggregate([{"$group": {"_id": "$borough", "count": {"$sum": 1}}}] )
for doc in cursor:
print("aggregate:",doc)
#先过滤再分组
cursor = db.restaurants.aggregate(
[
{"$match": {"borough": "Queens", "cuisine": "Brazilian"}},
{"$group": {"_id": "$address.zipcode", "count": {"$sum": 1}}}
]
)
for doc in cursor:
print("aggregate:",doc)
输出结果如下:
aggregate: {'count': 1, '_id': 'Queens'}
aggregate: {'count': 1, '_id': 'Manhattan'}
aggregate: {'count': 1, '_id': '10075'}
map-reduce
from pymongo import MongoClient
#连接字符串 mongodb://[username:password@]host1[:port1]]][/[database][?options]]
client = MongoClient("mongodb://test:test@192.168.1.235:27017/test?authMechanism=SCRAM-SHA-1") #MONGODB-CR
db = client["test"]
#map-reduce操作,此操作一般用来做更灵活的聚合操作,使用js脚本来编写map方法和reduce方法,结果会产生一个新的集合。
#比如当前需求如下,统计某小区各种宠物的数量
from bson.code import Code
db.animals.remove()
db.animals.insert({"name": "aaa", "animals": ["dog", "cat"]})
db.animals.insert({"name": "bbb", "animals": ["cat"]})
db.animals.insert({"name": "ccc", "animals": ["mouse", "cat", "dog"]})
db.animals.insert({"name": "ddd", "animals": []})
mapfun = Code("function () {"
" this.animals.forEach(function(z) {emit(z, 1);});"#emit函数把结果传递给reduce函数
"}")
reducefun = Code("function (key, values) {"
" var total = 0;"
" for (var i = 0; i < values.length; i++) {"
" total += values[i];"
" }"
" return total;"
"}")
result = db.animals.map_reduce(mapfun,reducefun,"results")#会产生一个新的集合,名字叫results。可以在mongo中使用show collections查看。
for doc in result.find():
print("map-reduce",doc)
#再比如统计各班各科成绩的总和
db.students.remove()
#学生数据如下
db.students.insert({"id":"1","sex":"boy","class":"181","scores":{"math":80,"english":60,"chinese":90}})
db.students.insert({"id":"2","sex":"gril","class":"182","scores":{"math":100,"english":90,"chinese":80}})
db.students.insert({"id":"3","sex":"boy","class":"182","scores":{"math":60,"english":50,"chinese":88}})
db.students.insert({"id":"4","sex":"gril","class":"182","scores":{"math":79,"english":87,"chinese":78}})
db.students.insert({"id":"5","sex":"gril","class":"181","scores":{"math":79,"english":87,"chinese":78}})
mapfun = Code("function(){"
" emit(this.class,this.scores);" #emit函数把结果传递给reduce函数
"}")
reducefun = Code("function(key,values){"
" var result = {math:0,english:0,chinese:0};"
" for(var i = 0;i < values.length;i++){"
" result.math += values[i].math;"
" result.english += values[i].english;"
" result.chinese += values[i].chinese;"
" }"
" return result;"
"}")
result = db.students.map_reduce(mapfun,reducefun,"class_scores")
for doc in result.find():
print("map-reduce1",doc)
client.close()
输出结果如下:
map-reduce {'value': 3.0, '_id': 'cat'}
map-reduce {'value': 2.0, '_id': 'dog'}
map-reduce {'value': 1.0, '_id': 'mouse'}
map-reduce1 {'value': {'chinese': 168.0, 'english': 147.0, 'math': 159.0}, '_id': '181'}
map-reduce1 {'value': {'chinese': 246.0, 'english': 227.0, 'math': 239.0}, '_id': '182'}