Skip to content

Mongodb 笔记 #21

Description

@Calerme

下载安装

从官网下载相应的版本 www.mongodb.com

wget https://www.mongodb.com/dr/fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.6.2.tgz/download
tar -xzvf mongodb-linux-x86_64-rhel70-3.6.2.tgz mongodb

可以直接运行 bin 文件夹下的命令文件,或者将 mongodb 加入环境变量,使它相关的命令变为全局命令:

mv mongodb /usr/local/mongodb

/etc/profile 或者 .zshrc 中添加以下语句:

PATH=$PATH:/usr/local/mongodb/bin
export PATH

创建目录结构

示例中将 mongodb 放入单独的项目文件中。

目录结构:

mongode_example
  |- data
  |- log
  |- conf
  |- bin
  |- mongodb # mongodb 源文件

创建配置文件

在 conf 文件夹中创建 default.conf 文件:

port = 12345 # 数据库端口号,默认27017
dbpath = data # 数据存储的目录
logpath = log/mongodb.log # 日志文件路径
fork = true # 让 mongodb 在后台运行

启动 mongodb

可以将 mongodb 源文件中的 bin 文件夹复制到 mongodb_example 目录中,方便命令调用。

启动 mongodb:

./bin/mongod -f conf/default.conf
# -f 指定配置文件

使用 mongo 转接数据库

mongo 是 mongodb 提供的原生的数据库管理客户端。

连接数据库:

./bin/mongo 127.0.0.1:12345/test # test 为数据库名称,test 也是默认的数据库

关闭数据库服务

在 mongo 客户端中输入:

use admin # 使用管理员权限
db.shutdownServer()

操作数据库

以下指令全部在 mongo 客户端中执行,其他编程语言的驱动程序语法大同小异。

基本操作

查看数据库

show dbs

进入数据库

进入 example 数据库,如果没有 example 数据库,mongo 会自动创建

use example

删除数据库

db.dropDatabase()
# 此时执行
show dbs
# 已经没有 example 数据库了

显示数据库中的集合(表)

show collections
# 等同于
show tables

创建集合并插入数据

如果没有指定集合,mongo 会自动创建:

db.example_collection.insert( { x: 1} );

插入多条数据

// 插入了97条数据
for (let i=3; i<100; i++)  db.example_collection.insert( { x: i } );

查询集合(表)中的数据

显示表中的所有数据:

db.example_collection.find();

每条数据都有一个_id字段,这个字段是数据默认且必须的索引,它的值在全局不能重复,可以在创建数据时,手动输入_id的值,但必须保证不能重复:

db.example_collection.insert({_id:'12345', x:1});

查询集合(表)中有多少条数据

db.example_collection.find().count();

过渡查询结果

显示 2 条数据,查询时跳过开头的 3 条数据,并将结果以 x 键进行排序

db.example_collection.find().skip(3).limit(2).sort( { x: 1} )
// 这里的 x : 1 的值表示以正序排序,-1 为倒序排序

更新数据

update() 方法默认只更新查询到的第一条数据。

db.example_collection.update( { x: 3 }, { x: 999});
// 第一个参数为查询条件,第二个参数为将要更新为的值
// 如果 { x:3 } 匹配到的整条数据都会被 { x: 999 } 覆盖,即其他键值对都会删除

局部更新数据

要想只更新匹配到的键值,需要使用$set特殊键:

