需要帮助根据Apache Spark的规则集过滤记录

时间:2017-06-16 13:00:38

标签: apache-spark apache-spark-sql apache-spark-mllib spark-graphx

我在使用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 [记录]

  • 广播列表[规则],因为它们的数量较少。

  • 将每条记录与所有规则匹配。

仍然在这种情况下,没有发生用于将每条消息与标准匹配的并行计算。

1 个答案:

答案 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进行过滤,您可以使用和,或多列构建非常复杂的表达式。这种方法的缺点是不安全,单元测试会更复杂。