基本
库的基本操作
-
创建库
# 创建并且切换到demo use demo; # 展示当前所在库位置 db; # 查看所有数据库 show dbs;
注意: 我们使用use 创建demo库时,再用 show dbs时,发现没有刚刚创建的demo库,这是因为刚创建的库只有在插入数据后才能显示出来。
-
删除数据库
# 切换到demo库 use demo; # 删除当前的所在库 db.dropDatabase();
增删改查
-
条件查询find
# 为了方便查询先插入一定数量的数据 for(var i=0; i<100; i++) db.book.insert({"num": i, "name": "ss"+i}) # 查询 num为 99 的那条数据 db.book.find({num: 99}); # 查询 num 为99 并且只返回name字段(_id 是总是会返回的,所以这里会返回_id和num两个字段的) db.book.find({num: 99}, {"name": true});
-
条件查询 findOne
有时候我们为了查询数据是否存在,没必要查询出所有的数据,此时我们可以使用findOne 可以节省游标不必要的开销。
# 查询 num 是否存在小于3的集合、 db.book.findOne({"num": {$lt: 3}});
-
分页 limit
其实mongo里的分页可以借助 limit 来实现的。可以先以某个属性字段进程排序,然后用limit来进行限制条数,达到分页的目的
# 倒序获取50 - 40 的数据 db.book.find({num: {$lt: 0}}).sort({num: -1}).limit(10);
-
修改 update
# num 为99 ,修改 name 为 hhh99 db.book.update({"num": 99}, {$set: {"name": "hhh99"}}); # 批量修改多个(一般的首先想到的是下面这样写, 其实是错误的),只会修改第一条数据 db.book.update({"num": {$lt: 10}}, {$set: {"name": "hhh"}}); # 上面的写法是错误的,那么正确的写法是 db.book.update({"num": {$lt: 10}}, {$set: {"name": "hhh"}}, {"multi": true}); # output > db.book.update({"num": {$lt: 10}}, {$set: {"name": "hhh"}}); WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 }) > db.book.update({"num": {$lt: 10}}, {$set: {"name": "hhh"}}, {"multi": true}); WriteResult({ "nMatched" : 10, "nUpserted" : 0, "nModified" : 9 })
注意: 批量修改的话,一定不要忘记
{"multi": true}
-
删除 remove
# 删除 num 大于等于 95 的集合 db.book.remove({"num": {$gte: 95}});
高级查询
-
$gt(大于), $lt(小于), $gte(大于等于), $lte(小于等于), $ne(不等于)
# 查询num 大于等于 45 小于65 的所有,并且显示name字段 db.book.find({"num": {$gte: 45, $lt: 65}}, {"name": true});
-
$all
匹配所有
这个属性跟sql里的in有点类似,但是又不完全一样使用# 先在上面的集合中添加几个数据字段数据 db.book.update({num: 0}, {$set: {"age": [5, 6, 7]}}); db.book.update({num: 1}, {$set: {"age": [6, 7, 8]}}); db.book.update({num: 2}, {$set: {"age": [7, 8, 9]}}); db.book.update({num: 3}, {$set: {"age": [8, 9, 10]}}); db.book.update({num: 4}, {$set: {"age": [9, 10, 11]}}); db.book.update({num: 5}, {$set: {"age": [10, 11, 12]}}); # 查询 age 有7和8 的集合 db.book.find({age: {$all: [7, 8]}}); # ouput > db.book.find({age: {$all: [7, 8]}}); { "_id" : ObjectId("5a0fd6ffab65c141825ab036"), "num" : 1, "name" : "hhh", "age" : [ 6, 7, 8 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab037"), "num" : 2, "name" : "hhh", "age" : [ 7, 8, 9 ] }
从上面我们可以看出,这里输出的只是7和8都同时存在的,而不是7或者8存在的集合。in 的用法则是或者的关系。
-
$exist
判断字段是否存在在关系型数据库里也有这样关键字,但是mongo里的exist却意义完全不一样,这里只是判断文档里的某个字段是否存在。
# 查询存在age字段的集合 db.book.find({"age": {$exists: true}}); # output > db.book.find({"age": {$exists: true}}); { "_id" : ObjectId("5a0fd6ffab65c141825ab035"), "num" : 0, "name" : "hhh", "age" : [ 5, 6, 7 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab036"), "num" : 1, "name" : "hhh", "age" : [ 6, 7, 8 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab037"), "num" : 2, "name" : "hhh", "age" : [ 7, 8, 9 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab038"), "num" : 3, "name" : "hhh", "age" : [ 8, 9, 10 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab039"), "num" : 4, "name" : "hhh", "age" : [ 9, 10, 11 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab03a"), "num" : 5, "name" : "hhh", "age" : [ 10, 11, 12 ] }
-
如何查询值为null?
# 添加一个值为 null 的字段 db.book.update({"num": 0}, {$set: {"size": null}}); # 查询 size 为 null 的数据 db.book.find({"size": null}); #ouput > db.book.find({"size": null}); { "_id" : ObjectId("5a0fd6ffab65c141825ab035"), "num" : 0, "name" : "hhh", "age" : [ 5, 6, 7 ], "size" : null } { "_id" : ObjectId("5a0fd6ffab65c141825ab036"), "num" : 1, "name" : "hhh", "age" : [ 6, 7, 8 ] } { "_id" : ObjectId("5a0fd6ffab65c141825ab037"), "num" : 2, "name" : "hhh", "age" : [ 7, 8, 9 ] } ... 可以看出不仅查询出 size 为 null, 还查出来size 不存在的值。所以,null 不仅能查询他自身,还能查询不存在的字段。 # 所以上面还需要再加上一个条件 size 属性存在 db.book.find({"size": null, "size": {$exists: true}}); 或者 db.book.find({"size": {$in: [null], $exists: true}});
-
$in
和$nin
的用法上面提过
$all
的用法,必须要求所给出的值一定要存在。这里的$in
跟之前学过关系型数据库的in是很相似的。# 查询num为 7, 9, 10这三项的数据 db.book.find({num: {$in: [7, 8, 9]}}); # output > db.book.find({num: {$in: [7, 8, 9]}}); { "_id" : ObjectId("5a0fd6ffab65c141825ab03c"), "num" : 7, "name" : "hhh" } { "_id" : ObjectId("5a0fd6ffab65c141825ab03d"), "num" : 8, "name" : "hhh" } { "_id" : ObjectId("5a0fd6ffab65c141825ab03e"), "num" : 9, "name" : "hhh" }
$nin
的用法则刚好和$in
的相反。 -
正则表达式
关系型数据库里有like做到模糊查询,这里mongo可以用正则表达式进行更加强大的模糊查询。
# 查询 name 为 hhh开头的 db.book.find({name: /^hhh.*/}); # 查询 name 非 hhh开头的 db.book.find({name: {$not: /^hh.*/}});
-
$not
和$ne
区别$not
一般会与 正则表达式配合使用。$ne
一般用于一个确切的值进行相反查询。 -
count
根据条件统计数量。
db.book.count({num: {$gte: 90}});
-
skip 重置记录起点
也就是跳过前面第几条数据然后向后查询。
# 以10 为页数 进行分页查询 db.book.find().skip(0).limit(10); db.book.find().skip(10).limit(10); db.book.find().skip(20).limit(10); ...
-
sort 排序
# 升序 db.find.find().sort({num: 1}); # 降序 db.find.find().sort({num: -1});
索引
-
概述
在关系型数据库里,也有索引这样的概念,这里意思是一样的,都是为了提高查询效率,为一些字段添加索引。
-
_id 默认主键索引
当一个文档创建时,默认的主键 _id 就自带了一个索引。
Note
In sharded clusters, if you do not use the _id field as the shard key, then your application must ensure the uniqueness of the values in the _id field to prevent errors. This is most-often done by using a standard auto-generated ObjectId.
上面引用官网的_id 补充说明, _id 可以删除的,但是在分布式的mongo中,默认生成的_id 是可以快速定位到一个节点上查找数据的,也就是最好不要改写_id 的生成规则,而是采用默认的标准即可。
-
创建index
关于createIndex 的接口,可以参考:https://docs.mongodb.com/manual/reference/method/db.collection.dropIndex/
# 为 book 创建 num字段的索引 db.book.createIndex({num: 1}, {name: "num_index"});
补充: 上面我们的创建索引时,字段后面的值是一个数字1 ,这里的含义是我们根据该字段的值创建一个升序的索引;如果为-1的话,这里就创建的是降序的索引。 我们还可以创建 "position.age" 这样的多层级的索引。
-
查看索引
db.book.getIndexes(); # output > db.book.getIndexes(); [ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "demo.book" }, { "v" : 2, "key" : { "num" : 1 }, "name" : "num_index", "ns" : "demo.book" } ]
-
删除index
db.book.dropIndex("num_index");