如何将 Slick 结果转换为所需格式?
How to convert Slick result in desired format?
我有 Person
类型的域对象,它在 class 的情况下定义如下:
case class Person(personName: String, personAge: Int, personId: Long = 0)
和对应的查询table如下:
final case class PersonTable(tag: Tag) extends Table[Person](tag, "people") {
def personId = column[Long]("person_id", O.AutoInc, O.PrimaryKey)
def personName = column[String]("person_name")
def age = column[Int]("person_age")
def * = (personName, age, personId).mapTo[Person]
}
并且我有类型为 Address
的域对象,在 class 的情况下定义如下:
case class Address(houseNumber: Int, street: String
, state: String, ownerId: Long, id: Long = 0)
对应的tableclass定义如下。人和地址是一对多的关系(一个人可以有多个地址但是一个地址只属于一个人)
final case class AddressTable(tag: Tag) extends Table[Address](tag, "addresses") {
def houseNumber = column[Int]("house_number")
def street = column[String]("street_name")
def state = column[String]("state_name")
def addressId = column[Long]("address_id", O.PrimaryKey, O.AutoInc)
def ownerId = column[Long]("owner_id")
def owner = foreignKey("owner_fk", ownerId, TableQuery[PersonTable])(_.personId, onDelete = ForeignKeyAction.Cascade)
def * = (houseNumber, street, state, ownerId, addressId).mapTo[Address]
}
我想 return 遵循基于 Akka-http
的 REST API 类型的 JSON 结果( 地址应该是 return编辑为数组):
{
"name": "shekhar",
"age": 30,
"id": 1234,
"addresses": [{
"house_number": 1,
"street": "water street",
"state": "foo bar",
"owner_id": 1234,
"address_id": 9874
},
{
"house_number": 99,
"street": "foo bar street",
"state": "foo disk state",
"owner_id": 1234,
"address_id": 007
}
]
}
为了得到这个结果,我使用 Slick 编写了查询,如下所示:
val peopleQueries = TableQuery[PersonTable]
val addressQueries = TableQuery[AddressTable]
val query = peopleQueries.filter(_.personName === "Shekhar") joinLeft addressQueries on (_.personId === _.ownerId)
val futureResultData = db.run(query.result)
我在以下结构中得到了结果(每个地址都重复了个人详细信息):
Vector(
(Person("shekhar",30,1234),
Some(Address(1,"Water Street","foo bar",1234,9874))
)
, (Person("shekhar",30,1234),
Some(Address(99,"foo bar street","foo disk state",1234,007))
)
)
要将上面的格式转换为预期的 JSON 格式,我可以等到数据库查询有 运行 并编写一些 Scala 代码以将其转换为所需的格式,但这会阻止请求,直到 post-处理完成(如有错误请指正)
我的代码如下所示:
futureResultData.onComplete {
case Success(data) => // code to bring data in desired format
}
我想知道有没有什么方法可以asynchrounous/non-blocking得到结果?
感谢Pedro,我找到了解决这个问题的方法。
对我有用的解决方案如下:
futureResultData.map( x => {
x.groupBy(_._1).mapValues(_.map(_._2.get))
})
futureResultData.map {
_.transformInDesiredFormat // code to bring data in desired format
}
如果你post转换的实际代码我可以帮助你更多
Futures 是 monad,所以当你映射时,你使用的是那个未来,如果你有一个 Future[Int] 并且你映射那个 Future,在映射中你使用 Int。
示例:
val aFuture = Future.successful(1)
aFuture.map(f=> f+ 1)
我有 Person
类型的域对象,它在 class 的情况下定义如下:
case class Person(personName: String, personAge: Int, personId: Long = 0)
和对应的查询table如下:
final case class PersonTable(tag: Tag) extends Table[Person](tag, "people") {
def personId = column[Long]("person_id", O.AutoInc, O.PrimaryKey)
def personName = column[String]("person_name")
def age = column[Int]("person_age")
def * = (personName, age, personId).mapTo[Person]
}
并且我有类型为 Address
的域对象,在 class 的情况下定义如下:
case class Address(houseNumber: Int, street: String
, state: String, ownerId: Long, id: Long = 0)
对应的tableclass定义如下。人和地址是一对多的关系(一个人可以有多个地址但是一个地址只属于一个人)
final case class AddressTable(tag: Tag) extends Table[Address](tag, "addresses") {
def houseNumber = column[Int]("house_number")
def street = column[String]("street_name")
def state = column[String]("state_name")
def addressId = column[Long]("address_id", O.PrimaryKey, O.AutoInc)
def ownerId = column[Long]("owner_id")
def owner = foreignKey("owner_fk", ownerId, TableQuery[PersonTable])(_.personId, onDelete = ForeignKeyAction.Cascade)
def * = (houseNumber, street, state, ownerId, addressId).mapTo[Address]
}
我想 return 遵循基于 Akka-http
的 REST API 类型的 JSON 结果( 地址应该是 return编辑为数组):
{
"name": "shekhar",
"age": 30,
"id": 1234,
"addresses": [{
"house_number": 1,
"street": "water street",
"state": "foo bar",
"owner_id": 1234,
"address_id": 9874
},
{
"house_number": 99,
"street": "foo bar street",
"state": "foo disk state",
"owner_id": 1234,
"address_id": 007
}
]
}
为了得到这个结果,我使用 Slick 编写了查询,如下所示:
val peopleQueries = TableQuery[PersonTable]
val addressQueries = TableQuery[AddressTable]
val query = peopleQueries.filter(_.personName === "Shekhar") joinLeft addressQueries on (_.personId === _.ownerId)
val futureResultData = db.run(query.result)
我在以下结构中得到了结果(每个地址都重复了个人详细信息):
Vector(
(Person("shekhar",30,1234),
Some(Address(1,"Water Street","foo bar",1234,9874))
)
, (Person("shekhar",30,1234),
Some(Address(99,"foo bar street","foo disk state",1234,007))
)
)
要将上面的格式转换为预期的 JSON 格式,我可以等到数据库查询有 运行 并编写一些 Scala 代码以将其转换为所需的格式,但这会阻止请求,直到 post-处理完成(如有错误请指正)
我的代码如下所示:
futureResultData.onComplete {
case Success(data) => // code to bring data in desired format
}
我想知道有没有什么方法可以asynchrounous/non-blocking得到结果?
感谢Pedro,我找到了解决这个问题的方法。
对我有用的解决方案如下:
futureResultData.map( x => {
x.groupBy(_._1).mapValues(_.map(_._2.get))
})
futureResultData.map {
_.transformInDesiredFormat // code to bring data in desired format
}
如果你post转换的实际代码我可以帮助你更多
Futures 是 monad,所以当你映射时,你使用的是那个未来,如果你有一个 Future[Int] 并且你映射那个 Future,在映射中你使用 Int。
示例:
val aFuture = Future.successful(1)
aFuture.map(f=> f+ 1)