Spark 快递经过多个分拨,确定正确的发件、到件

一条快递单号 会经过多个分拨,每次在分拨都会至少做一次到件、发件。而发件的时候会指定下一站。如果多次发件,就要选择正确的下一站,如果没有正确的下一站,则取最后一次发件。

之前的难点是 不知道哪个站点 是 正确的下一站。

后来才理解过来, 为了判断 正确的下一站,首先要确定 经过了哪些站点。

只有得到了 经过的站点,才能得知 正确的下一站。

不然直接在route里判断无法得知 正确的下一站是谁了。


spark.udf.register("analyRoute", (
                                   rec_site_id: Number,
                                   sign_site_id: Number,
                                   r1: Seq[GenericRowWithSchema]) => {

  /**
    *     经过的route对象,是一个数组   
      |-- route: array (nullable = true)
    * |    |-- element: struct (containsNull = true)
    * |    |    |-- scan_date: timestamp (nullable = true)
    * |    |    |-- scan_site_id: decimal(19,0) (nullable = true)
    * |    |    |-- pre_or_next_station_id: decimal(19,0) (nullable = true)
    * |    |    |-- use_type: integer (nullable = true)
    *
    * use_type:
    * 1 发件
    * 2 到件
    */
  val result = ListBuffer[ErrorData]()

  val recSiteId = rec_site_id.longValue()
  val signSiteId = sign_site_id.longValue()
  var index = 0

  //这里 就是解析route,获得 经过了哪些站点
  val passCenter = r1.foldLeft(List[(Long, Int)]())((l1: List[(Long, Int)], row: GenericRowWithSchema) => {
    val siteId = row.getAs[Number]("scan_site_id").longValue()
    if (l1.isEmpty) {
      List((siteId, 0))
    } else {
      //如果此时的扫描的站点 和 上一次的扫描是同一个,则不插入,反之新增站点
      if (l1.last == siteId) l1 else l1.:+(siteId, 0)
    }
  }).toArray

  def updateRoute(siteId: Long, useType: Int, useTime: Timestamp, nextSiteId: Long): Unit = {
    if (result.length == 0) {
      result.append(ErrorData(siteId).updateStatus(recSiteId, useType, useTime, nextSiteId, signSiteId))
    } else {

      if (result(index).siteId == siteId) {
        result(index) = result(index).updateStatus(recSiteId, useType, useTime, nextSiteId, signSiteId)
      } else {
        val data1 = ErrorData(siteId)
        result.append(data1.updateStatus(recSiteId, useType, useTime, nextSiteId, signSiteId))
        index += 1
      }
    }
  }


  for (no1 <- 0 until (r1.length)) {
    val row = r1(no1)
    val siteId = row.getAs[Number]("scan_site_id").longValue()
    val useType = row.getAs[Int]("use_type")
    val useTime = row.getAs[Timestamp]("scan_date")
    val nextSiteId = row.getAs[Number]("pre_or_next_station_id").longValue()

    //如果是发件
    if (useType == 1) {
      //同分拨多次发件
      if (no1 + 1 < r1.length && r1(no1 + 1).getAs[Number]("scan_site_id").longValue() == siteId && r1(no1 + 1).getAs[Int]("use_type") == 1) {
        //如果此时 还没有站点正确的下一站 且 此时的下一站是正确的下一站
        if (passCenter(index)._2 == 0 && index + 1 < passCenter.length && nextSiteId == passCenter(index + 1)._1) {
          //更新逻辑,告诉程序 这个站点的扫描 已经找到了 正确了下一站
          passCenter(index) = (siteId, 1)
          //去更新逻辑

          updateRoute(siteId, useType, useTime, nextSiteId)

        }
      } else if (passCenter(index)._2 == 0) {
        updateRoute(siteId, useType, useTime, nextSiteId)
      }

    } else {
      updateRoute(siteId, useType, useTime, nextSiteId)
    }
  }


  val resultLen = result.length
  val indexRs = ListBuffer[Int]()
  for (i <- 0 until resultLen) {
    if (result(i).siteId != signSiteId && result(i).nextSiteId > 0 && result(i).nextSiteId != signSiteId) {
      if (i < resultLen - 1 && result(i).nextSiteId != result(i + 1).siteId) {
        indexRs.append(i)
      } else if (i == resultLen - 1) {
        indexRs.append(i)
      }
    }
  }

  indexRs.foreach(index => {
    result.append(ErrorData(result(index).nextSiteId))
  })


  if (result.filter(_.siteId == recSiteId).isEmpty) {
    result.append(ErrorData(recSiteId, hasRec = true))
  }

  if (result.filter(_.siteId == signSiteId).isEmpty) {
    result.append(ErrorData(signSiteId, hasSign = true))
  }

  result
})

本人已经有5年的大数据开发工作经验了,处理的都是 快递数据。

如果大家有意向 在 快递方面的大数据 或者 java开发 有所心动,可以 联系我进行内推。(qq:1729874221)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值