使用Mongo-Hadoop连接器通过Apache Spark更新MongoDb中的集合

时间:2014-10-23 11:04:58

标签: java mongodb apache-spark rdd

我想通过Spark in Java更新MongoDb中的特定集合。 我使用MongoDB Connector for Hadoop检索并将Apache Spark中的信息保存到Java中的MongoDb。

在关注Sampo Niskanen的优秀post regarding retrieving and saving collections to MongoDb via Spark,后,我对更新集合感到困惑。

MongoOutputFormat.java包含一个构造函数,它使用String [] updateKeys,我猜这是指一个可能的键列表,用于比较现有集合并执行更新。但是,使用Spark的saveAsNewApiHadoopFile()方法和参数MongoOutputFormat.class,我想知道如何使用该更新构造函数。

save.saveAsNewAPIHadoopFile("file:///bogus", Object.class, Object.class, MongoOutputFormat.class, config);

在此之前,MongoUpdateWritable.java被用于执行集合更新。从我在Hadoop上看到的例子来看,这通常设置在mongo.job.output.value上,在Spark中可能是这样的:

save.saveAsNewAPIHadoopFile("file:///bogus", Object.class, MongoUpdateWritable.class, MongoOutputFormat.class, config);

但是,我仍然想知道如何在MongoUpdateWritable.java中指定更新密钥。

不可否认,作为一种hacky方式,我将对象的“_id”设置为我的文档的KeyValue,以便在执行保存时,集合将覆盖具有与_id相同的KeyValue的文档。

JavaPairRDD<BSONObject,?> analyticsResult; //JavaPairRdd of (mongoObject,result)
JavaPairRDD<Object, BSONObject> save = analyticsResult.mapToPair(s -> {
    BSONObject o = (BSONObject) s._1;

    //for all keys, set _id to key:value_
    String id = "";
    for (String key : o.keySet()){
        id += key + ":" + (String) o.get(key) + "_";
    }
    o.put("_id", id);

    o.put("result", s._2);
    return new Tuple2<>(null, o);
});

save.saveAsNewAPIHadoopFile("file:///bogus", Object.class, Object.class, MongoOutputFormat.class, config);

我想使用MongoOutputFormatMongoUpdateWritableConfiguration通过Spark执行mongodb集合更新,最好使用saveAsNewAPIHadoopFile()方法。可能吗?如果没有,有没有其他方法不涉及专门设置_id到我想要更新的键值?

1 个答案:

答案 0 :(得分:7)

我尝试了几种config.set("mongo.job.output.value","....")和几种

的组合
.saveAsNewAPIHadoopFile(
        "file:///bogus",
        classOf[Any],
        classOf[Any],
        classOf[com.mongodb.hadoop.MongoOutputFormat[Any, Any]],
        mongo_config
      )

并且没有一个工作。

我使用MongoUpdateWritable类作为我的map方法的输出来使其工作:

items.map(row => {
      val mongo_id = new ObjectId(row("id").toString)
      val query = new BasicBSONObject()
      query.append("_id", mongo_id)
      val update = new BasicBSONObject()

      update.append("$set", new BasicBSONObject().append("field_name", row("new_value")))
      val muw = new MongoUpdateWritable(query,update,false,true)
      (null, muw)
    })
     .saveAsNewAPIHadoopFile(
       "file:///bogus",
       classOf[Any],
       classOf[Any],
       classOf[com.mongodb.hadoop.MongoOutputFormat[Any, Any]],
       mongo_config
     )

在mongo中执行的原始查询是这样的:

2014-11-09T13:32:11.609-0800 [conn438] update db.users query: { _id: ObjectId('5436edd3e4b051de6a505af9') } update: { $set: { value: 10 } } nMatched:1 nModified:0 keyUpdates:0 numYields:0 locks(micros) w:24 3ms