近期項目做了次架構調整,原來是使用MySQL+GeoHash來存儲LBS數據(地理位置信息),現在使用NOSQL數據庫MongoDB來存儲LBS數據(地理位置信息)。由於項目是基於spring MVC開發的,今天就Mongodb的使用做下總結。
Spring MVC 集成Mongodb
1.加載jar,maven配置
<!-- 新加入的spring整合mongodb的包 開始 --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>2.13.0-rc0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.7.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-cross-store</artifactId> <version>1.7.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-log4j</artifactId> <version>1.7.1.RELEASE</version> </dependency> <!-- 新加入的spring整合mongodb的包 結束 -->
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
2.配置
Mongodb分2種方法集成,分別是單機和集群方式。
單機配置
applicationContext.xml
<mongo:mongo id="mongo" host="${mongo.host}" port="${mongo.port}" > <mongo:options connections-per-host="${mongo.connectionsPerHost}" threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}" auto-connect-retry="${mongo.autoConnectRetry}" socket-keep-alive="${mongo.socketKeepAlive}" socket-timeout="${mongo.socketTimeout}" slave-ok="${mongo.slaveOk}" write-number="1" write-timeout="0" write-fsync="true"/> </mongo:mongo>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
配置文件common-config.properties
mongo.dbname = test_db #數據庫名稱 mongo.password = test_pwd #密碼 mongo.username = test_user #用戶名 mongo.host = 127.0.0.1 #主機 mongo.port= 27017 #端口號 mongo.connectionsPerHost= 8 #一個線程變為可用的最大阻塞數 mongo.threadsAllowedToBlockForConnectionMultiplier= 4 #線程隊列數,它以上面connectionsPerHost值相乘的結果就是線程隊列最大值 mongo.connectTimeout= 1500 #連接超時時間(毫秒) mongo.maxWaitTime= 1500 #最大等待時間 mongo.autoConnectRetry= true #自動重連 mongo.socketKeepAlive= true #scoket保持活動 mongo.socketTimeout=1500 #scoket超時時間 mongo.slaveOk=true #讀寫分離
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
集群配置
applicationContext.xml
<mongo:mongo id="mongo" replica-set="${mongo.replicaSet}"> <mongo:options connections-per-host="${mongo.connectionsPerHost}" threads-allowed-to-block-for-connection-multiplier="${mongo.threadsAllowedToBlockForConnectionMultiplier}" connect-timeout="${mongo.connectTimeout}" max-wait-time="${mongo.maxWaitTime}" auto-connect-retry="${mongo.autoConnectRetry}" socket-keep-alive="${mongo.socketKeepAlive}" socket-timeout="${mongo.socketTimeout}" slave-ok="${mongo.slaveOk}" write-number="${mongo.writeNumber}" write-fsync="${mongodb.writeFsync}" /> </mongo:mongo>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
配置文件common-config.properties
mongo.dbname = test_db mongo.username = test_user mongo.password = test_pwd mongo.replicaSet = 192.168.2.193:27017,192.168.2.192:27017 mongo.connectionsPerHost= 100 mongo.threadsAllowedToBlockForConnectionMultiplier=50 mongo.connectTimeout=3000 mongo.maxWaitTime=5000 mongo.autoConnectRetry=true mongo.socketKeepAlive=true mongo.socketTimeout=5000 mongo.slaveOk=true mongo.writeNumber = 1 mongodb.writeFsync = true
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
其他配置
<!-- 用戶驗證 --> <bean id="userCredentials" class="org.springframework.data.authentication.UserCredentials"> <constructor-arg name="username" value="${mongo.username}" /> <constructor-arg name="password" value="${mongo.password}" /> </bean> <!-- mongo的工廠,通過它來取得mongo實例,dbname為mongodb的數據庫名,沒有的話會自動創建 --> <bean id="mongoDbFactory" class="org.springframework.data.mongodb.core.SimpleMongoDbFactory"> <constructor-arg ref="mongo" /> <constructor-arg value="${mongo.dbname}" /> <constructor-arg ref="userCredentials" /> </bean> <bean id="mappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" /> <bean id="defaultMongoTypeMapper" class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper"> <constructor-arg name="typeKey"> <null /> </constructor-arg> </bean> <!-- collection的映射 --> <bean id="mappingMongoConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mappingContext" ref="mappingContext" /> <property name="typeMapper" ref="defaultMongoTypeMapper" /> </bean> <!-- mongodb的主要操作對象,所有對mongodb的增刪改查的操作都是通過它完成 --> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" /> <constructor-arg name="mongoConverter" ref="mappingMongoConverter" /> </bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
Mongodb增刪改查
1.Mongodb對象模型
Dynamic.Java
@Document(collection = "Dynamic") public class Dynamic implements Serializable{ /** * */ private static final long serialVersionUID = 179822189115264434L; private String _id; private String userId; //用戶ID private Date releaseDate;//發布日期 private double []loc = new double[2];//位置 public void setId(String _id) { this._id = _id; } public String getId() { return this._id; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public Date getReleaseDate() { return releaseDate; } public void setReleaseDate(Date releaseDate) { this.releaseDate = releaseDate; } public double[] getLoc() { return loc; } public void setLoc(double[] loc) { this.loc = loc; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
2.代碼示例
新增
Dynamic dynamic = New Dynamic();
dynamic.setUserId("10023"); // ... // set屬性,自己補全 // 轉換為DBObject DBObject dbObject = BeanUtil.bean2DBObject(dynamic); db.removeField("serialVersionUID"); // 保存 mongoTemplate.getCollection(collection).save(dbObject)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
更新
普通更新
DBObject aim = new BasicDBObject("_id", id); DBObject setValue = new BasicDBObject(); setValue.put("loc", loc.getLoc()); // 更新的值,用$set DBObject updateSetValue = new BasicDBObject("$set", setValue); //更新,aim:where條件 updateSetValue:更新值 true:是否沒有記錄時插入 false:是否多行更新 mongoTemplate.getCollection(collection).update(aim, updateSetValue , true, false);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
數組更新
DBObject addAim = new BasicDBObject(); addAim.put("_id", id); //數據中push值 DBObject updateSetValue = new BasicDBObject("$push", addedValue); //增加 updateSetValue.put("$inc", new BasicDBObject("commentSize", 1)); mongoTemplate.getCollection(collection).update(addAim, updateSetValue);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
查詢
單條查詢
DBObject query = new BasicDBObject("_id", id); DBObject fields = new BasicDBObject(); mongoTemplate.getCollection(collection).findOne(query, fields)
- 1
- 2
- 3
- 1
- 2
- 3
分頁查詢
int pageSize = 20; int pageNum = 1; DBObject fields = new BasicDBObject(); //排序,-1 降序 DBObject orderBy = new BasicDBObject("release_date", -1); //分頁查詢 List<DBObject> list = new ArrayList<>(); Cursor cursor = mongoTemplate.getCollection(collection) .find(query, fields).skip((pageNum - 1) * pageSize) .limit(pageSize).sort(orderBy); while (cursor.hasNext()) { list.add(cursor.next()); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
范圍查詢
DBObject query = new BasicDBObject(); // $lte 小於等於,$lt 小於 query.put( "release_date", new BasicDBObject("$lte", DateUtil.parseDate( maxTime, DateStyle.YYYY_MM_DD_HH_MM_SS_SSS .getValue()))); // $gte 大於等於,$gt 大於 query.put( "release_date", new BasicDBObject("$gte", DateUtil.parseDate( minTime, DateStyle.YYYY_MM_DD_HH_MM_SS_SSS .getValue())));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
in 和not in 查詢
// $in 查詢 DBObject query = new BasicDBObject("qd_id", new BasicDBObject( "$in", idStr)) // $nin 查詢 DBObject query = new BasicDBObject("qd_id", new BasicDBObject( "$nin", idStr))
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
or 查詢
List orArry = new ArrayList<>(); orArry.add(new BasicDBObject("qd_id", new BasicDBObject( "$in", qd_ids.toArray()))); orArry.add(new BasicDBObject("_id", new BasicDBObject("$in", recommondIds.toArray()))); query.put("$or", orArry);
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
聚合查詢sum和group by
Map retMap = new HashMap<>(); // $group 分組,newsCount別名,$sum和,$commentSize字段名 String groupStr = "{$group:{_id:null,newsCount:{$sum:1},commentCount:{$sum:\"$commentSize\"},supportCount:{$sum:\"$supportSize\"}}}"; DBObject group = (DBObject) JSON.parse(groupStr); String minTime = (String)params.get("start") + " 00:00:00:000"; String maxTime = (String)params.get("end") + " 00:00:00:000"; BasicDBObject query = new BasicDBObject(); query.put( "release_date", new BasicDBObject("$gte", DateUtil.parseDate( minTime, DateStyle.YYYY_MM_DD_HH_MM_SS_SSS .getValue()))); query.put( "release_date", new BasicDBObject("$lte", DateUtil.parseDate( maxTime, DateStyle.YYYY_MM_DD_HH_MM_SS_SSS .getValue())).append("$gte", DateUtil.parseDate(minTime, DateStyle.YYYY_MM_DD_HH_MM_SS_SSS .getValue()))); DBObject match = new BasicDBObject("$match", query); // 聚合查詢 AggregationOutput output = mongoTemplate.getCollection(collection).aggregate(match,group); for( Iterator< DBObject > it = output.results().iterator(); it.hasNext(); ){ BasicDBObject dbo = ( BasicDBObject ) it.next(); retMap = com.alibaba.fastjson.JSON.parseObject(dbo.toString(), Map.class); } return retMap;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
LBS查詢(附近的人)
if (query == null) query = new BasicDBObject(); List<DBObject> pipeLine = new ArrayList<>(); BasicDBObject pipeBasicDBObject = new BasicDBObject(); pipeBasicDBObject.append("near", new double[] { longitude, latitude }) .append("distanceField", "dist.calculated") .append("spherical", true).append("query", query) .append("distanceMultiplier", 6371); if (qType == 1) { double maxDistance = distance/6371.0000; pipeBasicDBObject.append("maxDistance", maxDistance); } BasicDBObject aggregate = new BasicDBObject("$geoNear", pipeBasicDBObject); BasicDBObject orderObject = new BasicDBObject("$sort", new BasicDBObject().append("dist.calculated", 1)); pipeLine.add(aggregate); pipeLine.add(orderObject); int startNo = (pageNum-1)*pageSize; int limit = pageSize; if(pageNum == 1) { limit = limit+1; } else { startNo = startNo+1; } if (qType == 1) { BasicDBObject skipObject = new BasicDBObject("$skip", startNo); pipeLine.add(skipObject); } BasicDBObject limitObject = new BasicDBObject("$limit", limit); pipeLine.add(limitObject); List<DBObject> list = new LinkedList<>(); try { Cursor cursor = mongoTemplate.getCollection(collection).aggregate( pipeLine, AggregationOptions.builder().build()); while (cursor.hasNext()) { DBObject dBObject = cursor.next(); list.add(dBObject); } } catch (Exception e) { e.printStackTrace(); } return list;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
刪除
DBObject deleAim = new BasicDBObject(); deleAim.put("_id", id); mongoTemplate.getCollection(collection).remove(dbObject)
- 1
- 2
- 3
- 1
- 2
- 3
ps:上面示例不全,只附上了重要的代碼。