MongoDB使用笔记

MongoDB使用笔记

Scroll Down

下载安装MongoDB

将MongoDB服务器作为Windows服务运行

mongod --dbpath "D:\Program Files\mongodb\data\db" --logpath "D:\Program Files\mongodb\log\mongodb.log" --serviceName "mongodb" --serviceDisplayName "mongodb" --install

得到如下输出

2018-03-10T23:32:46.339+0800 I CONTROL  log file "D:\data\log\mongodb.log" exists; moved to "D:\data\log\mongodb.log.2018-03-10T15-32-46".

说明Mongodb服务安装成功。启动mongodb服务:

D:\mongodb\bin>net start mongodb
 
MongoDB 服务已经启动成功。

打开浏览器,范围地址http://127.0.0.1:27017/, 端口没改默认为27017,可看到如下信息

It looks like you are trying to access MongoDB over HTTP on the native driver port.

MongoDB聚合查询

聚合查询摘要,聚合框架是MongoDB的高级查询语言,允许我们通过转化合并由多个文档的数据来生成新的在单个文档里不存在的文档信息。通俗一点来说,可以把MongoDB的聚合查询等价于SQL的GROUP BY语句。

每个聚合操作完后,将输出数据作为下一个聚合操作的输入数据。

1.$project

  • 修改输入文档的结构
  • 重命名、增加或删除域
  • 创建计算结果以及嵌套文档

例:获取test集合的weight字段及name字段(_id不显示)

db.test.aggregate(
    { $project : {
        _id:    0 ,
        weight: 1 ,
        name : 1 
    }}
 );

2.$match

  • 用于过滤数据,只输出符合条件的文档,传递到下一个管道阶段。
  • 在$match中不能使用$geoNear地理空间操作符及$where表达式操作符

例:获取test集合的weight>=0.5且weight<=1

db.test.aggregate( {
    $match : 
        { weight : 
            { $gte : 0.5, $lte : 1 } 
        }
});

3.$group

  • 将集合中的文档分组,可用于统计结果
  • 在$match中不能使用$geoNear地理空间操作符及$where表达式操作符

例:获取test集合的weight>=0.5且weight<=1,然后将符合条件的记录送到下一阶段$group管道操作符进行处理

db.test.aggregate([
    {$match : 
        { weight : 
            { $gte : 0.5, $lte : 1 } 
        }
    },
    { $group: 
        { _id: null, 
          count: { $sum: 1 } 
        } 
    }
]);

4.$limit

  • $limit会接受一个数字n,返回结果集中的前n个文档
  • 限制传递到管道中下一阶段的文档数
  • 此操作仅返回管道传递给它的前5个文档, $limit对其传递的文档内容没有影响。
db.test.aggregate({ $limit : 5 });

5.$skip

  • $skip接受一个数字n,丢弃结果集中的前n个文档
  • 跳过进入stage的指定数量n的文档,并将其余文档传递到管道中的下一个阶段

例:获取test集合中第5条数据之后的数据

db.test.aggregate({ $skip: 5 });

6.$count

  • 返回包含输入到stage的文档的计数,理解为返回与表或视图的find()查询匹配的文档的计数。
    例:获取当前查询完得到的数量
{ $count: <string> }

7.$sort

  • 对所有输入文档进行排序,并按排序顺序将它们返回到管道。
    例:要对字段进行排序,将排序顺序设置为1或-1,以分别指定升序或降序排序
db.users.aggregate(
   [
     { $sort : { shippingDate : -1} }
   ]
)

逻辑操作符

$gt    大于

$gte    大于等于

$lt     小于

$lte     小于等于

$ne        不等于

$and      要求满足所有查询条件 ,否则返回空

$or    或关系

$nor    或关系取反

$exists    通常是用于判断是否有这个键,而不是SQL中的某个列上存在某个值

$type      针对字段类型进行查询

$in        在多个值范围内

$nin       不在多个值范围内

$all       匹配数组中多个值

$regex   正则,用于模糊查询

$size   匹配数组大小

$maxDistance  范围查询,距离(基于LBS)

$mod     取模运算

$near   邻域查询,查询附近的位置(基于LBS)

$elemMatch  匹配内数组内的元素

$within  范围查询(基于LBS)

