配色: 字号:
MongoDB Java异步驱动快速指南
2016-11-11 | 阅:  转:  |  分享 
  
MongoDBJava异步驱动快速指南

执行异步回调

创建一个连接

MongoClient

获得一个collection

添加一个document

添加多个document

统计一个collection的document数量

查询collection

在一个collection中找到第一个document

遍历查找一个collection中所有的document

通过查询条件获得一个document

通过查询获得一组documents

document排序

投射域

聚合

更新document

删除document

批量操作

回到顶部

导读



mongodb-java-driver是mongodb的Java驱动项目。



本文是对MongoDB-java-driver官方文档MongoDBAsyncDriverQuickTour的翻译(原创翻译)。



mongodb-java-driver从3.0版本开始同时支持同步、异步方式(分别是不同的驱动应用)。异步的好处,众所周知,就是支持快速、非阻塞式的IO操作,可以提高处理速度。



请注意:本文仅介绍异步驱动的使用指南。同步驱动官方文档:mongo-java-driver,需要了解的朋友,请移驾。



回到顶部

安装



简单提下安装说明。



注:MongoDB异步驱动需要依赖Netty或Java7。



如果你的项目是maven项目,只需在pom.xml中添加如下依赖:







org.mongodb

mongodb-driver-async

3.3.0





你也可以点击链接直接下载jar包:下载点这里。



分割线,下面是MongoDBAsyncDriverQuickTour的译文。



回到顶部

MongoDB异步驱动快速指南



以下的代码片段来自于asyncdriversource的范例代码QuickTour.java。



注意



如何安装MongoDB异步驱动请参考安装指导。



执行异步回调



MongoDB异步驱动利用Netty或Java7的AsynchronousSocketChannel来提供一个支持异步的API,以支持快速的、非阻塞式的IO操作。



该API形式和MongoDB同步驱动的新API保持一致,但是任何会导致网络IO的方法都会有一个SingleResponseCallback并且会立即返回,其中T是响应对于该文档的类型的任何方法。



SingleResponseCallback回调接口需要实现一个简单方法onResult(Tresult,Throwablet),这个方法在操作完成时被调用。其中,如果操作成功,result参数包含着操作结果;如果操作失败,t中包含着抛出的异常信息。



重要



在SingleResponseCallback的实现中检查错误并适当处理错误是十分重要的。下面的错误检查仅为简便起见而省略。



创建一个连接



下面的例子展示多种方法去链接本地机器上的mydb数据库。详情参考MongoClients.createAPI手册。



//直接连接默认服务host和端口,即localhost:27017

MongoClientmongoClient=MongoClients.create();



//使用一个字符串

MongoClientmongoClient=MongoClients.create("mongodb://localhost");



//使用一个ConnectionString

MongoClientmongoClient=MongoClients.create(newConnectionString("mongodb://localhost"));





//使用MongoClientSettings

ClusterSettingsclusterSettings=ClusterSettings.builder().hosts(asList(newServerAddress("localhost"))).build();

MongoClientSettingssettings=MongoClientSettings.builder().clusterSettings(clusterSettings).build();

MongoClientmongoClient=Mongowww.wang027.comClients.create(settings);



MongoDatabasedatabase=mongoClient.getDatabase("mydb");

此时,database对象是一个MongoDB服务器中指定数据库的连接。



注意



getDatabase("mydb")方法并没有回调,因为它没有涉及网络IO操作。一个MongoDatabase实例提供了与数据库进行交互的方法,若数据库不存在,它会在插入数据时创建一个新的数据库。例如,创建一个collection或插入document(这些确实需要回调,因为需要涉及网络IO)。



MongoClient



MongoClient实例实际上代表了一个数据库的连接池;即使要并发执行异步操作,你也仅仅需要一个MongoClient实例。



重要



一般情况下,在一个指定的数据库集群中仅需要创建一个MongoClient实例,并通过你的应用使用它。



当创建多个实例时:



所有的资源使用限制(例如最大连接数)适用于每个MongoClient实例

销毁实例时,请确保调用MongoClient.close()清理资源。

获得一个collection



要获得一个collection,你需要在getCollection(StringcollectionName)方法中指定collection的名字:



下面的例子获得名为test的collection:



MongoCollectioncollection=database.getCollection("test");

添加一个document



一旦你有了collection对象,你就可以向collection中插入document。例如,考虑如下的json形式document;document中含包含了一个名为info的子document。



{

"name":"MongoDB",

"type":"database",

"count":1,

"info":{

x:203,

y:102

}

}

要创建document,需要使用Document类。你可以使用这个类来创建嵌入式的document。



Documentdoc=newDocument("name","MongoDB")

.append("type","database")

.append("count",1)

.append("info",newDocument("x",203).append("y",102));

要向collection中插入document,需要使用insertOne()方法。



