我有一台运行Monogdb的服务器,它也有一个名为mycoll
的集合。新文档将不断插入到集合中。我的目的是拥有一个本地文件,其中包含该集合的所有文档的副本。我目前的做法如下:
String host = "myHost";
int port = 3717;
String user = "user";
String password = "pass";
String databaseName = "dbName";
String collectionName = "mycoll";
MongoCredential credential = MongoCredential.createCredential(user, databaseName, password.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(host, port), Arrays.asList(credential));
MongoDatabase database = mongoClient.getDatabase(databaseName);
MongoCollection<Document> collection = database.getCollection(collectionName);
FindIterable<Document> cursor = collection.find();
String path = "./outputData.txt";
while(cursor.iterator().hasNext()){
try(FileWriter fw = new FileWriter(path, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter out = new PrintWriter(bw))
{
out.println(cursor.iterator().next());
} catch (IOException e) {
System.out.println("Error writing to file.");
}
}
我知道我可以创建一个缓冲区来存储数据并在之后编写它,但是最大的问题仍然没有解决:文档是逐个访问的。因此,我的问题是:我如何一次访问多个文档才能在./outputData.txt
中写入?
答案 0 :(得分:2)
简单来说,只需通过调用MongoCursor
“一次”返回iterator()
,因为这就是您需要做的全部。
然后非常简单地在循环“外部”创建文件句柄。唯一真正属于“循环内部”的是实际的游标迭代和写作。
try {
MongoCursor<Document> cursor = collection.find().iterator();
String path = "./outputData.txt";
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter(path, true))
);
while(cursor.hasNext()){
out.println(cursor.next().toJson());
}
out.flush(); // flush to ensure writes
out.close(); // close the handle when done
} catch (IOException e) {
System.out.println("Error writing to file.");
}
完成游标后,只需关闭返回的文件描述符即可。
您真正需要注意的是,您不“创建”文件描述符或继续在循环内“重新打开”。这是你曾经做过的事情,然后只需通过任何方式“写出”每次迭代。
作为完整列表,您可以在默认端口上针对本地MongoDB运行代码,而无需身份验证。添加选项以根据需要进行更改,但这是所需的“基本”代码
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
public class Application {
public static void main(String[] args) {
PrintWriter out = null;
MongoClient mongoClient = null;
try {
mongoClient = new MongoClient();
MongoDatabase db = mongoClient.getDatabase("test");
MongoCollection<Document> collection = db.getCollection("sample");
out = new PrintWriter(
new BufferedWriter(new FileWriter("output.txt"))
);
// Clear collection and insert data
collection.deleteMany(new Document());
collection.insertMany(Arrays.asList(
new Document("a", 1),
new Document("a", 2),
new Document("a", 3)
));
MongoCursor<Document> cursor = collection.find().iterator();
while ( cursor.hasNext() ) {
out.println(cursor.next().toJson());
//System.out.println(cursor.next().toJson());
}
out.flush();
} catch(Exception e) {
System.out.println(e.getMessage());
} finally {
if (out != null) {
out.close();
}
if (mongoClient != null) {
mongoClient.close();
}
}
}
}
在每次运行时创建一个新文件,并输出插入到集合中的文档。
为您提供如下文件:
{ "_id" : { "$oid" : "5b0bd9576a6bfa1f30e6c320" }, "a" : 1 }
{ "_id" : { "$oid" : "5b0bd9576a6bfa1f30e6c321" }, "a" : 2 }
{ "_id" : { "$oid" : "5b0bd9576a6bfa1f30e6c322" }, "a" : 3 }
答案 1 :(得分:0)
您还可以使用 Spring Integration + MongoDB solution
23.4 MongoDB入站通道适配器
MongoDb入站通道适配器是一个读取的轮询使用者 来自MongoDb的数据并将其作为消息有效负载发送。
<int-mongodb:inbound-channel-adapter id="mongoInboundAdapter" channel="replyChannel" query="{'name' : 'Bob'}" entity-class="java.lang.Object" auto-startup="false"> <int:poller fixed-rate="100"/> </int-mongodb:inbound-channel-adapter>
MongoDB Inbound Channel Adapter
可以连续查询您的MongoDB数据库,然后处理信息以执行您想要执行的操作。
您可以在文档中找到几个示例。
我希望这会对你有所帮助。
答案 2 :(得分:0)
您可以使用.batchsize()批量读取进行优化。 使用游标检索数据时,可以使用 batchSize 子句指定每个操作中获取的行数。
示例:
FindIterable<Document> collection = database.getCollection(collectionName)
.find()
.batchSize(arraySize);
//if you want to read 10 documents at once,
//set arraySize to 10.. so on
for(Document doc : collection) {
// save to file
}
请注意,batchSize运算符实际上并不向程序返回一个数组 - 它只是控制每次网络往返中检索的文档数。从程序的角度来看,这一切都发生在“幕后”。希望这个帮助
您可以在https://docs.mongodb.com/manual/reference/method/cursor.batchSize/
了解有关batchsize的更多信息答案 3 :(得分:0)
我认为,你需要很多触发器。 MongoDB对触发器没有任何支持,但有些人已经推出了自己的&#34;使用一些技巧。这里的关键是oplog。
在副本集中运行MongoDB时,所有MongoDB操作都会记录到操作日志(称为oplog)。 oplog基本上只是对数据所做修改的运行列表。副本通过侦听此oplog上的更改然后在本地应用更改来设置功能。</ p>
您还可以阅读有关tailable游标的信息。
此外,您可以从正在进行的项目中获得相同问题的帮助:
https://github.com/deftlabs/mongo-java-tailable-cursor