1. pymongo官方文档学习
学习官方文档,中文版本,快速上手
2. 学习资料
https://www.jianshu.com/p/acc57241f9f0
3. 操作指南
更新操作update
在实际中,更新文档往往是更新文档的一部分内容,在 MongoDB 中,我们可以使用更新修改器 (update modifier) 来对文档中某些字段进行更新,常用的修改器有以下几个:
- $set用来指定一个字段的值,如果不存在,将创建一个新的字段
- $unset删除一个字段
- $inc用来增加(或减少)一个已有键的值,如果不存在将会创建一个
- $push 向已有的数组末尾添加一个元素
- $addToSet避免插入重复数据
- $pull删除元素,基于特定条件
- $each遍历列表操作
- $pop删除元素
$set
>> document = {'name': 'joe',
'age': 30,
'sex': 'male',
'location': 'Wisconsin' }
>> table.insert_one(document)
>> print(user.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'_id': ObjectId('5ac9836829561f64220f6f9d')}, {'$set' : {'favorite': 'War adn Peace'}})
>> print(table.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'favorite': 'War adn Peace',
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$set': {'favorite': 'Green Eggs and Ham'}})
>> print(user.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'favorite': 'Green Eggs and Ham',
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$set': {'favorite': ["Cat's Cradle": , "Foundation Trilogy", "Ender's Game"]}})
>> print(user.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'favorite': ["Cat's Cradle", 'Foundation Trilogy', "Ender's Game"],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> blog = database.blog
>> posts = {'title': 'A Blog Post', 'content': '...', 'author': {'name': 'joe', 'email': 'joe@example.com'}}
>> blog.insert_one(posts)
>> blog.find_one({'title':'A Blog Post'})
>> {'_id': ObjectId('5ac98a0a29561f64220f6f9e'),
'author': {'email': 'joe@example.com', 'name': 'joe'},
'content': '...',
'title': 'A Blog Post'}
>> blog.update_one({'author.name': 'joe'}, {'$set': {'author.name': 'joe schmoe'}})
>> blog.find_one()
>> {'_id': ObjectId('5ac98a0a29561f64220f6f9e'),
'author': {'email': 'joe@example.com', 'name': 'joe schmoe'},
'content': '...',
'title': 'A Blog Post'}
$unset
>> print(table.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'favorite': ["Cat's Cradle", 'Foundation Trilogy', "Ender's Game"],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$unset': {'favorite': 1}})
>> print(table.find_one({'_id':'5ac9836829561f64220f6f9d'}))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
$inc
>> games = test_database.games
>> games.insert_one({'game': 'pinball', 'user': 'joe'})
>> print(games.find_one('_id':'5ac9c55f29561f64220f6f9f'))
>> {'_id': ObjectId('5ac9c55f29561f64220f6f9f'), 'game': 'pinball', 'user': 'joe'}
>> games.update_one({'game': 'pinball', 'user': 'joe'}, {'$inc': {'score': 50}})
>> print(games.find_one('_id':'5ac9c55f29561f64220f6f9f'))
>> {'_id': ObjectId('5ac9c55f29561f64220f6f9f'),
'game': 'pinball',
'score': 50,
'user': 'joe'}
>> games.update_one({'game': 'pinball', 'user': 'joe'}, {'$inc': {'score': 5000}})
>> print(games.find_one('_id':'5ac9c55f29561f64220f6f9f'))
>> {'_id': ObjectId('5ac9c55f29561f64220f6f9f'),
'game': 'pinball',
'score': 5050,
'user': 'joe'}
$push
>> blog = test_database.blog
>> print(blog.find_one('_id':'5ac98a0a29561f64220f6f9e'))
>> {'_id': ObjectId('5ac98a0a29561f64220f6f9e'),
'author': {'email': 'joe@example.com', 'name': 'joe schmoe'},
'content': '...',
'title': 'A Blog Post'}
>> blog.update_one({'title': 'A Blog Post'},
{'$push' : {'comments': {'name': 'joe', 'email': 'joe@example.com', 'content': 'nice post.'}}})
>> print(blog.find_one('_id':'5ac98a0a29561f64220f6f9e'))
>> {'_id': ObjectId('5ac98a0a29561f64220f6f9e'),
'author': {'email': 'joe@example.com', 'name': 'joe schmoe'},
'comments': [{'content': 'nice post.', 'email': 'joe@example.com', 'name': 'joe'}],
'content': '...',
'title': 'A Blog Post'}
>> blog.update_one({'title': 'A Blog Post'},
{'$push' : {'comments': {'name': 'bob', 'email': 'bob@example.com', 'content': 'good post.'}}})
>> print(blog.find_one('_id':'5ac98a0a29561f64220f6f9e'))
>> {'_id': ObjectId('5ac98a0a29561f64220f6f9e'),
'author': {'email': 'joe@example.com', 'name': 'joe schmoe'},
'comments': [{'content': 'nice post.','email': 'joe@example.com', 'name': 'joe'},
{'content': 'good post.', 'email': 'bob@example.com', 'name': 'bob'}],
'content': '...',
'title': 'A Blog Post'}
$addToSet
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'},{'$push': {'emails': 'joe@example.com'}})
>> table.update_one({'name': 'joe'},{'$push': {'emails': 'joe@gmail.com'}})
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@example.com', 'joe@gmail.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$addToSet': {'emails': 'joe@example.com'}})
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@example.com', 'joe@gmail.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$push': {'emails': 'joe@example.com'}})
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@example.com', 'joe@gmail.com', 'joe@example.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
$pull
>> table.update_one({'name': 'joe'}, {'$pull': {'emails': 'joe@example.com'}})
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@gmail.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
$each
>> table.update_one({'name': 'joe'}, {'$pull': {'emails': 'joe@example.com'}})
>> print(table.find_one('_id':'5ac9836829561f64220f6f9d'))
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@gmail.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
pop
>> table.find_one({'_id':'5ac9836829561f64220f6f9d'})
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@gmail.com', 'joe@example.com', 'joe@outlook.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$pop': {'emails': -1}})
>> table.find_one({'_id':'5ac9836829561f64220f6f9d'})
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@example.com', 'joe@outlook.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
>> table.update_one({'name': 'joe'}, {'$pop': {'emails': 1}})
>> table.find_one({'_id':'5ac9836829561f64220f6f9d'})
>> {'_id': ObjectId('5ac9836829561f64220f6f9d'),
'age': 30,
'emails': ['joe@example.com'],
'location': 'Wisconsin',
'name': 'joe',
'sex': 'male'}
基于位置的数组修改器
如果文档中存在数组记录,而且数组记录有多个值,我们可以视同位置修改器或者定位符 $ 来修改数组其中的某些值。
>> posts = {'content': '...',
'comments': [{'comment': 'good post', 'author': 'John', 'votes': 0},
{'comment': 'i thought it was too short', 'author': 'Claire', 'votes': 3},
{'comment': 'free watches', 'auth: or': 'Alice', 'votes': -1}]}
>> blog.insert_one(posts)
>> blog.find_one({'_id':'5aca17cf29561f64220f6fa0'})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'John', 'comment': 'good post', 'votes': 0},
{'author': 'Claire', 'comment': 'i thought it was too short', 'votes': 3},
{'author': 'Alice', 'comment': 'free watches', 'votes': -1}],
'content': '...'}
>> blog.update_one({'_id': '5aca17cf29561f64220f6fa0'}, {'$inc': {'comments.0.votes': 1}})
>> blog.find_one({'_id':'5aca17cf29561f64220f6fa0'})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'John', 'comment': 'good post', 'votes': 1},
{'author': 'Claire', 'comment': 'i thought it was too short', 'votes': 3},
{'author': 'Alice', 'comment': 'free watches', 'votes': -1}],
'content': '...'}
>> blog.update_one({'comments.author': 'John'}, {'$set': {'comments.$.author': 'Jim'}})
>> blog.find_one({'_id':'5aca17cf29561f64220f6fa0'})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'Jim', 'comment': 'good post', 'votes': 1},
{'author': 'Claire', 'comment': 'i thought it was too short', 'votes': 3},
{'author': 'Alice', 'comment': 'free watches', 'votes': -1}],
'content': '...'}
条件查询
比较操作符
- $lt小于
- $lte小于等于
- $ge大于
- $gte大于等于
- $ne 不等于
>> for data in table.find():
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
>> for data in table.find({'age': {'$gt': 26}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
>> for data in table.find({'age': {'$gte': 26}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
>> for data in table.find({'age': {'$lt': 28}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
>> for data in table.find({'age': {'$lte': 28}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
>> for data in table.find({'age': {'$ne': 28}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
$in 和 $nin 的用法
使用 $in和 $nin 操作符来匹配一个键的多个值。
>> for data in table.find({'name': {'$in': ['joe', 'mike']}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
>> for data in table.find({'name': {'$nin': ['mike']}}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa1'), 'name': 'joe', 'age': 26}
{'_id': ObjectId('5acb225729561f64220f6fa3'), 'name': 'jake', 'age': 26}
$or 的用法
如果需要查询两个条件中其中一个为真的查询结果,可以使用 $or 操作符。
>> kate = {'name': 'kate', 'age': 30}
>> table.insert_one(kate)
>> for data in table.find({'$or': [{'name': 'mike'}, {'age': 30}]}):
print(data)
>> {'_id': ObjectId('5acb225729561f64220f6fa2'), 'name': 'mike', 'age': 28}
{'_id': ObjectId('5acb6cfc29561f64220f6fa4'), 'name': 'kate', 'age': 30}
null 值查询和$exists条件判定
在 Python 中,mongodb 中的 null 值以 None 表示。但在查询 null 值中,会出现比较奇怪的情况。
>> c = test_database.c
>> c.insert_many({'y': None}, {'y': 1}, {'y': 2})
>> for data in c.find():
print(data)
>> {'_id': ObjectId('5acb738029561f64220f6fa5'), 'y': None}
{'_id': ObjectId('5acb741029561f64220f6fa6'), 'y': 1}
{'_id': ObjectId('5acb741029561f64220f6fa7'), 'y': 2}
>> for data in c.find({'y': None}):
print(data)
>> {'_id': ObjectId('5acb738029561f64220f6fa5'), 'y': None}
>> for data in c.find({'z': None}):
print(data)
>> {'_id': ObjectId('5acb738029561f64220f6fa5'), 'y': None}
{'_id': ObjectId('5acb741029561f64220f6fa6'), 'y': 1}
{'_id': ObjectId('5acb741029561f64220f6fa7'), 'y': 2}
可以看到,当我们查找 {‘z’: None} 的时候,会把所有不包含这个条件的文档都查询出来,这样明显和我们的意图不一致,因此我们需要增加一个限定。
>> for data in c.find({'z': {'$in': [None], '$exists': 1}}):
print(data)
>>
通过加上 $exists 的限定,我们可以看到代码执行完之后并没有查询结果输出,符合我们的查询意图。
查询数组
- $all 匹配多个元素数组
- $size 匹配特定长度的数组
- $slice 返回匹配数组的一个子集
为方便演示,我们会先创建一个 food 的集合用来存放水果的文档记录。
>> food = test_database.food
>> food.insert_one({'_id': 1, 'fruit': ['apple', 'banana', 'peach']})
>> food.insert_one({'_id': 2, 'fruit': ['apple', 'kumquat', 'orange']})
>> food.insert_one({'_id': 3, 'fruit': ['cherry', 'banana', 'apple']})
>> for data in food.find():
print(data)
>> {'_id': 1, 'fruit': ['apple', 'banana', 'peach']}
{'_id': 2, 'fruit': ['apple', 'kumquat', 'orange']}
{'_id': 3, 'fruit': ['cherry', 'banana', 'apple']}
$all的用法
>> result = food.find({'fruit': {'$all': ['apple', 'banana']}})
>> for data in result:
print(data)
>> {'_id': 1, 'fruit': ['apple', 'banana', 'peach']}
{'_id': 3, 'fruit': ['cherry', 'banana', 'apple']}
>> result = food.find({'fruit.1': 'banana'})
>> for data in result:
print(data)
>> {'_id': 1, 'fruit': ['apple', 'banana', 'peach']}
{'_id': 3, 'fruit': ['cherry', 'banana', 'apple']}
$size的用法
>> food.update_one({'_id': 2}, {'$push': {'fruit': 'strawbreey'}})
>> for data in food.find():
print(data)
>> {'_id': 1, 'fruit': ['apple', 'banana', 'peach']}
{'_id': 2, 'fruit': ['apple', 'kumquat', 'orange', 'strawbreey']}
{'_id': 3, 'fruit': ['cherry', 'banana', 'apple']}
>> result = food.find({'fruit': {'$size': 3}})
>> for data in result:
print(data)
>> {'_id': 1, 'fruit': ['apple', 'banana', 'peach']}
{'_id': 3, 'fruit': ['cherry', 'banana', 'apple']}
$slice的用法
>> blog.find_one({'_id':'5aca17cf29561f64220f6fa0'})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'Jim', 'comment': 'good post', 'votes': 1},
{'author': 'Claire', 'comment': 'i thought it was too short', 'votes': 3},
{'author': 'Alice', 'comment': 'free watches', 'votes': -1}],
'content': '...'}
>> blog.find_one({}, {'comments': {'$slice': 2}})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'Jim', 'comment': 'good post', 'votes': 1},
{'author': 'Claire', 'comment': 'i thought it was too short', 'votes': 3}],
'content': '...'}
>> blog.find_one({}, {'comments': {'$slice': -1}})
>> {'_id': ObjectId('5aca17cf29561f64220f6fa0'),
'comments': [{'author': 'Alice', 'comment': 'free watches', 'votes': -1}],
'content': '...'}
min()和max() 的使用
如果我们以某个区间值作为查询条件,我们可以使用比较操作符来实现,但是,如果文档中存在值,以及值组成的数组时,查询结果往往与我们的意图不一致,这是我们就需要用到 $elemMatch 来匹配非数组元素,或者使用 min() 和 max() 方法。
>> c.insert_many([{'x': 5}, {'x': 15}, {'x': 25}, {'x': [5, 25]}])
>> c.count()
>> 4
>> for data in c.find():
print(data)
>> {'_id': ObjectId('5acc31c729561f64220f6fa8'), 'x': 5}
{'_id': ObjectId('5acc31c729561f64220f6fa9'), 'x': 15}
{'_id': ObjectId('5acc31c729561f64220f6faa'), 'x': 25}
{'_id': ObjectId('5acc31c729561f64220f6fab'), 'x': [5, 25]}
>> result = c.find({'x': {'$gt': 10. '$lt': 20}})
>> for data in result:
print(data)
>> {'_id': ObjectId('5acc31c729561f64220f6fa9'), 'x': 15}
{'_id': ObjectId('5acc31c729561f64220f6fab'), 'x': [5, 25]}
>> result = c.find({'x': {'$elemMatch': {'$gt': 10, '$lt': 20}}})
>> for data in result:
print(data)
>> // 没有输出结果
>> c.create_index('x')
>> 'x_1'
>> result = c.find({'x': {'$gt': 10, '$lt': 20}}).min([('x', 10)]).max([('x', 20)])
>> for data in result:
print(data)
>> {'_id': ObjectId('5acc31c729561f64220f6fa9'), 'x': 15}
关于min()和 max()两个方法,有两点需要注意:
使用这两个方法前,必须先要为需要查询的字段建立索引,否则会报错 这两个方法和在 mongodb 中的写法有一些不一样,在 mongodb 中,同样操作写作:min({‘x’: 10})但在 Pymongo 中,应写成min([(‘x’, 10)])注意区别,否则同样会报错。
$where 查询
针对一些比较复杂的查询,我们可以使用
w
h
e
r
e
。
然
而
,
由
于
where 。然而,由于
where。然而,由于where 可以在查询中执行任意的 Javascript,因此可能会产生出一些不安全的操作,因此,在实际生产环境中,竟可能的不用或者禁用$where。
>> foo.insert_one({'apple': 1, 'banana': 6, 'peach': 3})
>> foo.insert_one({'apple': 8, 'spinach': 4, 'watermelon': 4})
>> for data in foo:
print(data)
>> {'_id': ObjectId('5acdbf4729561f64220f6fac'), 'apple': 1, 'banana': 6, 'peach': 3}
{'_id': ObjectId('5acdbf6a29561f64220f6fad'), 'apple': 8, 'spinach': 4, 'watermelon': 4}
>> result = foo.find({'$where':
"""
function() {
for (var current in this) {
for (var other in this) {
if (current != other && this[current] == this[other]){
return true;
}
}
}
return false;
}
"""})
>> for data in result:
print(data)
>> {'_id': ObjectId('5acdbf6a29561f64220f6fad'), 'apple': 8, 'spinach': 4, 'watermelon': 4}
|