collection.insertOne(doc,newSingleResultCallback(){

@Override

publicvoidonResult(finalVoidresult,finalThrowablet){

System.out.println("Inserted!");

}

});

SingleResponseCallback是一个函数式接口并且它可以以lambda方式实现(前提是你的APP工作在JDK8):



collection.insertOne(doc,(Voidresult,finalThrowablet)->System.out.println("Inserted!"));

一旦document成功插入,onResult回调方法会被调用并打印“Inserted!”。记住,在一个普通应用中,你应该总是检查t变量中是否有错误信息。



添加多个document



要添加多个documents,你可以使用insertMany()方法。



接下来的例子会添多个document,document形式如下:



{"i":value}

循环创建多个documents。



Listdocuments=newArrayList();

for(inti=0;i<100;i++){

documents.add(newDocument("i",i));

}

要插入多个document到collection,传递documents列表到insertMany()方法.



collection.insertMany(documents,newSingleResultCallback(){

@Override

publicvoidonResult(finalVoidresult,finalThrowablet){

System.out.println("Documentsinserted!");

}

});

统计一个collection的document数量



既然前面的多个例子中我们已经插入了101个document,我们可以检查一下插入数量,使用count()方法。下面的代码应该打印101。



collection.count(

newSingleResultCallback(){

@Override

publicvoidonResult(finalLongcount,finalThrowablet){

System.out.println(count);

}

});

查询collection



使用find()方法来查询collection。



在一个collection中找到第一个document



要获得collection中的第一个document,需要调用first()方法。collection.find().first()返回第一个document或null值,而不是一个游标。这种查询适用于匹配一个单一的document,,或你仅对第一个document有兴趣。



注意



有时你需要多次使用相同或相似的回调方法。在这种情况下,合理的做法是DRY(不要重复自己):把回调保存为一个具体的类或分配给一个变量。



SingleResultCallbackprintDocument=newSingleResultCallback(){

@Override

publicvoidonResult(finalDocumentdocument,finalThrowablet){

System.out.println(document.toJson());

}

};

下面的例子传递printDocument回调给first方法:



collection.find().first(printDocument);

范例会打印下面的document:



{"_id":{"$oid":"551582c558c7b4fbacf16735"},

"name":"MongoDB","type":"database","count":1,

"info":{"x":203,"y":102}}

注意



_id元素会被MongoDB动态的添加到你的document上,并且值也会与展示的不同。“_”和“$”开头的域是MongoDB预留给内部使用的。



遍历查找一个collection中所有的document



要检索collection中所有的document,需要使用find()方法。find()方法返回一个FindIterable实例,它提供了一个接口来链接和控制查找操作。使用forEach()方法可以提供一个Block作用于每个document并且迭代结束时执行回调一次。下面的代码遍历collection中所有的document并逐一打印,最后打印“OperationFinished!”。



BlockprintDocumentBlock=newBlock(){

@Override

publicvoidapply(finalDocumentdocument){

System.out.println(document.toJson());

}

};

SingleResultCallbackcallbackWhenFinished=newSingleResultCallback(){

@Override

publicvoidonResult(finalVoidresult,finalThrowablet){

System.out.println("OperationFinished!");

}

};



collection.find().forEach(printDocumentBlock,callbackWhenFinished);

通过查询条件获得一个document



我们可以创建一个过滤器传递给find()方法,以获得我们collection中的一组子集。例如,如果我们想查找key为“i”,value为71的document,我们要按下面的方法做(重用printDocument回调)。



importstaticcom.mongodb.client.model.Filters.;



collection.find(eq("i",71)).first(printDocument);

最终会只印一个document:



{"_id":{"$oid":"5515836e58c7b4fbc756320b"},"i":71}

重要



请使用Filters、Sorts、Projections和UpdatesAPI手册来找到简单、清晰的方法构建查询。



通过查询获得一组documents



我们可以使用查询来从我们的collection中获得一组document集合。例如,如果我们想获得所有key为“i”,value大于50的document,我们应该按下面方式做(重用printDocumentBlock阻塞和callbackWhenFinished回调):



//使用范围查询获取子集

collection.find(gt("i",50)).forEach(printDocumentBlock,callbackWhenFinished);

范例应该会打印所有i>50的document。



我们也可以增加上限范围,如50


collection.find(and(gt("i",50),lte("i",100))).forEach(printDocumentBlock,callbackWhenFinished);

document排序



我们可以对document进行排序。通过在FindIterable上调用sort()方法,我们可以在一个查询上进行一次排序。



下面的例子中,我们使用exists()和降序排序descending("i")来为我们的document排序。



collection.find(exists("i")).sort(descending("i")).first(printDocument);

投射域



有时我们不需要将所有的数据都存在一个document中。Projections可以用来为查询操作构建投射参数并限制返回的字段。



下面的例子中,我们会对collection进行排序,排除_id字段,并输出第一个匹配的document。



