光滑连接两个表并获得

时间:2015-09-08 22:14:29

标签: scala join playframework-2.0 slick slick-3.0

我有这样的多对多关系设置:

人< - > PersonField< - >字段

现在,我不仅要查询Person的所有字段(我可以这样做),而且还要查询PersonField和Person字段的连接版本。 (我想在数据透视/中间表“PersonField”中查询/检索信息!)

人:

case class Person(id: Long, name: String)
{
   def fields =
   {
       person <- Persons.all.filter(_.id === this.id)
       field <- person.fields
   } yield field
}

class Persons(tag: Tag) extends Table[Person](tag, "persons")
{
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")

    def * = (id, name) <> (Person.tupled, Person.unapply)
    def fields = PersonFields.all.filter(_.personID === id).flatMap(_.fieldFK)
}

object Persons
{
    lazy val all = TableQuery[Persons]
}

字段:

case class Field(id: Long, name: String, description: Option[String])

class Fields(tag: Tag) extends Table[Field](tag, "fields")
{
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")
    def description = column[Option[String]]("description")

    def * = (id, name, description) <> (Field.tupled, Field.unapply)
}

object Fields
{
    lazy val all = TableQuery[Fields]
}

PersonField:

case class PersonField(id: Long, personID: Long, fieldID: Long, value: String)

// TODO add constraint to make (personID, fieldID) unique
class PersonFields(tag: Tag) extends Table[PersonField](tag, "person_field")
{
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def personID = column[Long]("person_id")
  def fieldID = column[Long]("field_id")
  def value = column[String]("value")

  def * = (id, personID, fieldID, value) <> (PersonField.tupled, PersonField.unapply)

  def personFK = foreignKey("person_fk", personID, Persons.all)(_.id)
  def fieldFK = foreignKey("field_fk", fieldID, Fields.all)(_.id)
}

object PersonFields
{
  lazy val all = TableQuery[PersonFields]
}

现在查询Person的所有字段我有一个小帮助类:

def getFields(p: Person): Future[Seq[Field]] =
{
    val query = p.fields
    db.run(query.result)
}

所以我可以做到

val personX ...

personX.onSuccess
{
    case p: Person =>
    {
        val fields = helper.getFields(p)
        fields.onSuccess
        {
            case f: Seq[Field] => f foreach println 
        }  
    }
}

现在,personX的每个字段都会打印到控制台。像魅力一样。

问题是,我也希望获得PersonField(使用Field)!

所以我尝试了以下更改(其中包括不起作用,我记不起来了)

def fields =
{
    for
    {
        person <- Persons.all.filter(_.id === this.id)
        field <- person.fields join Fields.all on (_.fieldID === _.id)
    } yield field
}

人物

def fields = PersonFields.all.filter(_.personID === id) //这里没有flatMap!

然后getFields(p:Person)看起来像这样:

def getFields(p: Person): Future[Seq[(PersonField, Field)]]

personX.onSuccess
{
    case p: Person =>
    {
        val fields = helper.getFields(p)
        fields.onSuccess
        {
            case f: Seq[(PersonField, Field)] => f map(f => println(f._1)} 
        }  
    }
}

什么也没给我,所以我猜我的联系一定是错的。但究竟我究竟做错了什么?

1 个答案:

答案 0 :(得分:2)

您可以加入所有三个,然后产生结果

for {
      ((personField, person), field) <- PersonFields.all join Persons.all on (_.personId === _.id) join Fields.all on (_._1.fieldId === _.id)
      if person.id === this.id
    } yield (personField, person, field)

(我不确定我到底想要从查询中得到什么,所以你可以编辑产量部分)