公司需要做LBS方面的应用,经过多方考察,决定使用mongodb。网上很多mongodb的资料,但是很少有java方面的资料,而且mongodb单位的讲解也特别混乱。因此有了这篇博客,欢迎大拿拍砖,请轻拍。
一、启动mongo(mongo官网:http://www.mongodb.org/)
1)、启动master:
mongod --dbpath/data/mongodb/db/r0/ --config /etc/mongor0.cnf --master --auth
2)、启动slave:
mongod --dbpath/data/mongodb/db/r1/ --config /etc/mongor1.cnf –slave
二、常用命令
mongo –help:查看mongo帮助
mongo -u Beside -p'fetiondev@))%db' 127.0.0.1:27017/Beside:通过用户名密码查看指定的库
show dbs:查看所有库
use xxx:切换到xxx库
db.addUser('用户名','密码'):添加用户、密码,如果db为admin,表示添加全局用户
show collections:查看所有集合
db.BesideTimeline.find():查询语句,可以与sort()、skip()、limit()、explain()、hint()、count()等方法使用, BesideTimeline表示集合名
db.BesideTimeline.ensureIndex({"position":"2d","feedid":-1}):添加position 的2d索引和feedid降序的复合索引
db.BesideTimeline.dropIndex({"feedid":-1}):删除索引
db.BesideTimeline.getIndexes():查看索引
三、java接口(网上讲geohash的很多,但是讲java调用的很少)
1、连接db
MongoClient mongoClient = newMongoClient(host, port);//连接mongo
DB db = mongoClient.getDB(dbName);//获取db
db.authenticate(userName,pwd.toCharArray());//登陆验证
2、使用BasicDBObjectBuilder 类拼接geoNear查询语句(包含详细的单位说明)
3、使用DBCollection类执行查询条件,结果集存储在DBCursor类中
4、第2、3步也可以使用BasicDBObject类封装
BasicDBObject feedId = newBasicDBObject();//封装查询条件
feedId.put("$lt", offset);
basicDBObject.put(FEED_ID,feedId);
DBObject orderBy = newBasicDBObject();//封装排序条件
orderBy.put(FEED_ID, -1);//降序
DBCollection dbCollection =besideTimelineDB.getCollection(TABLE_NAME);//获取集合
DBCursor dbCursor =dbCollection.find(basicDBObject).sort(orderBy).limit(num);//执行查询
5、DBCollection类
insert():插入方法,包含一个参数,可以是单个DBObject和批量List< DBObject>
update(DBObject condition,DBObject dbObject):更新方法,第一个参数是更新条件,第二个参数是更新值
remove(DBObject condition):删除方法,包含一个参数,表示删除条件
6、查询的单位问题:网上很多奖mongodb查询单位的文章,但是都不全面或者表述不清楚
1)、mongodb包含三种单位:米(meters)、平面单位(flat units,指经纬度的“一度”)、弧度(radians,指扇形角的度数)
2)、不同的存储方式或者查询方式使用的单位不一样
①如果数据在db中是以GeoJSON存储,则所有查询的单位都是米
②如果查询条件是以$near查询,则查询单位是平面单位“度”。假定你的系统传进来的参数是“米”,由于$near接受的是平面单位“度”,那么在拼接语句(可以认为是sql语句)的时候需要将“米”转换成“度”:米/1000/111,意思是将“米”转换成“公里”,再转换成“度”。如果不进行转换就进行查询,例如你传入100米,mongo会认为是100度。差距有多大,可想而知。其他情况,查看下表,进行类似转换即可。
3)米、平面单位“度”、弧度转换
①1米=(1/1000/111)度,其中1000表示转换成公里;111表示公里转换成度,这是近似值。
②1米=(1/1000/6371)弧度, 其中1000表示转换成公里;6371表示公里转换成弧度,以赤道为准,也是近似值。
注意:1)、关于mongo应用场景和单位的问题,推荐博客
2)、mongodb不适用与对时间敏感的应用场景,我有血的教训
3)、skip()方法存在效率问题,mongodb的java驱动本身效率很低
补充geonear查询的另一种方法:
BasicDBObject query = new BasicDBObject("timestamp", new BasicDBObject("$lt", SOMETIME));
// aggregate: geoNear
double[] currentLoc = new double[] {
Double.parseDouble(myLon),
Double.parseDouble(myLat)
};
DBObject geoNearFields = new BasicDBObject();
geoNearFields.put("near", currentLoc);
geoNearFields.put("distanceField", "dis");
geoNearFields.put("maxDistance", AROUNDME_RANGE_RADIUS_IN_RADIANS));
geoNearFields.put("query", query);
//geoNearFields.put("num", 5000); // FIXME: a temp solution I would really like to avoid
DBObject geoNear = new BasicDBObject("$geoNear", geoNearFields);
// aggregate: sort by timestamp
DBObject sortFields = new BasicDBObject("timestamp", -1);
DBObject sort = new BasicDBObject("$sort", sortFields);
// aggregate: limit
DBObject limit = new BasicDBObject("$limit", 20);