mongodb 查询
1.关于mongodb的思考
mongodb最大的特点就是能直接储存json字符串,而不用转化为关系型数据库的一个个字段,好处就是拓展字段很容易,坏处就是不能像关系型数据库一样不同表之间通过left join 等操作进行关联查询.
之前也思考过如果数据库存的是json对象,那么怎么根据条件查询想要的json呢?其实mongodb就可以解决,简单的find语法就可以筛选出符合条件的json对象,find({})一个空对象可以查询出所有对象,还是挺方便的,如果用关系型数据库来实现的话就需要把字段都转化成java对象进行过滤,但是mongodb可以直接在数据库层面完成这个操作,还是非常方便.虽然有思考过业务场景,但是没有工作中用不到,还是多少接触下mongodb,以后碰到了在深入学习.敬畏技术!
2. 根据条件查询数据
db.users.find({"birthday":"11"})可以查询出生日为11的用户
还是非常方便,不用转化成java对象,而且也比关系型数据库方便了许多.技术没有好坏,只是场景不同.
多条件下,可以传入多个字段
db.users.find({"birthday":"11","age": 11}) 同时查找年龄为11的用户;
3. 指定返回的键
用关系型数据库来说就是字段,可以指定返回的字段
db.users.find({"birthday":"11","age": 11},{"birthday":1}) 这里我只展示birthday字段,如果设置为0则不展示birthday字段.
db.users.find({"birthday":"11","age": 11},{"birthday":1,"_id":0}) 如果加上 _id为0,则可以把默认的_id字段去除掉.
4.限制
查询有一个限制就是字段不能作为查询条件的值,比如:
db.users.find({"birthday":"this.age"})
我想把年龄的值作为参数传递给birthday查询条件,这样是无法实现的,会解析为 this.age字符串,查询参数必须是一个常量.
5.查询条件
5.1 查询条件
查询条件有 "$lt" "$lte" "$gt" "$gte" "$ne" 分别为 < ,<= ,> ,>= ,!=;
db.users.find({"age": {"$gt": 15, "$lt": 20}}) 这个代码的意思查询年龄大于15,小于20的用户,需要注意的是查询条件需要和字段类型一直,否则不会执行成功.
5.2 $or
类似于sql语法中的 or 语句,只要一个条件符合就查询
db.users.find({"$or":[{"age":22}, {"name":"Bob"}]}) 查询姓名是Bob或者年龄是22的用户
5.3 $not
$not是元条件运算符,需要一个文档参数,意思是查询不符合not参数的文档
db.users.find({"age":{"$not":{"$mod": [5.1]}}}) 意思是查询年龄不是除以5后余数为1的用户.
5.4 null
null可以单独作为查询条件
db.users.find({"age":null}) 这个语句会查询年龄为null的用户和没有age字段的用户,如果想查询只包含age字段的用户,可以加上$exists
db.users.find({"age":{"$eq":null, "$exists": true}})
5.5 正则表达式 $regex
不重复赘述了,基本上所有语言都支持正则表达式
db.users.find({"name":{"$regex": /joy/i}}) 可以查询到name为joy的用户,不区分大小写.
5.6 数组查询
5.6.1 $all
$all可以查询数组,比如有如下数组: db.food.insertOne({"fruit":["apple","banana","peach"]})
我们可以用$all查询想要的数据
db.food.find({"fruit":{"$all": ["apple"]}}) 我们可以查询到fruit数组中包含apple的数据.
也可以指定下标查找
db.food.find({"fruit.2":"peach"}) 可以查找fruit下标为2是peach的水果.
5.6.2 $size
根据数组的大小查找,不能和$lt $gt 同时使用
db.food.find({"fruit": {"$size": 3}}) 可以查找数组为3的数据.
如果想用大于小于进行比较的话,可以单独增加一个size字段进行比较.
5.6.3 $slice
执行返回数组的长度, find方法第一个参数是条件,第二个是返回格式,我们可以用$slice指定返回数组的大小.
db.food.find({"fruit":{"$all":["apple"]}}, {"fruit":{"$slice": 2}) 返回包含apple数组的文档,同时只返回前两个数据.
如果是负数的话则返回后两个.
$slice会返回所有键,只是限制了数组的长度.
5.6.4 $运算符返回匹配的元素
db.foot.find({"comments.name":"bob", {"comments.$" : 1}}) 会返回文档中第一个匹配的元素.
5.6.5 利用$elemMatch 限制过滤条件只过滤数组
如果单纯的进行 $lt $gt 比较数组和数字会造成数组不准确,我们加上$elemMatch来限制只判断数组
db.test.find({"x":{"$elemMatch":{"$lt" 20, "$gt": 5}}})会查找x数组小于20大于5的数组.
5.6.6查询内嵌文档
如果要查找内嵌文档,可以用 . 点表示法来查找.
db.people.find({"name.first":"Joe"}) 用来查找姓为Joe的人员.如果直接db.people.find({"name":{"first":"Joe"}})则不行,这种方式是精确匹配,少个字段都无法查找.
如果想查询数组中的元素,就是5.6.5中提到的,用$elemMatch限制只查找数组.
5.7 $where查询
$where可以执行js脚本,比如:
db.test.find({"$where": function () { // 自定义条件 return true;} })
只有当方法里面的条件为true的时候,才返回数据.
但是$where查询执行比较慢,不建议使用.
5.8 游标
类似于java的遍历器iterator,通过find获取一个游标,可以进行遍历
var cursor = db.collections.find();
while(cursor.hasNext()){
var obj = cursor.next();
print(obj);
}
没什么好说的,基本操作.
注意: 游标遍历完会自动销毁,释放内存,如果没有遍历完,10分钟后mongodb也会销毁.
5.9 limit,skip,sort
limit限制查询数量
db.collections.find().limit(3) 只会查找三条数据.
skip 根据参数忽略查询结果
db.collections.find().limit(3) 会忽略前三条数据
sort排序
db.collections.find().sort({x:1}) 按照x字段正序或者倒序排列.
类似于其他语言的流式操作,可以结合使用
db.collections.find().limit(3) .sort({x:1})过滤前三个在排序.
注意: 分页等操作尽量不使用skip和limit操作,这样做效率比较低,可以使用 $lt先过滤一部分,在用limit筛选.