MongoDB索引

提高查询效率,如果没有索引查询将是全集合扫描。

1、给单字段添加索引

> db.files.getIndexes()    # 查看集合索引,默认有一个索引_id
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
> 
> 
> db.files.createIndex({id:-1})  # 添加索引
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 1,
        "numIndexesAfter" : 2,
        "ok" : 1
}
> db.files.getIndexes()     # 查看集合索引
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "id" : -1
                },
                "name" : "id_-1"
        }
]
> 

2、添加复合索引

> db.files.createIndex({id:-1,typeName:1})  # 添加复合索引(按照id升序,typeName降序排序)
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 2,
        "numIndexesAfter" : 3,
        "ok" : 1
}
> db.files.getIndexes()     # 查看集合索引
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "id" : -1
                },
                "name" : "id_-1"
        },
        {
                "v" : 2,
                "key" : {
                        "id" : -1,
                        "typeName" : 1
                },
                "name" : "id_-1_typeName_1"
        }
]
​

3、删除索引

> db.files.dropIndex({id:-1})   # 删除指定索引
{ "nIndexesWas" : 3, "ok" : 1 }
> db.files.getIndexes()
[
        {
                "v" : 2,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_"
        },
        {
                "v" : 2,
                "key" : {
                        "id" : -1,
                        "typeName" : 1
                },
                "name" : "id_-1_typeName_1"
        }
]
> db.files.dropIndex("id_-1_typeName_1")    # 根据名称删除指定索引
{ "nIndexesWas" : 2, "ok" : 1 }
> 
> db.files.getIndexes()
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
> 
> db.files.dropIndexes()        # 删除所有除‘_id’之外的索引
{
        "nIndexesWas" : 1,
        "msg" : "non-_id indexes dropped for collection",
        "ok" : 1
}
> db.files.getIndexes()     # 查询发现‘_id’索引依然存在
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" } ]
> 

4、索引的使用

4-1、执行计划

db.collection.find(query,options).explain(options)

> db.files.find().explain()     # 全聚合扫描
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "articledb.files",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        
                },
                "queryHash" : "8B3D4AB8",
                "planCacheKey" : "8B3D4AB8",
                "winningPlan" : {
                        "stage" : "COLLSCAN",   # 全聚合扫描
                        "direction" : "forward"
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "localhost",
                "port" : 27017,
                "version" : "4.4.14",
                "gitVersion" : "0b0843af97c3ec9d2c0995152d96d2aad725aab7"
        },
        "ok" : 1
}
> db.files.find({id:2}).explain()   # 根据id查询数据
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "articledb.files",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "id" : {
                                "$eq" : 2
                        }
                },
                "queryHash" : "6DAB46EC",
                "planCacheKey" : "801B9D84",
                "winningPlan" : {
                        "stage" : "FETCH",      # fetch抓取,说明走了id索引
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "id" : -1
                                },
                                "indexName" : "id_-1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "id" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "id" : [
                                                "[2.0, 2.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "serverInfo" : {
                "host" : "localhost",
                "port" : 27017,
                "version" : "4.4.14",
                "gitVersion" : "0b0843af97c3ec9d2c0995152d96d2aad725aab7"
        },
        "ok" : 1
}
> 

SpringBoot操作MongoDB

1、配置依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
    </dependencies>

2、application.yml配置文件

spring:
  data:
    mongodb:
      database: articledb
      host: 192.168.2.120
      password:
      port: 27017
      # 也可以直接使用uri连接(连接副本集也可以使用uri)
      # uri: mongodb://192.168.2.120:27017/articledb
server:
  port: 8090

3、编写实体类、repository、service、controller

