如何重用 Slick 查询
How can I reuse Slick query
我的 table 定义是
class Ipv4ToCountries(tag: Tag) extends Table[(Long, String)](tag, "IP2COUNTRIES") {
def ip = column[Long]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
class Ipv6ToCountries(tag: Tag) extends Table[(BigDecimal, String)](tag, "IPV6_2COUNTRIES") {
def ip = column[BigDecimal]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
class Country2Languages(tag: Tag) extends Table[(String, String, String)](tag, "COUNTRY2LANGUAGES") {
def code = column[String]("CODE")
def lang_code = column[String]("LANG_CODE")
def iso_country = column[String]("ISO_COUNTRY")
def * = (code, lang_code, iso_country)
}
请注意,Ipv4ToCountries
和 Ipv6ToCountries
之间的唯一区别是 ip
列的类型。这是我的查询函数:
def getLangCode(ip: String): Future[String] = {
InetAddress.getByName(ip) match {
case ipv4: Inet4Address =>
val q = (for {
i <- ipv4s.sortBy(_.ip.desc) if i.ip < ipv4ToLong(ipv4)
c <- ip2nationCountries if i.country === c.code
} yield c.lang_code).take(1)
db.run(q.result.head)
case ipv6: Inet6Address =>
val q = (for {
i <- ipv6s.sortBy(_.ip.desc) if i.ip < ipv6ToDecimal(ipv6)
c <- ip2nationCountries if i.country === c.code
} yield c.lang_code).take(1)
db.run(q.result.head)
}
}
IPv4 和 IPv6 的查询几乎相同,但条件 if i.ip < addrToNumeric
。
有什么方法可以重用查询吗?
你可以有一个共同的参数化 class 比如
class IpToContries[A: TypeMapper](t: Tag, s: String) extends Table[(A, String)](t, s) {
def ip = column[A]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
然后像
一样使用它
class Ipv4Countries(tag: Tag) extends IpToContries[Long](tag, "IP2COUNTRIES")
class Ipv6Countries(tag: Tag) extends IpToContries[BigDecimal](tag, "IPV6_2COUNTRIES")
我还没有测试过,但是 A
上绑定的 TypeMapper
上下文应该指定足以以这种方式使用的通用类型。
我的 table 定义是
class Ipv4ToCountries(tag: Tag) extends Table[(Long, String)](tag, "IP2COUNTRIES") {
def ip = column[Long]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
class Ipv6ToCountries(tag: Tag) extends Table[(BigDecimal, String)](tag, "IPV6_2COUNTRIES") {
def ip = column[BigDecimal]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
class Country2Languages(tag: Tag) extends Table[(String, String, String)](tag, "COUNTRY2LANGUAGES") {
def code = column[String]("CODE")
def lang_code = column[String]("LANG_CODE")
def iso_country = column[String]("ISO_COUNTRY")
def * = (code, lang_code, iso_country)
}
请注意,Ipv4ToCountries
和 Ipv6ToCountries
之间的唯一区别是 ip
列的类型。这是我的查询函数:
def getLangCode(ip: String): Future[String] = {
InetAddress.getByName(ip) match {
case ipv4: Inet4Address =>
val q = (for {
i <- ipv4s.sortBy(_.ip.desc) if i.ip < ipv4ToLong(ipv4)
c <- ip2nationCountries if i.country === c.code
} yield c.lang_code).take(1)
db.run(q.result.head)
case ipv6: Inet6Address =>
val q = (for {
i <- ipv6s.sortBy(_.ip.desc) if i.ip < ipv6ToDecimal(ipv6)
c <- ip2nationCountries if i.country === c.code
} yield c.lang_code).take(1)
db.run(q.result.head)
}
}
IPv4 和 IPv6 的查询几乎相同,但条件 if i.ip < addrToNumeric
。
有什么方法可以重用查询吗?
你可以有一个共同的参数化 class 比如
class IpToContries[A: TypeMapper](t: Tag, s: String) extends Table[(A, String)](t, s) {
def ip = column[A]("IP")
def country = column[String]("COUNTRY")
def * = (ip, country)
}
然后像
一样使用它class Ipv4Countries(tag: Tag) extends IpToContries[Long](tag, "IP2COUNTRIES")
class Ipv6Countries(tag: Tag) extends IpToContries[BigDecimal](tag, "IPV6_2COUNTRIES")
我还没有测试过,但是 A
上绑定的 TypeMapper
上下文应该指定足以以这种方式使用的通用类型。