# 模块二 基础巩固 MongoDB 聚合

## 2.5.5 MongoDB -- 聚合 <a href="#id-255mongodb-ju-he" id="id-255mongodb-ju-he"></a>

* 排序
* 索引类型
* 创建索引

### 排序 <a href="#pai-xu" id="pai-xu"></a>

```
// 升序
db.getCollection('author').find({}).sort({"age": 1}).limit(20)

// 降序
db.getCollection('author').find({}).sort({"age": -1}).limit(20)

// 组合
db.getCollection('author').find({}).sort({"age": 1, "name": -1}).limit(20)
```

### 索引类型 <a href="#suo-yin-lei-xing" id="suo-yin-lei-xing"></a>

* 单键索引
* 复合索引
* 多键索引
* 地理空间索引
* 文本索引
* 索引属性
* 唯一索引
* TTL索引
* 不区分大小写索引
* 稀疏索引
* 部分索引

<https://docs.mongodb.com/manual/indexes/>

```
// 使用 explan 查看 mongo 查询过程中的执行情况
db.author.find({"name": "user1"}).explain("executionStats")
```

### 创建索引 <a href="#chuang-jian-suo-yin" id="chuang-jian-suo-yin"></a>

```
// 创建索引，-1 代表降序方式创建
db.collection.createIndex( { name: -1 } )

// 复合索引
db.products.createIndex( { "item": 1, "stock": 1 } )

//多键索引
{ _id: 1, item: "ABC", ratings: [ 2, 5, 9 ] }

db.survey.createIndex( { ratings: 1 } )

//地理空间索引
db.places.insert(
   {
      loc : { type: "Point", coordinates: [ -73.97, 40.77 ] },
      name: "Central Park",
      category : "Parks"
   }
)

db.places.createIndex( { loc : "2dsphere" } )

//文本索引，一个集合只能创建一个
db.reviews.createIndex( { comments: "text" } )

db.reviews.createIndex(
   {
     subject: "text",
     comments: "text"
   }
 )
 
// 索引属性（唯一索引）
db.members.createIndex( { "user_id": 1 }, { unique: true } )

// 索引属性（TTL索引），可以设置过期时间
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

// 索引属性（不区分大小写索引）
db.collection.createIndex( { "key" : 1 },
                           { collation: {
                               locale : <locale>,
                               strength : <strength>
                             }
                           } )
                           
// 索引属性（稀疏索引）
db.addresses.createIndex( { "xmpp_id": 1 }, { sparse: true } )

// 索引属性（部分索引）
db.restaurants.createIndex(
   { cuisine: 1, name: 1 },
   { partialFilterExpression: { rating: { $gt: 5 } } }
)
```

覆盖索引：所有查询字段是索引的一部分，所有查询返回字段在同一个索引中

低效操作：

* 取反效率低（比如不等于，因为等于会命中索引，取反不会）
* $nin 总是进行全表扫描
* 一次查询只能使用一个索引，$or 除外，但 $or 使用多个索引查询之后再将结果进行合并的效率并不高，所以不推荐使用（尽可能使用$in）
* 嵌套对象字段索引与基本字段的处理方式一致

使用索引的场景：

* 集合较大
* 文档较大
* 选择性查询

```
// 后台创建索引，如果使用工具线程，可能会阻塞查询
db.people.createIndex({zipcode: 1}, {background: true})
```

索引基数：数据类型多，索引基数高，索引效率高，如果数据比如性别只有男，女两种数据，索引效率低
