JAVA中Spark迁移数据-hive到mongoDB(没数据添加有数据则更新)

最近做的业务是在java层面对hive数据进行迁移到mongo。
在迁移数据的时候需要判断从hive来的数据在mongo是否存在。
如果存在则对已有的数据更新(根据某一字段更新),没有数据则直接添加。
我现在基于java分享相关的方法,拿走即用的代码段。

1、处理RDD

JavaRDD rdd = dataset.toJavaRDD();
        JavaRDD> rddUpsert = rdd.map(new Function>() {
            @Override
            public ReplaceOneModel 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(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 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 rdd = dataset.toJavaRDD();
        JavaRDD> rddUpsert = rdd.map(new Function>() {
            @Override
            public ReplaceOneModel 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(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 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:可能因为框架原因,可能出现序列化问题。出现的时候,全局进行序列化即可。

你可能感兴趣的:(工具整理,大数据,hive,spark,hadoop)