公司需要做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查询语句(包含详细的单位说明)

 

mongodb 固定小数位 double mongodb数据基本单位_lbs

3、使用DBCollection类执行查询条件,结果集存储在DBCursor类中

mongodb 固定小数位 double mongodb数据基本单位_lbs_02

 

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度。差距有多大,可想而知。其他情况,查看下表,进行类似转换即可。

mongodb 固定小数位 double mongodb数据基本单位_lbs_03

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);