最近做的业务是在java层面对hive数据进行迁移到mongo。
在迁移数据的时候需要判断从hive来的数据在mongo是否存在。
如果存在则对已有的数据更新(根据某一字段更新),没有数据则直接添加。
我现在基于java分享相关的方法,拿走即用的代码段。
1、处理RDD
JavaRDD<Row> rdd = dataset.toJavaRDD();
JavaRDD<ReplaceOneModel<Document>> rddUpsert = rdd.map(new Function<Row, ReplaceOneModel<Document>>() {
@Override
public ReplaceOneModel<Document> call(Row v1) {
Document doc = new Document();
StructField[] str = v1.schema().fields();
Object[] values = ((GenericRowWithSchema) v1).values();
for (int i = 0; i < str.length; i++) {
String field = str[i].name();
Object data = values[i];
doc.put(field, data);
}
//fieldName为过滤条件;value为doc字段
return new ReplaceOneModel<Document>(Filters.eq("flag", doc.get("flag")), doc, new ReplaceOptions().upsert(true));
}
});
这部分主要将我们需要更新的数据基于更新字段 进行处理。
其中 Document 很重要,它需要携带我们需要处理的数据。最后根据更新字段走下面的更新逻辑。
2、处理需要更新逻辑
//根据自己情况定义 writeConfig
WriteConfig writeConfig = WriteConfig.create("数据库名", "mongo指定集合", "数据库url", 5, WriteConcern.ACKNOWLEDGED);
DefaultMongoClientFactory factory = new DefaultMongoClientFactory("mongo的url", Option.apply(99));
MongoConnector mongoConnector = new MongoConnector(factory);
ClassTag<Document> tag = ClassManifestFactory.classType(Document.class);
rddUpsert.foreachPartition(iterm -> {
mongoConnector.withCollectionDo(writeConfig, collection -> {
iterm.forEachRemaining(batch -> {
//batc为每一条文档
collection.bulkWrite(Collections.singletonList(batch));
});
return null;
}, tag);
});
3、完整示例代码
JavaRDD<Row> rdd = dataset.toJavaRDD();
JavaRDD<ReplaceOneModel<Document>> rddUpsert = rdd.map(new Function<Row, ReplaceOneModel<Document>>() {
@Override
public ReplaceOneModel<Document> call(Row v1) {
Document doc = new Document();
StructField[] str = v1.schema().fields();
Object[] values = ((GenericRowWithSchema) v1).values();
for (int i = 0; i < str.length; i++) {
String field = str[i].name();
Object data = values[i];
doc.put(field, data);
}
//fieldName为过滤条件;value为doc字段
return new ReplaceOneModel<Document>(Filters.eq("flag", doc.get("flag")), doc, new ReplaceOptions().upsert(true));
}
});
//根据自己情况定义 writeConfig
WriteConfig writeConfig = WriteConfig.create("数据库名", "mongo指定集合", "数据库url", 5, WriteConcern.ACKNOWLEDGED);
DefaultMongoClientFactory factory = new DefaultMongoClientFactory("mongo的url", Option.apply(99));
MongoConnector mongoConnector = new MongoConnector(factory);
ClassTag<Document> tag = ClassManifestFactory.classType(Document.class);
rddUpsert.foreachPartition(iterm -> {
mongoConnector.withCollectionDo(writeConfig, collection -> {
iterm.forEachRemaining(batch -> {
//batc为每一条文档
collection.bulkWrite(Collections.singletonList(batch));
});
return null;
}, tag);
});
本部分将处理完的RDD数据传下来,连接对应的数据库。将传下来的RDD进行处理更新存储。
最后就能达到我们的需求。mongo里面没有数据的时候走添加操作,有数据的时候走更新操作。
ps:可能因为框架原因,可能出现序列化问题。出现的时候,全局进行序列化即可。