mongodb初学习

/ 0评 / 0

目前学习使用mongodb,主要是一个项目中使用到了地理位置服务相关的内容。比如发布一个活动,客户端自动将当前位置获取到一同存储到后端;可以利用数据库中的地理位置信息实现如“附近的活动,附近的人;在地图上展现附近的活动、人”等功能。

原先的这些location功能实现是一并采用mysql建表实现的。

[mysql]

CREATE TABLE `i_event_locations` (
`event_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '活动id',
`name` varchar(255) NOT NULL DEFAULT '' COMMENT 'Name',
`address` varchar(255) NOT NULL COMMENT 'Address',
`lat` double NOT NULL DEFAULT '0' COMMENT '纬度',
`lng` double NOT NULL DEFAULT '0' COMMENT '经度',
`created` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '创建时间',
`updated` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
UNIQUE KEY `event_id` (`event_id`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Location Table'

[/mysql]

表结构就是如此,需要说明的是活动event与location是一对一的关系,event_id就是活动id即是外键也是主键。

这样的结构在后端业务中怎么实现呢,主要思路就是通过传入经纬度得到一个表达式distance,在event与location进行join联表查询时按distance进行desc的排序,得到最近的event list;如果需要限制在10km之间,那么就需要加上where distance < 10000

[php]

/**
* 返回计算距离的SQL语句表达式
* @param $lat
* @param $lng
*/
private function get_distance_exp($lat, $lng){
return DB::expr("(2 * 6378.137* ASIN(SQRT(POW(SIN(PI() * ($lat - lat)/360), 2) + COS(PI() * {$lat} / 180)
* COS(lat * PI() / 180) * POW(SIN(PI() * ({$lng} - lng) / 360), 2))))*1000");
}

[/php]

就是上面这个东东,我也没看明白是什么原理。总之它返回的是以米为单位的一个数据值。

弊端确实有,需要联表查询且还要计算表达式可能会比较慢。(详细性能测试暂没有进行)

确实需要了解下性能方面的问题了,不能只听别人说mysql这样处理很慢就觉得慢,听别人说mongodb用的快就用;

mongodb是文档化schema free(自由格式)的数据库,开源有商业团队支持,高速发展,应用广泛;与mysql不存在谁取代谁的问题,只是什么环境下哪种数据库更适合。

回到那个地理位置检索的问题,将i_event_locations转变为mongodb collection后,可以根据建立的loc二维索引进行当前location 经纬度的检索,这样就得到了所有的event_id值,在通过这些event_id的到符合需求条件的event活动;

这样也就不用进行联表查询以及地理位置的表达式运算(这部分目前直接交予索引处理了);

MongoDB的特性 来自blog.nosqlfan.com

MongoDB的优点

使用MongoDB,你得记住以下几点:

MongoDB在下面领域不太擅长

安装mongodb

要学习使用,首先下载mongodb

windows 32位平台下也可以安装但是数据容量最大只有2G,可以作为测试学习之用,不推荐作为工作生产环境。

Linux 64位则最大可以达到128T,所以推荐linux平台上部署。

mongodb下载后解压到目录后

进入bin里面执行下面命令

--dbpath 是mongodb数据库文档存储目录,--logpath 是mongodb的日志文件,--install 则是将mongodb安装到系统服务里面去。要了解更多命令执行mongod --help查看。

执行完成后检查mongodb.log要是没有错误信息,则通过http://localhost:27017可以看到

You are trying to access MongoDB on the native driver port. For http diagnostic access, add 1000 to the port number
则说明成功了。而访问http://localhost:28017 可以查看mongodb的监控信息。

注意这里第一次安装没有成功时,mongodb_data里面新生成的的mongod.lock 可能会被锁住,再次安装时会产生

dbexit: really exiting now

这时需要删除掉mongod.lock,重新进行安装。

注意在windows xp 下面安装时可能会出现“无法定位程序输入点 InterlockedCompareExchange64 于动态链接库KERNEL32.dll上”

原因就是这样

“Mongodb最新的开发分支已经不再支持xp,也就是说vista是最陈旧支持的客户端,windows server2003是最陈旧的windows服务器版本,但是2.0的分支任然支持着xp,V2.0.6是最新也是最后一个新版本支持xp。因此最好还 是在 linux 下开发吧。”

我的windows xp安装版本是

db version v2.0.6, pdfile version 4.5
Wed Feb 27 22:24:02 git version: e1c0cbc25863f6356aa4e31375add7bb49fb05bc

所以还是推荐最新平台最新版本吧。

MongoDB shell命令

MongoDB自带一个JavaScript shell, 以命令行与MongoDB实例交互。

可以执行管理操作,检查运行实例等

启动Shell:

$ ./mongo

可以运行任何JavaScript程序,还可以利用JavaScript的标准库。所以所有的对象方法都是区分大小写的,输入命令时要注意!

可以定义和调用JavaScript函数。

可以使用多行命令。

show dbs; -- 查看数据库

show databases;  --查看数据库

use dbname; --选择数据库

show collections; --查看表

show tables; --查看表

db.tablename.find(); -- tablename的数据查询,

db.tablename.find({a: 'k'}); -- 对a字段进行数据k的匹配检索查询

db.tablename.find({a:'k'}).sort({id: -1}); --对a字段进行数据k的匹配检索查询且按照id进行倒叙排列,反之1则是正序排列了

db.tablename.find({a:'k'}).limit(5); --对a字段进行数据k的匹配检索查询只返回最初5条记录

db.tablename.find({a:'k'}).skip(2).limit(5); --对a字段进行数据k的匹配检索查询从第二条开始返回5条记录。skip()限制返回记录的开始点,就等于是mysql里面的offset

db.tablename.save({a: 'haha', id:'22}); -- 添加新的记录

db.tablename.update({id: 22},  {$set: {a: 'xixi'}}); -- 对id为22的字段a进行修改;即第一个参数是query(也就是mysql中的where),第二个参数修改内容集合,还有第三个参数就是update时的一些设置;

db.tablename.remove({id:22}, 1); -- 删除id为22的记录,第一个参数为where,第二个参数为limit,比如为1则只删除查询结果中的1条

db.tablename.drop(); --删除当前的表,drop()不同于remove(),remove只是清空数据,drop直接数据连同表删除了

db.dropDatabase(); --删除当前的数据库

mongodb crud manual

db.location.ensureIndex({loc: 2d}) --对location构建2d 地理位置的索引,{id: 1}设置为1则是正序索引,-1倒序索引;1(ascending),-1(descending)

db.location.getIndexes(); --查看location的索引。

db.location.getIndexKeys(); --查看location的索引keys。

db.location.dropIndex('loc'); --按索引名字删除索引,注意这里不是字段的名字

db.location.count(); --查询表中记录数

 

mongodb数据导出,不是进入到mongo shell里面去,

mongodump -d databasename -o D:/dirname -u username -p  --等于是mysql的mysqldump命令一样。

有导出当然有导入咯。

mongorestore -d test D:\mongodb_bak\test -u admin -p --还原test数据库

mongodb不推荐使用mongoexport与mongoimport来进行导出与导入;而是推荐使用mongodump与mongorestore来进行。

 

 

mongodb权限验证

mongodb 默认是无权限验证就可访问的。所以需要开启auth用户验证,需要在mongod安装时加上 --auth参数

Control Access to MongoDB Instances with Authentication

加入--auth参数安装好mongodb后;可以使用下面的进行用户设置

-- 超级管理员,所有数据库都能访问

use admin

db.addUser("username","password");

-- 普通管理员

user exampledb

db.addUser("alex","alex");

alex只能对exampledb进行查看管理

-- 只读管理员,登录后只有读的权限

user exampledb

db.addUser("alex","alex",true);

 

对比之前的无认证环境,可以看到现在都出现了need login的信息内容了。

那首先就login

db.auth("username","password");  返回的是1,表示这个用户匹配上了,也就是登录成功了。

 

还有一种就是keyFile的方式,

Specify the path to a key file to store authentication information. This option is only useful for the connection between replica set members.

指定的密钥文件的路径存储身份验证信息。此选项只适用于副本集成员之间的连接。(没明白这个副本集成员之间的链接是什么意思)

同样是在安装时指定 mongod --keyFile filepath

keyFile 必须小于1kb,只是包含base64的字符;密钥文件没有组且具有 “world” permissions on UNIX systems

+++++

unix world permissions

unix的世界权限是个啥呢?Unix Permissions

找到了一篇解答

The third group of permission bits corresponds to the world permissions. These are the permissions granted to everyone.

也就是每一个人都具有这个权限,任何人都有这个权限。

+++++

在windows system上面不检测权限。

更多请看:Security Considerations for Replica Sets

 

 

 

更多命令看这里

学习资料推荐

MongoDB Manual

MongoDB资料汇总专题

MySQL和MongoDB设计实例对比

Php Mongodb Manual

MongoDB php driver

Php mongodb-odm

Kohanaframework mongodb module

从PHP客户端看MongoDB通信协议

发表评论

您的电子邮箱地址不会被公开。

*