官方文档
- PyMongo: 只有API接口,而查询,过滤等的设置在Mongodb的官方文档中。
- 总结很好的中文资料,有高级特性的说明
- Mongodb官方文档
培训
Mongodb中的事务
MySQL事务
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
- 在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
一般来说,事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
例子
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
#包的导入
db = MySQLdb.connect("ip地址,本机为localhost","用户名","密码","表名")
#打开数据库的连接
cursor = db.cursor()
#使用cursor()方法获得操作游标
try:
# 执行sql语句
cursor.execute("update account set money=money-600 where name='zhangsan'")
cursor.execute("update account set money=money+600 where name='lisi'")
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚 回滚到获取游标的位置开始重新执行 看代码上面的文字有说明
db.rollback()
db.close()
#关闭数据库的连接
Mongodb也即将加入事务特性
数据类型
ObjectID
重要的操作
1. 查询find的使用
查询collection的大小
def get_size(self, table):
return self.mc[table].find().count()
查询(排序,跳跃,返回某些字段,升序降序)
def get_many(self, table, cond={}, items=None, n=0, sort_key=None, ascend=True, skip=0):
collection = self.mc[table].find(cond, items) if items else self.mc[table].find(cond)
if sort_key:
n = FLAGS.table_capacity if not n else n
res = collection.limit(n).skip(skip).sort([(sort_key, 1 if ascend else -1)])
return list(res) if res else None
else:
''' slice without sort make no sense '''
res = collection.limit(n).skip(skip)
return list(res) if res else None
# 使用,只返回'asset_id'字段
asset_dict = self.mongo_cli.get_many(table=FLAGS.asset_info, cond={'$or': [{'asset_definition.name': definition}, {'asset_definition.symbol': definition}]}, items={'asset_id': True, '_id': False})
# 返回
{'asset_id': xxx}
# 使用,只返回'address'字段和‘txs'数组的最后一个元素
db.address_info.find({}, {'_id': 0, 'address': 1, 'txs': { $slice: [-1, 1]}})
# 返回
{ "address" : "sm1q3jwsv0lhfmndnlag3kp6avpcq6pkd3xyxg7z8f", "txs" : [ "158d7d7c6a8d2464725d508fafca76f0838d998eacaacb42ccc58cfb0c155352" ] }
{ "address" : "sm1qpat0qv68yk6vtlppm0377rxxjcmj4x2jhwsnxr", "txs" : [ "b4f966eb7ce78b204b47551bbfb8c04ba769819e8681b08276e8f2e50c2b558c" ] }
{ "address" : "sm1qeckclscyjmld9wrmqkhdwjmtx3zufk8jfun99q", "txs" : [ "b908148d3cbeb1bbf31728866ea7d20e2d9a40c2533e3229b1e9e8548aa52693" ] }
{ "address" : "sm1qmzscm80frxkla6ew8g56k0743qthxqr3kq6ml4", "txs" : [ "b30e2e0759d56c6239b2e1351747a97aa5c7f321161f7e185605f5c5e6542f24" ] }
{ "address" : "sm1qhd49u5uxa8w37p3jyd96dfttfcp538ydjezk5z", "txs" : [ "b908148d3cbeb1bbf31728866ea7d20e2d9a40c2533e3229b1e9e8548aa52693" ] }
{ "address" : "sm1q7k66mj4a595t50esgvfx7xjznrc64qs9fz4clx", "txs" : [ "bd1eb6bf520b20ecf896f4b5400d779c17016c8bda30edabdf0432e2a43798aa" ] }
{ "address" : "sm1qccdqucg763kr70jnvjaxw5ncju8y7am6q53wm4", "txs" : [ "fc0685846174b6d9d9997bdacd8cf7d53c43a6d827e707c489ad4593bad3609b" ] }
{ "address" : "sm1qfadew3ksk9atzkezfcvxvxj6zvsy5degf33lzh", "txs" : [ "b908148d3cbeb1bbf31728866ea7d20e2d9a40c2533e3229b1e9e8548aa52693" ] }
{ "address" : "sm1qm3ulf032p89hawmjl7gcc2an77gztl2vhhuku6", "txs" : [ "b908148d3cbeb1bbf31728866ea7d20e2d9a40c2533e3229b1e9e8548aa52693" ] }
{ "address" : "sm1q6w768cvwr5j9egg5a00nmuppgye0uuvw78k4hu", "txs" : [ "bd1eb6bf520b20ecf896f4b5400d779c17016c8bda30edabdf0432e2a43798aa" ] }
多字段排序查询
def sort(self, key_or_list, direction=None):
"""Sorts this cursor's results.
Pass a field name and a direction, either
:data:`~pymongo.ASCENDING` or :data:`~pymongo.DESCENDING`::
for doc in collection.find().sort('field', pymongo.ASCENDING):
print(doc)
To sort by multiple fields, pass a list of (key, direction) pairs::
for doc in collection.find().sort([
('field1', pymongo.ASCENDING),
('field2', pymongo.DESCENDING)]):
print(doc)
# 先按照field1字段降序排序,在该字段中有相同值时按照另一字段field2升序排序
# 一下三种表达方式等价
.sort({field1: -1, field2: 1})
.sort([['field1', 'desc'], ['field2', 'asc']])
.sort([['field1', 'desc'], 'field2'])
高级检索
- 条件操作符号: > 、 < 、 >= 、<= 、!=
{"age":{$gt:1}} : person集合中年龄大于1的所有数据文档
- $all匹配所有,类似t-sql中的in,但是t-sql中的in是满足括号里面的任何一个都能出数据,而mongodb中的$all则必须满足[]中的所有值。
{age:{$all:[7,9]}}:age数组中只要有7和9就满足条件。如果只有7,没有9则不符合条件。
- $in包含,$nin不包含。跟t-sql中的in,not in一样。
{age:{$in:[10,11]}}:如果age是数组的话,只要数组包含in中条件的任何一条数据,都能被检索出来。不是数组,则只要满足in中的任何一个条件数据,也可以被检索出来。
- $size数组元素个数
{age:{$size:4}}:age数组元素个数为4的数据结果集。
- $exists判断字段是否存在,(true/false)
{city:{$exists:true}}: 集合中存在city这个字段的数据
- $mod取模运算
{age:{$mod:[7,6]}}:集合中模7余6的数据
- $not正则匹配不满足条件
import re
for noMatch in db.inventory.find( { "item": { "$not": re.compile("^p.*") } } ):
print noMatch
db.inventory.find( { price: { $not: { $gt: 1.99 } } } )
This query will select all documents in the inventory collection where:
- the price field value is less than or equal to 1.99
- the price field does not exist
{ $not: { $gt: 1.99 } } is different from the $lte operator. { $lte: 1.99 } returns only the documents where price field exists and its value is less than or equal to 1.99.
- 正则表达式
以下命令使用正则表达式查找包含 runoob 字符串的文章:
>db.posts.find({post_text:{$regex:"runoob"}})
以上查询也可以写为:
>db.posts.find({post_text:/runoob/})
如果检索需要不区分大小写,我们可以设置 $options 为 $i。
以下命令将查找不区分大小写的字符串 runoob:
>db.posts.find({post_text:{$regex:"runoob",$options:"$i"}})
- cursor
事实上在日常的业务中,很少有一次性取10000条数据的,但是有时候
从数据库取出来的数据是跨数据的,比如取第100页的数据。我们查询
的时候不想一次性取出那么多数据,想进行逐条处理,这个时候我们就
需要使用“游标(cursor)”来解决。
var cursor = db.bar.find().skip(8000).limit(10);
while(cursor.hasNext()) {
printjson(cursor.next());
};
- where
db.comsys.insert({"_id":"20180101","day":30,"time":24});
db.comsys.find({$where:function(){if(this.day > 20) return true;}});
db.comsys.find({$where: "this.day > 20"})
$where操作的原理:
当由where操作时,他将逐一遍历mongo集合中文档对象,将其属性由Bson格式转换为Json。然后能通过json找到对象属性,供js来调用。而如果不用where语句进行比较,则是通过文档对象的Bson二进制形式直接进行比较,类似于关系型数据库。
- 缺点:
- 不利用索引
- 他的的比较操作,是必须逐一遍历该集合下所有文档对象,将二进制转换为json对象在磁盘上进行判断操作!!!这将带来多大的性能消耗,效率很低。
- 优点
- 能写出比较复杂的操作语句
- 能使的表达式写的比较容易
- 改良
可用常规查询做前置过滤,配置”$where”查询进行调优,可达到不牺牲性能的要求。
2. 更新数据
update
db.COLLECTION_NAME.update({},{},true|false,true|false);
- 第一个参数是查询选择器,与findOne的参数一样,相当于sql的where子句
- 第二个参数是更新操作文件,由各种更新操作符和更新值构成,
- 第三个参数是upsert。如果是true,表示如果没有符合查询选择器的文档,mongo将会综合第一第二个参数向集合插入一个新的文档。
- 第四个参数是multi。true:更新匹配到的所有文档,false:更新匹配到的第一个文档,默认值
findAndModify
一次最多只更新一个文档,也就是条件query条件,且执行sort后的第一个文档。
db.COLLECTION_NAME.findAndModify({query:{}, update:{}, remove:true|false, new:true|false, sort:{}, fields:{}, upsert:true|false});
- query是查询选择器,与findOne的查询选择器相同
- update是要更新的值,不能与remove同时出现
- remove表示删除符合query条件的文档,不能与update同时出现
- new为true:返回更新后的文档,false:返回更新前的,默认是false
- sort:排序条件,与sort函数的参数一致。
- fields:与find*的第二个参数一致,表明返回哪些字段
- upsert:与update的upsert参数一样。
update和findandmodify用处的区别
with findAndModify you increment the counter and get its incremented value in one step.
Compare if A perform this operation in two steps (update and get value) and B does the same operation between your steps
then A and B may get the same last counter value instead of two different (just one example of possible issues).using update to modify a single document i.e.(“multi”:false} is also atomic. Currently, it should also be faster than doing the equivalent update using findAndModify.
常用操作命令
大于/小于/AND/OR
$gt:大于
$lt:小于
$gte:大于或等于
$lte:小于或等于
$ne:不等于
db.collection.find({ "field" : { $lt: value } } )
注意在python中,查询条件为{“field”: {“$lt”: value}}
$inc (配合更新操作使用)
只能用于整型,长整型,双精度浮点型。
初始状态:
{
_id: 1,
sku: "abc123",
quantity: 10,
metrics: {
orders: 2,
ratings: 3.5
}
}
操作:
db.products.update(
{ sku: "abc123" },
{ $inc: { quantity: -2, "metrics.orders": 1 } }
)
结果:
{
"_id" : 1,
"sku" : "abc123",
"quantity" : 8,
"metrics" : {
"orders" : 3,
"ratings" : 3.5
}
}