Spring 批量 Mongo DB 到 .csv 到电子邮件
Spring Batch Mongo DB to .csv to email
这是我的问题陈述,
-第一步:
调用 mongo 数据库并获取当天的所有文档(基本上是一个请求)。
-第2步:
对于上面的每个文档,对不同的 mongodb 进行另一个调用,最终获取约 70k 个文档。
-第3步:
然后将上述 70k 文档(一些字段)分块处理以创建 .csv 文件。
-第4步:
然后这个 .csv 文件将存储在驱动器中,位置信息将通过电子邮件发送给用户。
-第5步:
对步骤 1 中的每个文档重复步骤 2 到 4。
为了实现这一点,我正在探索 Spring 批处理选项(更乐观的性能)但无法弄清楚该怎么做。任何专业建议/指导都会更有帮助。
谢谢,
据我所知,第 2 步到第 4 步是一个 MongoItemReader(将文档获取到 Mongo),处理一些字段和一个 CSV 项目编写器。所有这三个任务都应该是一个步骤,并且应该 运行 分块。
MongoItemReader 应该是这样的:
@Bean
@StepScope
public MongoItemReader<ReportFiles> reader(MongoTemplate mongoTemplate) {
Criteria expiredFiles = Criteria.where("DateCreated").lte(expiredDate);
HashMap<String, Sort.Direction> sortMap = new HashMap<>();
sortMap.put("ReportFiles", Sort.Direction.DESC);
MongoItemReader<ReportFiles> reader = new MongoItemReader<>();
reader.setTemplate(mongoTemplate);
reader.setSort(sortMap);
reader.setTargetType(ReportFiles.class);
reader.setQuery(Query.query(expiredFiles).getQueryObject().toString());
return reader;
}
处理器对字段做一些事情:
@Override
public Docuement process(Docuement doc) {
// Do some stuff with doc
return doc;
}
和平面 FileitemWriter
@Bean
public FlatFileItemWriter<Document> writer(Resource outputResource)
{
FlatFileItemWriter<Document> writer = new FlatFileItemWriter<>();
writer.setResource(outputResource);
writer.setAppendAllowed(true);
writer.setLineAggregator(new DelimitedLineAggregator<Document>() {
{
setDelimiter(",");
setFieldExtractor(new BeanWrapperFieldExtractor<Document>() {
{
setNames(new String[] { "docID", "docName", "docPath" });
}
});
}
});
return writer;
}
读取过程-写入步骤:
@Bean
public Step step(StepBuilderFactory stepBuilderFactory,
MongoItemReader<Document> reader,
Processors processors,
FlatFileItemWriter<Document> writer
) {
return stepBuilderFactory
.get("MainStep").<Document, Document>chunk(100)
.reader(reader)
.processor(processors)
.writer(writer)
.build();
}
作业的定义应该包括第一步阅读(step 1)
@Bean
public Job job(JobBuilderFactory jobBuilderFactory,
Step readMongoFirstTime,
Step step) {
return jobBuilderFactory
.get(appName)
.start(readMongoFirstTime)
.next(readProcessWriteStep)
.next(emailStep)
.build();
}
根据第一步需要读取的数据量,可以通过作业执行上下文将第一步的信息传递到第二步。但是,如果数据太多,你应该小心。
最后一步需要发送电子邮件。另一件需要注意的事情是创建的文件占用的内存量。
这是我的问题陈述,
-第一步: 调用 mongo 数据库并获取当天的所有文档(基本上是一个请求)。
-第2步: 对于上面的每个文档,对不同的 mongodb 进行另一个调用,最终获取约 70k 个文档。
-第3步: 然后将上述 70k 文档(一些字段)分块处理以创建 .csv 文件。
-第4步: 然后这个 .csv 文件将存储在驱动器中,位置信息将通过电子邮件发送给用户。
-第5步: 对步骤 1 中的每个文档重复步骤 2 到 4。
为了实现这一点,我正在探索 Spring 批处理选项(更乐观的性能)但无法弄清楚该怎么做。任何专业建议/指导都会更有帮助。
谢谢,
据我所知,第 2 步到第 4 步是一个 MongoItemReader(将文档获取到 Mongo),处理一些字段和一个 CSV 项目编写器。所有这三个任务都应该是一个步骤,并且应该 运行 分块。
MongoItemReader 应该是这样的:
@Bean
@StepScope
public MongoItemReader<ReportFiles> reader(MongoTemplate mongoTemplate) {
Criteria expiredFiles = Criteria.where("DateCreated").lte(expiredDate);
HashMap<String, Sort.Direction> sortMap = new HashMap<>();
sortMap.put("ReportFiles", Sort.Direction.DESC);
MongoItemReader<ReportFiles> reader = new MongoItemReader<>();
reader.setTemplate(mongoTemplate);
reader.setSort(sortMap);
reader.setTargetType(ReportFiles.class);
reader.setQuery(Query.query(expiredFiles).getQueryObject().toString());
return reader;
}
处理器对字段做一些事情:
@Override
public Docuement process(Docuement doc) {
// Do some stuff with doc
return doc;
}
和平面 FileitemWriter
@Bean
public FlatFileItemWriter<Document> writer(Resource outputResource)
{
FlatFileItemWriter<Document> writer = new FlatFileItemWriter<>();
writer.setResource(outputResource);
writer.setAppendAllowed(true);
writer.setLineAggregator(new DelimitedLineAggregator<Document>() {
{
setDelimiter(",");
setFieldExtractor(new BeanWrapperFieldExtractor<Document>() {
{
setNames(new String[] { "docID", "docName", "docPath" });
}
});
}
});
return writer;
}
读取过程-写入步骤:
@Bean
public Step step(StepBuilderFactory stepBuilderFactory,
MongoItemReader<Document> reader,
Processors processors,
FlatFileItemWriter<Document> writer
) {
return stepBuilderFactory
.get("MainStep").<Document, Document>chunk(100)
.reader(reader)
.processor(processors)
.writer(writer)
.build();
}
作业的定义应该包括第一步阅读(step 1)
@Bean
public Job job(JobBuilderFactory jobBuilderFactory,
Step readMongoFirstTime,
Step step) {
return jobBuilderFactory
.get(appName)
.start(readMongoFirstTime)
.next(readProcessWriteStep)
.next(emailStep)
.build();
}
根据第一步需要读取的数据量,可以通过作业执行上下文将第一步的信息传递到第二步。但是,如果数据太多,你应该小心。
最后一步需要发送电子邮件。另一件需要注意的事情是创建的文件占用的内存量。