// 1、bean
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
​
//{ "_id":ObjectId("62b4360a70d355701ebb38d9"), "id":3, "typeName":"演示专用", "typeInfo":"abc2", "fkParentId":2, "wordTplAddress":"", "fkBorrowFlow":11521 }
​
//可以省略,如果省略,则默认使用类名小写映射集合
@Document("files")
//复合索引(推荐使用命令行方式去添加索引)
//@CompoundIndex(def = "{'id':1, 'typeInfo':-1}")
public class File {
​
    //主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫"id",则该注解可以省略
    @Id
    private String _id;
    //添加一个单字段索引
    //@Indexed
    private Integer id;
    //该属性对应MongoDB的属性字段名称,如果一致可以省略这个注解
    @Field("typeInfo")
    private String typeInfo;
    private String typeName;
    private Integer fkParentId;
    private String wordTplAddress;
    private String fkBorrowFlow;
    // get / set / toString
}
​
// 2、repository层
import com.re.po.File;
import org.springframework.data.mongodb.repository.MongoRepository;
​
//file文档对象的持久化层
public interface FilesRepository extends MongoRepository<File, String> {
    //根据typeName获取分页数据
    Page<File> findByTypeName(String typeName, Pageable pageable);
}
​
// 3、service层
import com.re.dao.FilesRepository;
import com.re.po.File;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.List;
​
@Service
public class FileService {
​
    @Autowired
    private FilesRepository filesRepository;
​
    /**
     * 保存file实体类
     */
    public void saveFiles(File file){
        //如果需要自定义主键,这里可以指定主键;如果不自定义主键,MongoDB会自动生成主键
        //设置一些默认初始值
        //调用dao
        filesRepository.save(file);
    }
​
    /**
     * 根据file的id删除file文档
     * @param id
     */
    public void deleteFileById(String id){
        //调用dao
        filesRepository.deleteById(id);
    }
​
    /**
     * 根据file更新file文档数据
     * @param file
     */
    public void updateFile(File file){
        //调用dao
        filesRepository.save(file);
    }
​
    /**
     * 查询所有文档
     * @return
     */
    public List<File> findFilesList(){
        //调用dao
        return filesRepository.findAll();
    }
​
    /**
     * 根据id查询file文档
     * @return
     */
    public File findFileById(String id){
        //调用dao
        return filesRepository.findById(id).get();
    }
    
    /**
     * 根据typeName分页查询文档
     * @param typeName
     * @return
     */
    public Page<File> findByTypeName(String typeName, int page, int size) {
        return filesRepository.findByTypeName(typeName, PageRequest.of(page-1,size));
    }
}
​
// 4、controller层
import com.re.po.File;
import com.re.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
import java.util.List;
​
@RestController
@RequestMapping("/file")
public class FileController {
​
    @Autowired
    private FileService fileService;
​
    /**
     * 查询files集合内所有的文档
     * @return
     */
    @GetMapping("/getAllFiles")
    public List<File> getAllFiles(){
        return fileService.findFilesList();
    }
    
    /**
     * 根据id分页查询文档
     * @param typeName
     * @return
     */
    @GetMapping("/findByTypeName")
    public Page<File> findByTypeName(String typeName, Integer page, Integer size){
        if (typeName==null || page == null || size == null){
            return null;
        }
        Page<File> byTypeName = fileService.findByTypeName("typeName", page, size);
        return byTypeName;
    }
}

副本集

1、两种类型三种角色

1、两种类型:(主节点:数据操作的主要连接点,可读写。)(从节点:备份,可以读或选举。)

2、三种角色:(主要成员:主要接收所有写操作。就是主节点。)(副本成员:从主节点复制相同数据集,不可写操作。是一种从节点类型。)(仲裁者:不保留任何数据的副本,只具有投票选举的作用。)

2、搭建副本集

2-1、主节点

1、创建目录

[root@localhost /]# mkdir -p /mongodb/myrs_27017/data/db
[root@localhost /]# mkdir -p /mongodb/myrs_27017/log
[root@localhost /]# mkdir -p /mongodb/myrs_27018/data/db
[root@localhost /]# mkdir -p /mongodb/myrs_27018/log
[root@localhost /]# mkdir -p /mongodb/myrs_27019/data/db
[root@localhost /]# mkdir -p /mongodb/myrs_27019/log

2、配置文件

[root@localhost myrs_27017]# vi /mongodb/myrs_27017/mongod.conf

内容

systemLog:
   #MongoDB发送所有日志输出的目标指定为文件
   destination: file
   #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
   path: "/mongodb/myrs_27017/log/mongod.log"
   #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
   logAppend: true
storage:
   #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
   dbPath: "/mongodb/myrs_27017/data/db"
   journal:
      #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
      enabled: true