$box    范围查询,矩形范围(基于LBS)

$center       范围醒询,圆形范围(基于LBS)

$centerSphere  范围查询,球形范围(基于LBS)

$slice    查询字段集合中的元素(比如从第几个之后,第N到第M个元素)

Explain 分析查询性能

COLLSCAN:全表扫描

IXSCAN:索引扫描

FETCH:根据索引去检索指定document

SHARD_MERGE:将各个分片返回数据进行merge

SORT:表明在内存中进行了排序

LIMIT:使用limit限制返回数

SKIP:使用skip进行跳过

IDHACK:针对_id进行查询

优化方法

  • $match条件需要增加索引,如果是多个,最好用组合索引;
  • $sort的字段也需要增加索引;
  • $group的_id也需要增加索引;
  • limit可以大幅度降低时耗。

MongoDB 索引限制

额外开销

每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引。

内存(RAM)使用

由于索引是存储在内存(RAM)中,你应该确保该索引的大小不超过内存的限制。

如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。

查询限制

索引不能被以下的查询使用:

正则表达式及非操作符,如 $nin, $not, 等。
算术运算符,如 $mod, 等。
$where 子句
所以,检测你的语句是否使用索引是一个好的习惯,可以用explain来查看。

索引键限制

从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。

插入文档超过索引键限制
如果文档的索引字段值超过了索引键的限制,MongoDB不会将任何文档转换成索引的集合。与mongorestore和mongoimport工具类似。

最大范围

  • 集合中索引不能超过64个
  • 索引名的长度不能超过128个字符
  • 一个复合索引最多可以有31个字段

慢查询优化:

  • 查看某聚合查询的执行计划:
db.ODS_fi_task.explain("executionStats").aggregate([
            {
                "$match": {
                    "reply4Shipment": {
                        "$exists": true
                    }
                }
            },
            {
                "$sort": {
                    "etlLatestTime": -1
                }
            },
            {
                "$limit": 20
            }
        ])

如下所示,可以看出,排序sort耗时很长,executionTimeMillis有5s不止,stage为COLLSCAN模式,效率低下;

	"executionStats" : {
					"executionSuccess" : true,
					"nReturned" : 2258,
					"executionTimeMillis" : 5257,
					"totalKeysExamined" : 0,
					"totalDocsExamined" : 4758,
					"executionStages" : {
						"stage" : "COLLSCAN",
						"filter" : {
							"reply4Shipment" : {
								"$exists" : true
							}
						},
						"nReturned" : 2258,
						"executionTimeMillisEstimate" : 41,
						"works" : 4760,
						"advanced" : 2258,
						"needTime" : 2501,
						"needYield" : 0,
						"saveState" : 886,
						"restoreState" : 886,
						"isEOF" : 1,
						"direction" : "forward",
						"docsExamined" : 4758
					}
				}
			}
		},

添加etlLatestTime为索引

db.ODS_fi_task.createIndex({"etlLatestTime":-1})

速度提示显著:

"executionStats" : {
					"executionSuccess" : true,
					"nReturned" : 20,
					"executionTimeMillis" : 70,
					"totalKeysExamined" : 30,
					"totalDocsExamined" : 30,
					"executionStages" : {
						"stage" : "FETCH",
						"filter" : {
							"reply4Shipment" : {
								"$exists" : true
							}
						},
						"nReturned" : 20,
						"executionTimeMillisEstimate" : 0,
						"works" : 30,
						"advanced" : 20,
						"needTime" : 10,
						"needYield" : 0,
						"saveState" : 8,
						"restoreState" : 8,
						"isEOF" : 0,
						"docsExamined" : 30,
						"alreadyHasObj" : 0,
						"inputStage" : {
							"stage" : "IXSCAN",
							"nReturned" : 30,
							"executionTimeMillisEstimate" : 0,
							"works" : 30,
							"advanced" : 30,
							"needTime" : 0,
							"needYield" : 0,
							"saveState" : 8,
							"restoreState" : 8,
							"isEOF" : 0,
							"keyPattern" : {
								"etlLatestTime" : -1
							},
							"indexName" : "etlLatestTime_-1",
							"isMultiKey" : false,
							"multiKeyPaths" : {
								"etlLatestTime" : [ ]
							}