{ $push: {<字段名1>: <值1>, <字段名2>: <值2>, … } }
$push将给定数值(<值1>)插入到目标数组(<字段名1>)中,操作对象必须为数组类型的字段。如果记录中不存在指定的字段名,将指定的字段名以数组对象的形式推入到记录中并填充其指定的数值;如果记录中存在指定的字段名,且字段名存在指定的数值,指定的数值也会被推入到记录中。
def test1(): conn = ServerMongoStore.test_conn() for i in range(10): conn.update_one({"name": "test1"}, {"$push": { "locs": {"name": str(i), "create_time": randint(0, 100)}}}, True) item = conn.find_one({"name": "test1"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果:
[{'name': '0', 'create_time': 70}, {'name': '1', 'create_time': 5}, {'name': '2', 'create_time': 79}, {'name': '3', 'create_time': 5}, {'name': '4', 'create_time': 34}, {'name': '5', 'create_time': 70}, {'name': '6', 'create_time': 55}, {'name': '7', 'create_time': 70}, {'name': '8', 'create_time': 44}, {'name': '9', 'create_time': 13}]会根据create_time 增序的对数据进行排序。一般来说,向数组尾部插入的效率会更高。
def test2(): conn = ServerMongoStore.test_conn() for i in range(10): conn.update_one({"name": "test2"}, {"$push": { "locs": {"$each": [{"name": str(i), "create_time": randint(0, 100)}], "$sort": {"create_time": 1}}}}, True) item = conn.find_one({"name": "test2"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果:
[{'name': '8', 'create_time': 3}, {'name': '3', 'create_time': 27}, {'name': '9', 'create_time': 37}, {'name': '5', 'create_time': 44}, {'name': '0', 'create_time': 49}, {'name': '4', 'create_time': 49}, {'name': '1', 'create_time': 57}, {'name': '6', 'create_time': 73}, {'name': '7', 'create_time': 85}, {'name': '2', 'create_time': 99}]结果
[{'name': '4', 'create_time': 72}, {'name': '7', 'create_time': 72}, {'name': '1', 'create_time': 85}, {'name': '9', 'create_time': 87}, {'name': '8', 'create_time': 100}]{ $addtoset: { <字段名1>: [ <值1>,<值2>,…,<值N>] ,<字段名2>: [ <值1>,<值2>,…,<值N> ], … } }
$addtoset是向数组对象中添加元素和值,操作对象必须为数组类型的字段
def test4(): conn = ServerMongoStore.test_conn() for i in range(100): conn.update_one({"name": "test4"}, {"$addToSet": { "locs": randint(0, 5)}}, True) item = conn.find_one({"name": "test4"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果:
[3, 5, 0, 2, 1, 4]结果
[1, 2, 0, 4, 3, 5]{ $push_all: {<字段名1>:[<值1>,<值2>,…,<值N>], <字段名2>: [<值1>,<值2>,…,<值N>], … } }
$push_all向指定数组对象(如<字段名1>)推入每一个指定值([<值1>,<值2>,…,<值N>])。操作对象必须为数组类型的字段。如果记录中不存在指定的数组对象,向记录推入指定的数组对象和每一个指定的值([<值1>,<值2>,…,<值N>]);如果指定的值存在数组对象中,同样被推入到数组对象中。
def test6(): conn = ServerMongoStore.test_conn() updates = [] for i in range(10): updates.append({"name": str(i), "create_time": randint(0, 100)}) conn.update_one({"name": "test6"}, {"$pushAll": { "locs": updates}}, True) item = conn.find_one({"name": "test6"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果
[{'name': '0', 'create_time': 41}, {'name': '1', 'create_time': 73}, {'name': '2', 'create_time': 15}, {'name': '3', 'create_time': 67}, {'name': '4', 'create_time': 7}, {'name': '5', 'create_time': 22}, {'name': '6', 'create_time': 12}, {'name': '7', 'create_time': 6}, {'name': '8', 'create_time': 48}, {'name': '9', 'create_time': 33}]{ $pop: { <字段名1>: <值1>, <字段名2>: <值2>, … } }
$pop 操作是删除指定数组对象(<字段名1>,<字段名2>,…)尾部 N 个元素,N 的大小由“<值>"决定。如果记录中不存在指定的数组对象,则不做任何操作;如果 N 大于数组对象的长度,数组对象的长度更新为 0,即它的元素全部被删除;如果 N < 0,则从数组头部删除 N 个元素
def test7(): conn = ServerMongoStore.test_conn() conn.update_one({"name": "test1"}, {"$pop":{"locs":1}}) item = conn.find_one({"name": "test1"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果
[{'name': '0', 'create_time': 70}, {'name': '1', 'create_time': 5}, {'name': '2', 'create_time': 79}, {'name': '3', 'create_time': 5}, {'name': '4', 'create_time': 34}, {'name': '5', 'create_time': 70}, {'name': '6', 'create_time': 55}, {'name': '7', 'create_time': 70}, {'name': '8', 'create_time': 44}]{ $pull: { <字段名1>: <值1>, <字段名2>: <值2>, … } }
$pull 要求操作的记录中 <字段名> 的值必须是数组,它从数组中删除与 <值> 相同的元素
def test8(): conn = ServerMongoStore.test_conn() conn.update_one({"name": "test1"}, {"$pull":{"locs": {'name': '0', 'create_time': 70}}}) item = conn.find_one({"name": "test1"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果
[{'name': '1', 'create_time': 5}, {'name': '2', 'create_time': 79}, {'name': '3', 'create_time': 5}, {'name': '4', 'create_time': 34}, {'name': '5', 'create_time': 70}, {'name': '6', 'create_time': 55}, {'name': '7', 'create_time': 70}, {'name': '8', 'create_time': 44}]{ $pull_all: { <字段名1>: [ <值1>, <值2>, …, <值N> ], <字段名2>: [ <值1>, <值2>, …, <值N> ], … } }
$pull_all 与 p u l l 功 能 类 似 。 区 别 在 于 : pull 功能类似。区别在于: pull功能类似。区别在于:pull 只能匹配某个字段的一个值,$pull_all 能匹配某个字段的多个值。
def test9(): conn = ServerMongoStore.test_conn() conn.update_one({"name": "test1"}, {"$pullAll":{"locs": [{'name': '1', 'create_time': 5}, {'name': '2', 'create_time': 79}, {'name': '3', 'create_time': 5}, {'name': '4', 'create_time': 34}]}}) item = conn.find_one({"name": "test1"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果:
[{'name': '5', 'create_time': 70}, {'name': '6', 'create_time': 55}, {'name': '7', 'create_time': 70}, {'name': '8', 'create_time': 44}]{ $pull_by: { <字段名1>: <值1>, <字段名2>: <值2>, … } }
$pull_by 与 $pull 功能类似。
区别在于:
$pull_by 若 <值> 为对象时,只要 <值> 中的所有字段值与数组元素的字段值相同,则认为匹配成功,并删除数组中的元素。
$pull 若 <值> 为对象时,需要数组元素的每个字段值都与 <值> 中的字段值相同,才认为匹配成功,并删除数组中的元素。
在python中 $pull 操作符同样支持 $pull_by 操作
def test10(): conn = ServerMongoStore.test_conn() conn.update_one({"name": "test1"}, {"$pull":{"locs": {"create_time": {"$gt": 0}}}}) item = conn.find_one({"name": "test1"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs"))结果:
[]结果
{'name': '4', 'create_time': 83}很多情况下,并不知道要修改数组中哪个元素,可以使用“$”来定位要修改的元素。但要注意,定位操作只能定位到匹配的第一个元素
def test13(): conn = ServerMongoStore.test_conn() conn.update_one({"name": "test3", "locs.create_time":{"$gt":0}}, {"$inc": {"locs.$.create_time": 1}}) item = conn.find_one({"name": "test3"}, {"locs": 1, "_id": 0}) if item: print(item.get("locs")[:2])结果
[{'name': '4', 'create_time': 86}, {'name': '7', 'create_time': 72}]查询条件匹配到了数组中的某个元素, 返回整个文档
def test14(): conn = ServerMongoStore.test_conn() item = conn.find_one({"locs": {"name": "4","create_time": 86}}) if item: print(item.get("name"))结果
test3结果
test3结果
test3结果
{'_id': ObjectId('5efd7ccd7bfc4296095cd6ea'), 'locs': [{'create_time': 86}, {'create_time': 72}, {'create_time': 85}, {'create_time': 87}, {'create_time': 100}]}返回了数组尾部2个元素, 想返回开头则{“locs”:{"$slice": 2}}
{'_id': ObjectId('5efd7ccd7bfc4296095cd6ea'), 'name': 'test3', 'locs': [{'name': '9', 'create_time': 87}, {'name': '8', 'create_time': 100}]}$slice 也支持数组
def test17(): conn = ServerMongoStore.test_conn() item = conn.find_one({"name":"test3"},{"locs":{"$slice": [1,3]}}) if item: print(item)结果是数组首尾都包含的
{'_id': ObjectId('5efd7ccd7bfc4296095cd6ea'), 'name': 'test3', 'locs': [{'name': '7', 'create_time': 72}, {'name': '1', 'create_time': 85}, {'name': '9', 'create_time': 87}]}