processManagement:
   #启用在后台运行mongos或mongod进程的守护进程模式。
   fork: true
   # 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
   pidFilePath: "/mongodb/myrs_27017/log/mongod.pid"
net:
   #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
   #bindIpAll: true
   # 服务实例绑定的IP
   bindIp: localhost,192.168.2.120
   #bindIp
   #绑定的端口,默认是27017
   port: 27017
replication: 
   # 副本集的名称(多个节点的副本集名称要一致)
   replSetName: myrs

3、启动

[root@localhost myrs_27017]# /usr/local/mongodb/bin/mongod -f /mongodb/myrs_27017/mongod.conf

2-2、从节点

1、配置文件

[root@localhost myrs_27018]# vi /mongodb/myrs_27018/mongod.conf

内容

systemLog:
   #MongoDB发送所有日志输出的目标指定为文件
   destination: file
   #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
   path: "/mongodb/myrs_27018/log/mongod.log"
   #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
   logAppend: true
storage:
   #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
   dbPath: "/mongodb/myrs_27018/data/db"
   journal:
      #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
      enabled: true
processManagement:
   #启用在后台运行mongos或mongod进程的守护进程模式。
   fork: true
   # 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
   pidFilePath: "/mongodb/myrs_27018/log/mongod.pid"
net:
   #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
   #bindIpAll: true
   # 服务实例绑定的IP
   bindIp: localhost,192.168.2.120
   #bindIp
   #绑定的端口,默认是27018
   port: 27018
replication: 
   # 副本集的名称(多个节点的副本集名称要一致)
   replSetName: myrs

2、启动

[root@localhost myrs_27018]# /usr/local/mongodb/bin/mongod -f /mongodb/myrs_27018/mongod.conf

2-3、仲裁节点(不保存数据)

1、配置文件

[root@localhost myrs_27019]# vi /mongodb/myrs_27019/mongod.conf

内容

systemLog:
   #MongoDB发送所有日志输出的目标指定为文件
   destination: file
   #mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
   path: "/mongodb/myrs_27019/log/mongod.log"
   #当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
   logAppend: true
storage:
   #mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
   dbPath: "/mongodb/myrs_27019/data/db"
   journal:
      #启用或禁用持久性日志以确保数据文件保持有效和可恢复。
      enabled: true
processManagement:
   #启用在后台运行mongos或mongod进程的守护进程模式。
   fork: true
   # 指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
   pidFilePath: "/mongodb/myrs_27019/log/mongod.pid"
net:
   #服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
   #bindIpAll: true
   # 服务实例绑定的IP
   bindIp: localhost,192.168.2.120
   #bindIp
   #绑定的端口,默认是27019
   port: 27019
replication: 
   # 副本集的名称(多个节点的副本集名称要一致)
   replSetName: myrs

2、启动

[root@localhost myrs_27019]# /usr/local/mongodb/bin/mongod -f /mongodb/myrs_27019/mongod.conf

2-4、初始化副本集

2-4-1、主节点

[root@localhost /]# /usr/local/mongodb/bin/mongo
MongoDB shell version v4.4.14
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("4a1f2f91-b631-479a-bd20-8efd08142bb3") }
MongoDB server version: 4.4.14
..........
> rs.initiate()  # 初始化
{
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "192.168.2.120:27017",
        "ok" : 1
}
myrs:SECONDARY> 
myrs:PRIMARY>   # PRIMARY主节点

2-4-2、从节点(在主节点添加从节点rs.add(host)或者rs.add(host, false) )

rs.add(host, arbiterOnly)

如果host是一个字符串应该包含ip和端口号,也可以是一个主机成员配置文档。arbiterOnly为true表示为仲裁节点,如果为false表示为从节点。

myrs:PRIMARY> rs.add("192.168.2.120:27018", false)  # 在主节点添加从节点
{
        "ok" : 1,                                   # 看到ok代表成功
        "$clusterTime" : {
                "clusterTime" : Timestamp(1656549106, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1656549106, 1)
}
myrs:PRIMARY> rs.config()   # 再次查看发现27018也进来了
{
        "_id" : "myrs",
        "version" : 2,
        "term" : 1,
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "192.168.2.120:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                                
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 1,
                        "host" : "192.168.2.120:27018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                                
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ]......
}
myrs:PRIMARY> 