collection.find().projection(excludeId()).first(printDocument);

聚合



有时,我们需要将存储在MongoDB中的数据聚合。Aggregates支持对每种类型的聚合阶段进行构建。



下面的例子,我们执行一个两步骤的转换来计算i10的值。首先我们使用Aggregates.match查找所有i>0的document。接着,我们使用Aggregates.project结合$multiply操作来计算“ITimes10”的值。



collection.aggregate(asList(

match(gt("i",0)),

project(Document.parse("{ITimes10:{$multiply:[''$i'',10]}}")))

).forEach(printDocumentBlock,callbackwww.baiyuewang.netWhenFinished);

For$groupoperationsusetheAccumulatorshelperforanyaccumulatoroperations.



对于$group操作使用Accumulators来处理任何累加操作。



下面的例子中,我们使用Aggregates.group结合Accumulators.sum来累加所有i的和。



collection.aggregate(singletonList(group(null,sum("total","$i")))).first(printDocument);

注意



当前,还没有专门用于聚合表达式的工具类。可以使用Document.parse()来快速构建来自于JSON的聚合表达式。



更新document



MongoDB支持许多的更新操作。



要更新至多一个document(可能没有匹配的document),使用updateOne方法指定过滤器并更新document。这里,我们使用Updates.set来更新匹配过滤器i等于10的第一个document并设置i的值为110。



collection.updateOne(eq("i",10),set("i",110),

newSingleResultCallback(){

@Override

publicvoidonResult(finalUpdateResultresult,finalThrowablet){

System.out.println(result.getModifiedCount());

}

});

使用updateMany方法可以更新所有匹配过滤器的document。这里我们使用Updates.inc来为所有i小于100的document增加100。



collection.updateMany(lt("i",100),inc("i",100),

newSingleResultCallback(){

@Override

publicvoidonResult(finalUpdateResultresult,finalThrowablet){

System.out.println(result.getModifiedCount());

}

});

更新方法返回一个UpdateResult,其中包含了操作的信息(被修改的document的数量)。



删除document



要删除至多一个document(可能没有匹配的document)可以使用deleteOne方法。



collection.deleteOne(eq("i",110),newSingleResultCallback(){

@Override

publicvoidonResult(finalDeleteResultresult,finalThrowablet){

System.out.println(result.getDeletedCount());

}

});

使用deleteMany方法可以删除所有匹配过滤器的document。这里我们删除所有i大于等于的document。



collection.deleteMany(gte("i",100),newSingleResultCallback(){

@Override

publicvoidonResult(finalDeleteResultresult,finalThrowablet){

System.out.println(result.getDeletedCount());

}

});

删除方法返回一个DeleteResult,其中包含了操作的信息(被删除的document的数量)。



批量操作



批量操作允许批量的执行插入、更新、删除操作。批量操作有两种类型:



有序的批量操作

有序的执行所有操作并在第一个写操作的错误处报告错误。



无序的批量操作

执行所有的操作并报告任何错误。



无序的批量操作不保证执行顺序。



我们来围观一下两个分别使用有序和无序操作的简单例子:



SingleResultCallbackprintBatchResult=newSingleResultCallback(){

@Override

publicvoidonResult(finalBulkWriteResultresult,finalThrowablet){

System.out.println(result);

}

};



//2.有序批量操作

collection.bulkWrite(

Arrays.asList(newInsertOneModel<>(newDocument("_id",4)),

newInsertOneModel<>(newDocument("_id",5)),

newInsertOneModel<>(newDocument("_id",6)),

newUpdateOneModel<>(newDocument("_id",1),

newDocument("$set",newDocument("x",2))),

newDeleteOneModel<>(newDocument("_id",2)),

newReplaceOneModel<>(newDocument("_id",3),

newDocument("_id",3).append("x",4))),

printBatchResult

);





//2.无序批量操作

collection.bulkWrite(

Arrays.asList(newInsertOneModel<>(newDocument("_id",4)),

newInsertOneModel<>(newDocument("_id",5)),

newInsertOneModel<>(newDocument("_id",6)),

newUpdateOneModel<>(newDocument("_id",1),

newDocument("$set",newDocument("x",2))),

newDeleteOneModel<>(newDocument("_id",2)),

newReplaceOneModel<>(newDocument("_id",3),

newDocument("_id",3).append("x",4))),

newBulkWriteOptions().ordered(false),

printBatchResult

);

重要



不推荐在pre-2.6的MongoDB服务器上使用bulkWrite方法。因为这是第一个支持批量写操作(插入、更新、删除)的服务器版本,它允许驱动去实现BulkWriteResult和BulkWriteException的语义。这个方法虽然仍然可以在pre-2.6服务器上工作,但是性能不好,一次只能执行一个写操作。

献花(0)
+1
(本文系thedust79首藏)