我在使用Apache Spark中针对一组规则过滤记录时遇到的一个用例中需要帮助。
例如,由于实际数据的字段太多,您可以考虑下面的数据(为简单起见,以JSON格式提供数据),
records : [{
"recordId": 1,
"messages": [{"name": "Tom","city": "Mumbai"},
{"name": "Jhon","address": "Chicago"}, .....]
},....]
rules : [{
ruleId: 1,
ruleName: "rule1",
criterias: {
name: "xyz",
address: "Chicago, Boston"
}
}, ....]
我想根据所有规则匹配所有记录。这是伪代码:
var matchedRecords = []
for(record <- records)
for(rule <- rules)
for(message <- record.message)
if(!isMatch(message, rule.criterias))
break;
if(allMessagesMatched) // If loop completed without break
matchedRecords.put((record.id, ruleId))
def isMatch(message, criteria) =
for(each field in crieteria)
if(field.value contains comma)
if(! message.field containsAny field.value)
return false
else if(!message.field equals field.value) // value doesnt contain comma
return false
return true // if loop completed that means all criterias are matched
有成千上万的记录包含数千条消息,并且有这些规则的内容。
解决此类问题的方法有哪些?任何特定的模块都会有用(SparkSQL,Spark Mlib,Spark GraphX)?我是否需要使用任何第三方lib?
方法1:
列出[规则]&amp; RDD [记录]
广播列表[规则],因为它们的数量较少。
将每条记录与所有规则匹配。
仍然在这种情况下,没有发生用于将每条消息与标准匹配的并行计算。
答案 0 :(得分:0)
我认为您建议的方法是好的方向。如果我必须解决这个任务,我将从实现通用特征开始,该方法负责匹配:
trait FilterRule extends Serializable {
def match(record: Record): Boolean
}
然后我会实现特定的过滤器,例如:
class EqualsRule extends FilterRule
class RegexRule extends FilterRule
然后我会实现复合过滤器,例如:
class AndRule extends FilterRule
class OrRule extends FilterRule
...
然后你可以用:
过滤你的rdd或DataSet// constructing rule - in reality reading json from configuration, parsing json and creating FilterRule object
val rule = AndRule(EqualsRule(...), EqualsRule(...), ...)
// applying rule
rdd.filter(record => rule.match(r))
第二个选项是尝试使用现有的Spark SQL函数和DataFrame进行过滤,您可以使用和,或多列构建非常复杂的表达式。这种方法的缺点是不安全,单元测试会更复杂。