Spring MVC中使用Mongodb總結

近期項目做了次架構調整,原來是使用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

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

配置文件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

集羣配置 
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

配置文件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

其他配置

<!-- 用戶驗證 -->
    <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

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

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

更新 
普通更新

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

數組更新

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

查詢 
單條查詢

DBObject query = new BasicDBObject("_id", id);
DBObject fields = new BasicDBObject();
mongoTemplate.getCollection(collection).findOne(query, fields)
  • 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

範圍查詢

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

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

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

聚合查詢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

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

刪除

DBObject deleAim = new BasicDBObject();
deleAim.put("_id", id);
mongoTemplate.getCollection(collection).remove(dbObject)
  • 1
  • 2
  • 3

ps:上面示例不全,只附上了重要的代碼。

至此,總共介紹了常用查詢,聚合查詢,刪除,保存,geo查詢等方法。

個人技術分享微信公衆號,歡迎關注一起交流 


轉自:http://blog.csdn.net/JaCman/article/details/49814383

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章