MongoDB的查找最重要的函数是find
find()函数第一个参数是查找文档,第二个参数可以限制返回的键
查询条件
'$lt' $lte $gt $gte
使用 分别代表< 、<=、>、>=
$ne
表示不相等
我的docs 是这样组织的
doc ={
'title':title,
'description':desc,
'classname':classname,
'pdflocation':pdf_path,
'sourcelocation':source_path,
'uploadtime':time.strftime('%F %X',time.localtime(time.time())),
'downloadcount':0,
'username':username,
'cover':"",
'recentDownload':[],
}
查找某一个条件可以这样写
#连接数据库操作 语言为python
from pymongo import Connection
#连接到test数据库,MongoDB默认自带的测试数据库
db = Connection("localhost", 27017).test
db.docs.find({'title':'hehe'})
当然我也可以限制只返回pdflocation
db.docs.find({'title':'hehe'},{'pdflocation':1})
或者除了pdflocation都要
db.docs.find({'title':'hehe'},{'pdflocation':0})
上面的操作返回docs数据集中title 为hehe的文档
如果我想找到时间在某一个范围内的doc,我可以这样写
docs = db.docs.find({'uploadtime':{
'$lte':time.strftime('%F %X',time.localtime(time.time())),
'$gt':time.strftime('%F %X',time.localtime(time.time())),
}
})
当然既小于当前时间又大于当前时间的doc肯定不错在了,所以返回None
像上面的查询文档中的关系类似 sql中的where A and B
那么要查找where a or b 该怎么办?
或关系查找
使用 $in
或者 $or
比如我想查找文档中名字是 test1 或 test2的 可以这样
docs = db.docs.find({'title':{
'$in':['test1','test2'],
}
})
对于某个键的或查找,这样效率是很不错的
相对应的还有nin
not in 不在这个里面的 很容易理解
那么要找题目(title)或者描述(description)是test的怎么查找呢?
用$or
需要注意的是$or
后面需要的是一个list ,list每一项就是一个或的一个条件
docs = db.docs.find({
'$or':[{'title':'test'},{'description':'test'}]
})
逻辑操作
有了$or
当然也由其他逻辑操作符号
$not
取反 与正则表达式一起使用将极为高效
$and
很少使用 默认在一个{}中的条件都是and关系
这几个使用基本相同 后面都需要接一个数组
数组的每一项都是字典,里面是进行逻辑组合的条件
模糊搜索
使用要使用像Sql中 where A like "%s% " 可以使用正则表达式来匹配
Mongodb支持于Perl兼容的正则表达式来匹配字符串
在python的pymongo这个库中可以这样写
利用re模块
docs = db.docs.find({'title':re.compile('[\w]+')})
或者利用$regex
docs = db.docs.find({'title':{'$regex':'[\w]+'}})
这样就支持了我在py中用的正则表达式了
键的值非空
传统Sql数据中一般都由Null字段
MongoDB也是有的,在python中对应的是None
查找名字非空的文档
docs = db.docs.find({'title':{'$ne':None}})
查找名字为空的文档
docs = db.docs.find({'title':{'$in':[None]}})
查询数组
MongoDB中某个键的值是list是是经常使用的,比如doc
recentDownload 字段是一个list,每次有人下载该文档,
都将下载者的di放到这个list 中(很不推荐这样做,这只是个例子
比如 coco、joe、tom最近下载了这个文档
那么
docs = db.docs.find({'recentDownload':'coco'})
docs = db.docs.find({'recentDownload':'joe'})
都将返回这个文档
那么如果想找到coco和tom最近都下载了哪个文档
需要用$all
docs = db.docs.find({'recentDownload':{'$all':['coco','tom']}})
并且all后面的数组的顺序不影响结果
当然你也可以精确匹配
docs = db.docs.find('recentDownload':['coco','joe'])
这里的['coco','joe']是一个元素 除非recentDownload完全等于这个list,否则不会匹配
如果知道顺序也可以这样查找
查找recentDownload2的第二个元素是coco
docs = db.docs.find('recentDownload.2':'coco')
使用$size
可以查找到特定长度的数组
文档被下载的次数越来越多,这个list也越来大,如果只想知道最近哪十个人下载了这个文档
可以在更新指定这个list的大小,也可以在查询时用$slice
来限制返回的数量
从前到后的10个
docs = db.docs.find({'recentDownload':{'$slice':10}})
我们想要最近下载的十个人的id 那么
但是在python中报错了
pymongo.errors.OperationFailure: database error: Can't canonicalize query: BadValue unknown operator: $slice
怀疑pymongo不支持
docs = db.docs.find({'recentDownload':{'$slice':-10}})
就可以了
查询数组与范围查询的相互影响
我们现在由这样的文档
{'x': 5 }
{'x': 15 }
{'x': 25 }
{'x': [5,25 }
执行这样的查询
docs = db.testDoc.find({'x':{'$gt':6,'$lt':24}})
发现输出
{u'x': 15, u'_id': ObjectId('54815f29348e3b14df008c41')}
{u'x': [5, 25], u'_id': ObjectId('54815f29348e3b14df008c43')}
不应该啊! 5 和25 都不在这个范围啊!
原因在于:
5满足小于24 6满足大于5的条件,故这个文档被返回了
这时候需要使用$elemMatch
操作符
这时候返回空
..因为$elemMatch只搜索数组
解决这个问题的方法需要使用“索引”
查询内联文档
一个键的值出了可以是一个list之外,当然可以是一个文档(dict)了
比如文档作者可以由名字和性别组成
{'author':{
'name':'coco',
'sex':'f'
}}
那么可以这样搜索
查询author的名字为coco的文档
docs = db.testDoc.find({'author.name':'coco'})
但是如果这个coco有男有女怎么办呢?
和list时一样一个dict要满足所有条件需要使用$elemMatch
注 这里发生了些许问题,问题的原因不明,正在寻找问题的原因
docs = db.testDoc.find({'author':{'$elemMatch':{'name':'coco','sex':'f'}}})
如果使用javascript 还可以在$where
语句之后添加函数 ,相当牛X