1、Jongo可以用來做什麼?
Jongo框架的目的是使在MongoDB中可以直接使用的查詢Shell可以直接在Java中使用。在官網首頁有一個非常簡潔的例子:
SHELL:這種查詢方式是MongoDB數據庫支持的查詢方式。
JAVA DRIVER:是MongoDB Java驅動API中提供的查詢方式
JONGO:就是jongo框架提供的查詢方式。
由此可以看出,JONGO框架的意圖很明顯。
2、Jongo的下載
在Jongo的官網上,介紹說jongo框架的使用依賴於 Jackson 2.2.3, Bson4Jackson 2.2.3 and Mongo Java Driver 2.11+,而jongo目前最新的版本爲1.0。通過我的嘗試,我發現在實際應用中需要用到以下jar包:
bson4jackson-2.3.1.jar
jackson-annotations-2.4.1.jar
jackson-core-2.4.1.1.jar
jackson-databind-2.4.1.2.jar
jongo-1.0.jar
mongo-java-driver-2.12.2.jar
3、Jongo的使用
PersonInfo類:
1 package com.jongo.enties;
2
3 public class PersonInfo {
4
5 private int id;
6 private String person_name;
7 private String sex;
8 private String relationship;
9
10 public PersonInfo() {
11
12 }
13 //getter and setter
14 @Override
15 public String toString() {
16 return "PersonInfo [id=" + id + ", person_name=" + person_name
17 + ", sex=" + sex + ", relationship=" + relationship + "]";
18 }
19 }
1)第一個簡單的例子
package com.jongo.demo;
import java.util.Iterator;
import org.jongo.Jongo;
import org.jongo.MongoCollection;
import com.jongo.enties.PersonInfo;
import com.mongodb.DB;
import com.mongodb.MongoClient;
public class FirstDemo {
public static void main(String[] args) {
MongoClient mongo = null;
try {
mongo = new MongoClient("localhost",27017);
DB db = mongo.getDB("jongo");
Jongo jongo = new Jongo(db);
MongoCollection person_info = jongo.getCollection("person_info");
@SuppressWarnings("unchecked")
Iterator<PersonInfo> all = (Iterator<PersonInfo>) person_info.find().as(PersonInfo.class);
while(all.hasNext()) {
PersonInfo personInfo = all.next();
System.out.println("all:"+personInfo);
}
PersonInfo one = (PersonInfo) person_info.findOne("{id:1}").as(PersonInfo.class);
System.out.println("one:"+one);
} catch(Exception e) {
e.printStackTrace();
} finally {
if(mongo != null) {
mongo.close();
}
}
}
}
運行結果:
all:PersonInfo [id=1, person_name=xiaoming, sex=Man, relationship=Friend]
all:PersonInfo [id=2, person_name=xiaohong, sex=Male, relationship=Friend]
one:PersonInfo [id=1, person_name=xiaoming, sex=Man, relationship=Friend]
2)Jongo的Save
PersonInfo personInfo = new PersonInfo(4,"Marry","Male","ClassMate");
mcoll.save(personInfo);
3)Jongo的Update
在Jongo中,Update語法和Mongo Shell有一點點不同,修改的查詢語句需要通過使用with()來實現,with()內可以包含一個字符串,或者是一個對象。
(1)person_info.update(new ObjectId("53cb7d99b963ac657273328c")).with("{$inc: {id: 2}}");
原始記錄:{ "_id" : ObjectId("53cb7d99b963ac657273328c"), "id" : 6, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate" }
更新後:{ "_id" : ObjectId("53cb7d99b963ac657273328c"), "id" : 8, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate" }
(2)person_info.update("{person_name : 'Dark'}").with("{$set:{person_name:'Dark Update'}}");
原始記錄:{ "_id" : ObjectId("53cb7d91b963ac657273328a"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate" }
更新後:{ "_id" : ObjectId("53cb7d91b963ac657273328a"), "id" : 5, "person_name" : "Dark Update", "sex" : "Male", "relationship" : "ClassMate" }
這種Update方式只會改變第一個被找到的記錄。而下面這種方式將會更新所有person_name爲Dark的記錄:
person_info.update("{person_name : 'Dark'}").multi().with("{$set:{person_name:'Dark Update'}}");
(3)person_info.update("{person_name : 'Dark'}").with(new PersonInfo(10, "Dark Update Object", "Man", "ClassMate"));
原始記錄:{ "_id" : ObjectId("53cb82ebb963ac657273329d"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate" }
更新後:{ "_id" : ObjectId("53cb82ebb963ac657273329d"), "id" : 10, "person_name" : "Dark Update Object", "sex" : "Man", "relationship" : "ClassMate" }
(4)person_info.update("{person_name : 'Dark'}").with("{$set:{address:#}}",new Address("0755","shenzhen"));
原始記錄:{ "_id" : ObjectId("53cb8310b963ac657273329e"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate" }
更新後:{ "_id" : ObjectId("53cb8310b963ac657273329e"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate", "address" : { "regionI d" : "0755", "provinceName" : "shenzhen" } }
4)Jongo的Insert
(1)person_info.insert("{person_name:'Insert Demo'}");
結果:{ "_id" : ObjectId("53cb85cf2fd87f4058d1ff93"), "person_name" : "Insert Demo" }
(2)插入一條記錄
PersonInfo personInfo = new PersonInfo(6,"Marry Insert","Male","ClassMate");
person_info.insert(personInfo);
結果:{ "_id" : ObjectId("53cb85e0b963ac65727332a3"), "id" : 6, "person_name" : "Marry Insert", "sex" : "Male", "relationship" : "ClassMate" }
(3)插入多條記錄:
PersonInfo personInfo2 = new PersonInfo(7,"Marry Insert2","Male","ClassMate");
person_info.insert(personInfo,personInfo2); //方式一
person_info.insert(new Object[]{personInfo,personInfo2});//方式二
5)Jongo的Remove
person_info.remove(); //刪除所有
person_info.remove(new ObjectId("53cb87c02fd8f9ffd258ceb3"));
person_info.remove("{person_name:'Marry Insert'}");
6)Jongo的Query
在Jongo中,Query和Mongo Shell中的Query幾乎是一致的。
我們先來看看在Mongo Shell中如何查詢:
原始記錄:{ "_id" : ObjectId("53cb8e8a2602b31118434306"), "id" : 2, "person_name" : "xiaohong", "sex" : "Male", "relationship" : "Friend" }
//對於數字類型
> db.person_info.find({id:2});
或者> db.person_info.find({"id":2});
{ "_id" : ObjectId("53cb8e8a2602b31118434306"), "id" : 2, "person_name" : "xiaohong", "sex" : "Male", "relationship" : "Friend" }
//對於字符串類型
> db.person_info.find({person_name:'xiaohong'});
或者> db.person_info.find({"person_name":"xiaohong"});
{ "_id" : ObjectId("53cb8e8a2602b31118434306"), "id" : 2, "person_name" : "xiaohong", "sex" : "Male", "relationship" : "Friend" }
那麼,在Jongo中怎麼查詢呢?其實,在上面的第一個簡單例子中我們已經見識過了,
Iterator<PersonInfo> all = (Iterator<PersonInfo>) person_info.find().as(PersonInfo.class);
PersonInfo one = (PersonInfo) person_info.findOne("{id:1}").as(PersonInfo.class);
我們再來看看這種文檔結構:{ "_id" : ObjectId("53cb9015b963ac65727332a4"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate", "address" : { "regionI
d" : "0755", "provinceName" : "shenzhen" } },假如我要查詢出address中regionId爲0755的記錄,該怎麼做?
在Mongo Shell中,我們是這樣查詢的:db.person_info.find({"address.regionId":"0755"});或者db.person_info.find({'address.regionId':'0755'});
在Jongo中的做法也是如出一轍,
PersonInfo personInfo = (PersonInfo) person_info.findOne("{address.regionId:'0755'}").as(PersonInfo.class);
7)Jongo如何查詢出指定字段(不查詢某字段)?
我們一般通過{field:1}或{field:0}來控制查詢字段的顯示與否。
在Mongo Shell中,做法如下:
> db.person_info.find({},{person_name:1,_id:0}); //查詢出person_name,不查詢出_id。
{ "person_name" : "xiaohong" }
{ "person_name" : "Dark" }
而在Jongo中我們需要使用projection來到達這種效果。
PersonInfo personInfo =
(PersonInfo) person_info.findOne().projection("{person_name:1,id:1}").as(PersonInfo.class);
8)Jongo的Sort、Skip、Limit、Hint、Count
在Jongo中Sort、Skip、Limit、Hint、Count基本和Mongo Shell一致。
假設數據集合中有這樣兩天記錄:
> db.person_info.find()
{ "_id" : ObjectId("53cb8e8a2602b31118434306"), "id" : 2, "person_name" : "xiaohong", "sex" : "Male", "relationship" : "Friend" }
{ "_id" : ObjectId("53cb9015b963ac65727332a4"), "id" : 5, "person_name" : "Dark", "sex" : "Male", "relationship" : "ClassMate", "address" : { "regionI
d" : "0755", "provinceName" : "shenzhen" } }
Iterator<PersonInfo> sort = (Iterator<PersonInfo>) person_info.find().sort("{id:1}").as(PersonInfo.class);//sort {field:1} 升序,{field:-1} 降序
Iterator<PersonInfo> skip = (Iterator<PersonInfo>) person_info.find().skip(1).as(PersonInfo.class);//查詢時跳過多少條記錄
Iterator<PersonInfo> limit = (Iterator<PersonInfo>) person_info.find().limit(2).as(PersonInfo.class);//查詢指定數量的記錄
Iterator<PersonInfo> hint = (Iterator<PersonInfo>) person_info.find().hint("{person_name:-1}").as(PersonInfo.class);//在查詢過程中強制使用hint指定的索引方式,注意必須事先建立person_name字段的倒序索引。
long len = person_info.count("{id:5}");//查詢滿足條件的記錄數
9)Jongo的Oid
在映射部分,_id的定義可有註解@ObjectId來控制,如果你想完全地避免使用原先驅動包的ObjectId,可以使用Jongo提供的Oid類。其用法如下:
import static org.jongo.Oid.withOid;
PersonInfo personInfo= new PersonInfo(); // @ObjectId String _id PersonInfo類中需要定義一個名爲_id的字段,且加上@ObjectId註解
person_info.save(personInfo);
person_info.find(withOid(personInfo._id)).as(PersonInfo .class); // instead of new ObjectId(personInfo._id)
10)Jongo的查詢模板
幾乎所有查詢Jongo可以模板化:添加錨#。綁定參數可以BSON原語或任何複雜類型。
PersonInfo personInfo = person_info.findOne("{id:#,person_name:#}",2,"xiaohong").as(PersonInfo.class); //相當於findOne("{id:2,person_name:'xiaohong'}")
PersonInfo personInfo2 = person_info.findOne("{address:#}",new Address("0755","shenzhen")).as(PersonInfo.class); //相當於 db.person_info.findOne({'address.regionId':'0755','address.privinceName':'shenzhen'});
Iterator<PersonInfo> ite = (Iterator<PersonInfo>) person_info.find("{id:{$in:#}}",ids).as(PersonInfo.class); //相當於db.person_info.find({id:{$in:[2,5]}});
11)Jongo的正則查詢
以下幾種正則查詢都是等價的:
PersonInfo personInfo1 =
person_info.findOne("{person_name:{$regex:#}}","Dar.*").as(PersonInfo.class);
PersonInfo personInfo2 =
person_info.findOne("{person_name:{$regex:'Dar.*'}}").as(PersonInfo.class);
PersonInfo personInfo3 =
person_info.findOne("{person_name:#}",Pattern.compile("Dar.*")).as(PersonInfo.class);
Pattern p = Pattern.compile("Dar.*");
PersonInfo personInfo4 =
person_info.findOne("{person_name:{$regex:'"+p+"'}}").as(PersonInfo.class);
12)Jongo的聚合操作
(1)Distinct
List<String> personNames = person_info.distinct("person_name").as(String.class);
List<Address> addresses = person_info.distinct("address").query("{id:5}").as(Address.class);
int size = person_info.distinct("address").query("{id:5}").as(Address.class).size();
(2)聚合框架
這個特性只能在Mongo2.2以上版本中使用,所有諸如$project, $match, $limit, $skip, $unwind, $group, $sort的聚合操作都支持。在官網有一個例子:
collection.aggregate("{$project:{sender:1}}")
.and("{$match:{tags:'read'}}")
.and("{$limit:10}")
.as(Email.class);
4、對象映射
查詢結果自動映射到對象,它依賴於Jackson,涉及文檔結構,處理列表以及忽略缺失的屬性。僅僅需要一個無參構造器(甚至私有構造器都行,前提是對象是不可變的,註解@JsonCreator可以用來替代)
_id在每個MongoDB文檔中是一個唯一的標識符,如果沒有被設定,它將自動生成,用Jongo來定義它時,一個屬性需要被命名爲_id或者帶有@Id註解(別名 @JsonProperty("_id")),可以使用專門的ObjectId類或者一個簡單的由@ObjectId註解的簡單字符串來定義。
需要注意的是,當你保存一個自定義的文檔_id時(任何Java類型,除了數組意外,只要它是唯一值)總是需要在持久化之前手動的去進行設置。
以下幾種情形式需要手動設置_id的:
而下面這幾種是自動生成的: