目录
一、数据库二、文档
三、索引
四、聚合
一、数据库
show dbs -- 查看所有数据库
use DATABASE_NAME -- 如果数据库不存在,则创建数据库,否则切换到指定数据库。
db.dropDatabase() -- 删除当前数据库
db.COLLECTION_NAME.drop() -- 删除集合
二、文档
1. 插入文档
db.col.insert({
title: 'MongoDB Course',
tags: ['database', 'NoSQL']
})
document = ({ -- 将数据定义为一个变量
title: 'MongoDB Course',
tags: ['database', 'NoSQL']
});
db.col.save(document)
2. 更新文档
-- update
db.collection.update(
<query>, -- 查询条件,类似sql的where语法
<update>, -- 更新的对象,类似sql的set语法
{
upsert: <boolean>, -- 可选,默认是false,表示update的记录不存在时不插入数据,true则为插入,
multi: <boolean>, -- 可选,默认是false,只更新找到的第一条记录,true则更新查出来的多条记录。
writeConcern: <document> -- 可选,抛出异常的级别
}
)
db.col.update(
{title: 'MongoDB Course'},
{$set:{title: 'MongoDB'}}
)
db.col.find().pretty()
-- save 通过传入的文档来替换已有文档
db.col.save({
title: 'MongoDB',
tags: ['database', 'NoSQL']
})
-- update更多例子
db.col.update( { "id" : { $gt : 3 } } , { $set : { "desc" : "OK"} } ); -- 只更新第一条记录
db.col.update( { "id" : { $gt : 3 } } , { $set : { "desc" : "OK"} },false,false ); --只更新第一条记录
db.col.update( { "id" : { $gt : 3 } } , { $set : { "desc" : "OK"} },true, false ); -- 只添加第一条
db.col.update( { "id" : { $gt : 3 } } , { $set : { "desc" : "OK"} },true, true ); --全部添加加进去
db.col.update( { "id" : { $gt : 3 } } , { $set : { "desc" : "OK"} },false,true ); --全部更新
3. 删除文档
db.collection.remove(
<query>, -- (可选)删除的文档的条件
{
justOne: <boolean>, -- (可选)如果设为 true 或 1,则只删除一个文档。
writeConcern: <document> -- (可选)抛出异常的级别。
}
)
db.col.remove({'title':'MongoDB Course '})
4. 查询文档
db.collection.find(query, projection) -- query:(可选)指定查询条件, projection:(可选)指定返回的键
db.col.find().pretty() -- 以格式化的方式来显示所有文档
(1) MongoDB 与 RDBMS Where 语句比较
(2) AND和OR 条件
db.col.find({"by":"tom", "title":"MongoDB"}) -- and
db.col.find({$or:[{"by":"tom"},{"title": "MongoDB"}]}) -- or
db.col.find({"likes":{$gt:50}, $or:[{"by":"tom"},{"title":"MongoDB"}]}) --'where likes>50 AND (by ='tom' OR title='MongoDB')'
(3) 条件操作符
-- $gt > $gte >= $lt < $lte <= $eq = $ne !=
db.col.find({likes : {$lte : 150}}) -- where likes <= 150
db.col.find({likes : {$lt :200, $gt : 100}}) -- where likes>100 AND likes<200
(4) $type操作符
MongoDB 中的类型如下:
db.col.find({"title" : {$type : 2}}) -- 获取 "col" 集合中 title 为 String 的数据
Limit与Skip方法
limit() -- 读取指定数量的数据, skip() -- 跳过指定数量的数据
db.col.find({},{"title":1,_id:0}).limit(2) -- 查询文档中的两条记录
db.col.find({},{"title":1,_id:0}).skip(10).limit(100) -- 读取从第10条记录后的100条记录
(6) Sort排序方法
指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而-1是用于降序排列
db.col.find({},{"title":1}).sort({"likes":-1})
db.col.find({"title":"MongoDB"},{"title":1}).sort({"title":1}).skip(2).limit(10)
三、索引
索引是对数据库表中一列或多列的值进行排序的一种结构,索引通常能够极大的提高查询的效率。对于每个插入的数据,都会自动生成一条唯一的 _id 字段,_id 索引是绝大多数集合默认建立的索引。
db.col.getIndexes() -- 察看索引
db.col.ensureIndex({"title":-1}) -- 按title降序创建索引
db.col.ensureIndex({"title": 1, by: 1}, {background: true}) -- 让创建工作在后台执行
db.col.dropIndexes() -- 删除所有索引
db.col.dropIndex("normal_index") -- 删除指定索引
1. 创建索引
ensureIndex() 接收可选参数,可选参数列表如下:
2. 查询分析
MongoDB 查询分析可以确保我们建议的索引是否有效,是查询语句性能分析的重要工具。查询分析常用函数有:explain() 和 hint()。
-- 1. 使用 explain()
db.users.ensureIndex({gender:1,user_name:1})
db.users.find({gender:"M"},{user_name:1,_id:0}).explain()
{
-- MongoDB中索引存储在B树结构中,所以该查询使用了BtreeCursor类型的游标。没有使用索引的游标类型是BasicCursor。
-- 可以通过该索引名称查看当前数据库下的system.indexes集合(系统自动创建),获取索引的详细信息。
"cursor" : "BtreeCursor gender_1_user_name_1",
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 0,
"nscanned" : 1, -- nscanned/nscannedObjects表明此查询一共扫描了集合中多少个文档,这个数值和返回文档的数量越接近越好。
"nscannedObjectsAllPlans" : 0,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : true, -- 字段为 true ,表示我们使用了索引。
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0, -- 当前查询所需时间,毫秒数。
"indexBounds" : {...} -- 当前查询具体使用的索引。
}
-- 2. 使用 hint() 虽然MongoDB查询优化器一般工作的很不错,但是也可以使用 hint 来强制 MongoDB 使用一个指定的索引。
db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain() -- 指定了使用gender和user_name索引字段来查询
3. 覆盖索引查询
当查询中的所有字段是索引的一部分, MongoDB 只需从RAM中的索引获取数据,比扫描整个文档读取数据要快得多。
- 所有的查询字段是索引的一部分
- 所有的查询返回字段在同一个索引中
-- user集合
{ "_id" : 1, "username" : "Amy", "gender" : "F", "score" : 100, "age" : 34 }
{ "_id" : 2, "username" : "Ram", "gender" : "M", "score" : 90, "age" : 24 }
db.user.ensureIndex({gender:1,username:1})
db.user.find({gender:"M"},{username:1,_id:0}) -- 该查询会被索引覆盖,MongoDB不用去数据库文件中查找
db.user.find({gender:"M"},{username:1}) -- 该查询不会被覆盖,由于我们的索引中不包括 _id字段,而此查询没有排除该字段
4. 高级索引
当所有索引字段是一个数组或是一个子文档,不能使用覆盖索引查询
-- users集合
{
"name": "Tom Benzamin"
"address": {"city": "Los Angeles", "state": "California", "pincode": "123"}, -- 子文档
"tags": ["music", "cricket", "blogs"] -- 数组
}
-- 索引数组字段: 在数组中创建索引,需要对数组中的每个字段依次建立索引。因此对数组tags建立索引,会为 music、cricket、blogs三个值建立单独的索引
db.users.ensureIndex({"tags":1})
db.users.find({tags:"cricket"}).explain() -- 执行结果中会显示 "cursor" : "BtreeCursor tags_1" ,表示已经使用了索引
-- 索引子文档字段: 为子文档的三个字段创建索引
db.users.ensureIndex({"address.city":1,"address.state":1,"address.pincode":1})
db.users.find({"address.city":"Los Angeles"})
db.users.find({"address.city":"Los Angeles","address.state":"California","address.pincode":"123"})--查询表达式必须遵循指定的索引的顺序
5. 索引限制
(1) 额外开销: 每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。如果你很少对集合进行读取操作,建议不使用索引。
(2) 内存(RAM)限制: 要确保该索引的大小不超过内存(RAM)的限制。如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
(3) 查询限制: 索引不能被以下的查询使用 a. 正则表达式及非操作符,如$nin, $not等 b. 算术运算符,如$mod等 c. $where 子句
(4) 索引键限制:从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。
(5) 最大范围: a. 集合中索引不能超过64个 b.索引名的长度不能超过128个字符 c.一个复合索引最多可以有31个字段
四、聚合
1. count() 和 distinct()
count --统计文档数量
db.collection.count(<query>) 或者 db.collection.find(<query>).count()
db.user.count({"username":"amy"});
distinct --对集合中的文档进行去重处理
db.collection.distinct(field,query)
db.user.distinct("username",{“age":{$gt:28}}); -- 用于查询年龄age大于28岁的不同用户名
2. aggregate()
1. 聚合的表达式:
-- 对每个分组进行计数: select sex, count(*) personCount from col group by sex
db.col.aggregate([{$group: {_id: '$sex', personCount: {$sum:1} }}])
-- 对每个分组求某一列的总和sum/平均值avg/最大值max/最小值min/第一个值first/最后一个值/last
-- select sex, sum(score) totalScore from col group by sex
db.col.aggregate([{$group: {_id: '$sex', totalScore: {$sum:'$score'} }}])
-- 把每个分组的结果集插入到一个数组中$push/$addToSet(去掉重复的)
db.mycol.aggregate([{$group: {_id: 'sex', scores: {$push:′score'} }}])
2. 管道操作符
MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。
- $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- $group:将集合中的文档分组,可用于统计结果。
- $sort:将输入文档排序后输出。
- $limit:用来限制MongoDB聚合管道返回的文档数。
- $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
- $geoNear:输出接近某一地理位置的有序文档。
db.user.aggregate(
[
{$project: {username: 1, score: 1}}, -- 指定输入字段,_id默认是包含的,可添加_id:0去掉
{$match: {score: {$gt: 70, $lte: 90}}},
{$group: {_id: username, count: {$sum: 1}}},
{$skip : 5}
{$sort : {"username": 1}}
])