2-4-3、仲裁节点

rs.addArb(host)或者rs.add(host,true)

myrs:PRIMARY> rs.addArb("192.168.2.120:27019")  # 添加仲裁节点
{
        "ok" : 1,                               # 看到ok代表成功
        "$clusterTime" : {
                "clusterTime" : Timestamp(1656549589, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        },
        "operationTime" : Timestamp(1656549589, 1)
}
myrs:PRIMARY> rs.config()   # 再次查看发现27019也进来了
{
        "_id" : "myrs",
        "version" : 3,
        "term" : 1,
        "protocolVersion" : NumberLong(1),
        "writeConcernMajorityJournalDefault" : true,
        "members" : [
                {
                        "_id" : 0,
                        "host" : "192.168.2.120:27017",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                                
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 1,
                        "host" : "192.168.2.120:27018",
                        "arbiterOnly" : false,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 1,
                        "tags" : {
                                
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                },
                {
                        "_id" : 2,
                        "host" : "192.168.2.120:27019",
                        "arbiterOnly" : true,
                        "buildIndexes" : true,
                        "hidden" : false,
                        "priority" : 0,
                        "tags" : {
                                
                        },
                        "slaveDelay" : NumberLong(0),
                        "votes" : 1
                }
        ],
        ......
}
myrs:PRIMARY> 

2-5、添加数据

myrs:SECONDARY> show dbs
uncaught exception: Error: listDatabases failed:{
        "topologyVersion" : {
                "processId" : ObjectId("62bcec94c6af0385dfdd73ed"),
                "counter" : NumberLong(4)
        },
        "operationTime" : Timestamp(1656551618, 1),
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotPrimaryNoSecondaryOk",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1656551618, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs/<@src/mongo/shell/mongo.js:147:19
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:99:12
shellHelper.show@src/mongo/shell/utils.js:937:13
shellHelper@src/mongo/shell/utils.js:819:15
@(shellhelp2):1:1
myrs:SECONDARY> rs.slaveOk()    # 开启自己为从节点,开启读数据权限
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
myrs:SECONDARY> show dbs
admin    0.000GB
article  0.000GB
config   0.000GB
local    0.000GB
myrs:SECONDARY> use article
switched to db article
myrs:SECONDARY> db.files.find()     # 从节点也可以读取到数据
{ "_id" : 1, "typeName" : "演示专用", "id" : 1001 }
myrs:SECONDARY> rs.slaveOk(false)   # 取消作为奴役节点(不具备读权限)
WARNING: slaveOk() is deprecated and may be removed in the next major release. Please use secondaryOk() instead.
myrs:SECONDARY> db.files.find()     # 再次读取数据就报错了
Error: error: {
        "topologyVersion" : {
                "processId" : ObjectId("62bcec94c6af0385dfdd73ed"),
                "counter" : NumberLong(4)
        },
        "operationTime" : Timestamp(1656558608, 1),
        "ok" : 0,
        "errmsg" : "not master and slaveOk=false",
        "code" : 13435,
        "codeName" : "NotPrimaryNoSecondaryOk",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1656558608, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

2-6、主节点的选举

1、主节点故障。

2、主节点网络不可达(默认心跳为10秒)。

3、人工干预(rs.stepDown())。

当从节点挂掉后然后主节点数据发生变更后,从节点又重新启动起来时也可以读取到在这期间主节点变化的数据。

当主节点挂掉后,从节点会被选举为主节点(票数得到半数以上)。

3、SpringDataMongoDB连接副本集

3-1、配置文件

spring:
  data:
    mongodb:
      # database: articledb
      # host: 192.168.2.120
      # password:
      # port: 27017
      # 也可以直接使用uri连接
      # 连接副本集
      uri: mongodb://192.168.2.120:27017,192.168.2.120:27018,192.168.2.120:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs
​
server:
  port: 8090

目录

1、给单字段添加索引

2、添加复合索引

3、删除索引

4、索引的使用

SpringBoot操作MongoDB

1、配置依赖

2、application.yml配置文件

3、编写实体类、repository、service、controller

副本集

1、两种类型三种角色

2、搭建副本集

3、SpringDataMongoDB连接副本集


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值