db.example_collection.insert( { x: 100, y: 200, z: 300 } );
db.example_collection.update( { y: 200 }, { $set: { z: 500 });
// 匹配到的数据只有 z 键被更新了,x 和 y 还都在,没有被覆盖

更新不存在的数据

updata 默认更新不存在的数据会进行任何操作,但如果将第三个参数设为 true,update 在更新数据时,如果数据存在就会创建这条数据:

db.example_collection.update( { y: 2333 }, { y: 888 }, true);
// 这时 如果 { y: 2333 } 不存在,就会创建 { y: 888 } 这条数据

更新匹配到的所有数据

前面说到 update 默认只会更新查询到的第一条数据,可以设置第四个参数为 true,update 就会更新所有匹配到的数据,不过出于安全设计的原则,此种更新方式只支持局部更新:

db.example_collection.update( {x: 3}, {$set: { y: 100} }, false, true);

删除数据

remove 默认删除所有匹配到的数据(文档)。

db.example_collection.remove({c:2});

// 只删除匹配到的第一条
db.example_collection.remove( {c:2}, true);

删除整个集合(表)

db.example_collection.drop();
// 此时 example_collection 已经不存在了
show tables

索引

_id是唯一默认且必须的索引,创建索引后可以显著地加快查询速度。索引应该尽早在数据库创建时就进行设置,如果数据太多,再进行索引创建,交会非常耗时。

查看目前数据库中有哪些索引

db.example_collection.getIndexes();

单键索引

// 以 x 键健索引,且为正向排序。此后再以 x 键进行搜索速度会是非常快。
db.example_collection.ensureIndex( { x: 1 } );

多键索引

// db.example_collection.ensureIndex({x:1}) 会为下面的文档创建多键索引
db.example_collection.insert({x:[1,2,3,4,5});
// 下面两条语句都可以找到上面的文档
db.example_collection.find({x:1});
db.example_collection.find({x:4});

复合索引

查询条件不为一时,就需要创建复合索引。

db.example_collection.ensureIndex({x:1, y:1});
db.example_collection.find({x:3, y:4});

过期索引

索引会在设定的时间内过期,过期后相应的数据(文档)就会被删除。

过期索引适合存储一些实效数据,如用户的登录信息,存储日志等。

db.example_collection.ensureIndex({ time: 1 }, { expireAfterSeconds:30 });
// expireAfterSeconds 表示 30 秒后索引过期
db.example_collection.insert({ time: new Date() }); // 这条数据会在 30 秒后被删除
  • 过期索引指定的时间字段必须是时间类型,必须是 ISO Date 或 ISO Date 数组,不能使用时间戳,否则不能自动删除。
  • 如果指定了 ISO Date 数组,则按照最小的时间进行删除。
  • 过期索引不能是复合索引。
  • 删除数据的时间不是精确的。删除过程是由后台程序每 60s 跑一次,而且删除操作本身也需要一定的时间。

全文索引

如在一个博客网站进行搜索时,搜索的关键字会匹配博客的标题,博客的作者,博客的内容,这就是使用全文索引对数据库进行了检索。

每个集合(表)只允许创建一个全文索引。

db.example_collection.ensureIndex({ author: "text", title: "text", article: "text" });
// 对所有键创建全文索引
db.example_collection.ensureIndex({ "$**": "text" });

使用全文索引进行查询

示例:

// 先添加几组数据
db.example_collection.insert({article: "aa bb cc dd ee"});
db.example_collection.insert({article: "aa bb rr gg"});
db.example_collection.insert({article: "aa bb cc hh xx"});

// 单个关键字查询
db.example_collection.find({$text: { $search: 'aa' }});

// 多个关键字查询,用空格将关键字格开便可
// 这种查询为 或 查询,即只要包含一个关键字就算匹配成功
db.example_collection.find({$text: {$search: 'aa bb cc'}});

// 排队查询,在排队的关键字前加一个 - 号便可
// 以下语句表示查询一个包含 aa 或 bb 的数据但不包含 cc
db.example_collection.find({$text: { $search: 'aa bb -cc' }});

// 给关键字加上引号,即为 与 查询,即列出的关键字必须被匹配到
db.example_collection.find({$text: {$search: "\"aa\" \"bb\" \"cc\""}});

全文索引的相似度

为 find 传入第二个参数 {score: {$meta: 'textScore'}} 会为返回的结果中添加 score 字段,代表数据与查询条件的相似度。

配合 sort 会达到很好的实用效果。

db.example_collection.find({ $text: { $search: 'aa bb cc' }}, { score: {$meta: 'textScore'}})
  .sort({ score: {$meta: 'textScore'}});

自定义索引

使用getIndexes会看到当前数据集合中的所有索引,每个索引有一个 name 值,这个值是 mongodb 自动生成的,全文方法为“键值加下划线加正一或负一”, 例:x_1_y_-1_z_1

自定义索引名即在创建索引时,传入第二个参数:

db.example_collection.ensureIndex({x:1, y:-1, z:1}), {name: 'normalIndex'});

唯一索引

即此索引中的数据不能重复。

db.example_collection.ensureIndex({m:1, n:1}, {unique: true});

db.example_collection.insert({m:1, n:1});
db.example_collection.insert({m:1, n:1}); // 报错,不能存入

稀疏性索引

地理位置索引

概念:将一些占的位置存储在 MongoDB 中,创建索引后,可以按照位置来查找其他点。

子分类:

  • 2d 索引,用于存储和查找平面上的点。(示例:查找附近的人)
  • 2dsphere 索引,用于存储和查找球面上的点

2d 索引

平面地理位置索引。

在 MongoDB 中使用经纬度 [经度,纬度] 表示地理位置。

取值范围:

  • 经度:-180~180
  • 纬度:-90~90
// 创建 2d 索引
db.example_collection.ensureIndex({w: '2d'});

// 插入几条数据
db.example_collection.insert({w: [1, 1]});
db.example_collection.insert({w: [1, 2]});
db.example_collection.insert({w: [3, 2]});
db.example_collection.insert({w: [100, 70]});

$near 查询距离某个点最近的点:

db.example_collection.find({w:{$near: [1,1], $maxDistance: 10, $minDistance: 3}});
// $maxDistance 默认值为100,即距离指定点最远为 100 个点的距离

$geoWithin 查询某个形状中的点

  • $box: [[, ], [, ]] 矩形
  • $center: [[, ], r] 圆形
  • $polygon: [[x1, y1], [x2,y2], ...] 多边形
db.example_collection.find({w: {$geoWithin: {$box: [[0,0], [3,3]]}}});

getNear 使用 runCommand 命令进行使用:

db.runCommand(
  {
    geoNear: 'example_collection',
    near: [x, y],
    minDistance: 20, (对 2d 索引无效
    maxDistance: 30,
    num: 1, // 只返回一个数据
  }
);

2dphere 索引

概念:球面地理位置索引。

位置表示方式:GeoJSON——描述一个点,一条直线,多边形等开头。

GeoJSON格式:{type: '', coordinates: [<coordinats>]}

db.example_collection.ensureIndex({w: "2dsphere"});

索引构建分析

好处: 加快索引相关的查询。

坏处:增加磁盘空间,降低写入性能。

mongostat 工具

查看 mongoDB 运行状态的程序。

./mongostat -h 127.0.0.1:12345

profile 集合

日志

在 mongodb 的 config 文件里可以设置日志的级别,由一个v~vvvvv(5个)表示

port = 12345
dbpath = data
logpath = log/mongod.log
bind_ip = 127.0.0.1
verbose = vvvvv
fork = true

explain 操作

显示查询操作的详细参数

db.example_collection.find({x:1}).explain();

MongoDB 安全

  • 最安全的是物理隔离:不现实
  • 网络隔离:内网、外网
  • 防火墙隔离:只允许指定 IP 访问
  • 用户名密码的安全性最低

开启权限认证

默认情况下,MongoDB 不会开启权限认证。

  1. 创建用户:

用户类型(MongoDB内建):

  • read
  • readWrite
  • dbAdmin
  • dbOwner
  • userAdmin
db.createUser({
  user: 'caler',
  pwd: 'mima',
  customData: '备注信息',
  roles: [ // 用户角色类型
    { role: 'userAdmin', db: 'admin' }, // 对 admin 数据库是 userAdmin 权限
    { role: 'read', db: 'test' } // 对 test 数据库具有 read 权限
  ]
});

2.修改配置文件中的 auth 开启权限认证:

auth = true

3.使用用户名密码连接数据库

mongo 127.0.0.1:12345 -u caler -p mima

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions