2015-07-08 2 views
4

Мне нужно было использовать собственный класс в Scala для ключа в паре ключ/значение. В частности, у меня есть простой класс, который содержит две переменные id1 и id2, и я хочу, чтобы элементы были сгруппированы только на основе id2, а не id1. Я не мог найти какую-либо информацию в Интернете о том, как и где вы можете переопределить метод сравнения для метода reduceByKey(), чтобы он мог группировать элементы с тем же ключом на основе моего настраиваемого метода compare().Spark: метод сравнения пользовательских ключей для reduceByKey

Любая помощь приветствуется. Спасибо.

ответ

0

Не можете ли вы просто mapRDD, чтобы первый элемент пары был ключом, который вы хотите использовать?

case class MyClass(id1: Int, id2: Int) 
val rddToReduce: Rdd[(MyClass, String)] = ... //An RDD with MyClass as key 

rddToReduce.map { 
    case (MyClass(id1, id2), value) => (id2, (id1, value)) //now the key is id2 
} .reduceByKey { 
    case (id1, value) => //do the combination here 
    ... 
} .map { 
    case (id2, (id1, combinedValue)) => 
    (MyClass(id1, id2), combinedValue) //rearrange so that MyClass is the key again 
} 
+0

Что-то, о чем я должен был упомянуть - после сопоставления мне нужен ключ, чтобы оставаться в качестве моего пользовательского объекта, содержащего id1 и id2, потому что, хотя мне нужно, чтобы они были сгруппированы по id2, мне нужно, чтобы id1 оставался на месте, потому что я позже переназначил и перегруппировал значения на основе id1. Я верю, что вы предложили выбросить id1? – Sasha

+0

Я обновил пример, чтобы передать 'id1'. Вы обязательно выбрасываете некоторые 'id1', но подумайте, что произойдет, если у вас есть две записи с тем же' id2', но с разными 'id1' s? Вы можете получить только один элемент (потому что вы их объединяете, так как они имеют одинаковый идентификатор id2), поэтому вы получите только один идентификатор «id1». – lmm

3

Вы не можете переопределить сравнение reduceByKey, потому что он не сможет использовать тот факт, что данные часто перемешиваются с помощью ключа на отдельных исполнителей во всем кластере. Вы можете, хотя изменить ключ (и знать, что в зависимости от преобразований/действий, которые вы используете это, вероятно, перетасовать данные вокруг).

Существует отличный способ в РДУ сделать это называется keyBy, так что вы можете сделать что-то вроде этого:

val data: RDD[MyClass] = ... // Same code you have now. 
val byId2 = data.keyBy(_.id2) //Assuming your ids are Longs, will produce a RDD[(Long,MyClass)] 
+0

Это должно делать именно то, что вы хотите, без каких-либо изменений. –

2

Если вы можете изменить свой класс, то reduceByKey использует equals и hashCode. Таким образом, вы можете убедиться, что они определены, и это приведет к использованию правильных сравнений.

+0

Да, я в состоянии. Спасибо, я постараюсь продолжить это. – Sasha

+0

Не забывайте поднимать и отмечать как ответ, если он работает на вас :) –

+0

Я столкнулся с другой проблемой, которую мне нужно решить, прежде чем вернуться к этому, но я это сделаю! – Sasha

Смежные вопросы