Получение кортежа объектов и списка из запроса Slick 2

У меня есть этот запрос, который должен получить список сообщений с информацией об отправителе и их список получателей (рассмотрим параметры функции groupID и senderID):

(for {
    groupUsers <- Users.users if targets.groupID === groupID
    mRecipients <- recipients if mRecipients.targetID === groupUsers.id
    message <- messages if message.senderID === groupUsers.id || message.id === mRecipients.messageID
    sender <- Users.users if sender.id === m.senderID
} yield (message, sender ,mRecipients)).list.map{ result => new FullMessage(result ._1, result ._2, result ._3) }

Но в результате я получил кортеж (Сообщение, Пользователь, Получатель), когда хотел получить кортеж (Сообщение, Пользователь, Список [Получатель]). Как мне удается получить такой результат?

Спасибо вам всем.

1 ответ

Ну... код будет выводить в соответствии с тем, что вы написали, а не в соответствии с тем, что вы хотите. Сосредоточиться на этой части...

yield (message, sender ,mRecipients)

Вы получаете кортеж (message, sender, mRecipents)

И ты сделал это внутри для понимания

mRecipients <- recipients if mRecipients.targetID === targetID
message <- messages if message.senderID === senderID || message.id === mRecipients.messageID
sender <- Users.users if sender.id === m.senderID

Здесь каждое из выражений типа recipients if mRecipients.targetID === targetID оценивает Query монада.

Чтобы понять, что с этим не так, это очень похоже на следование, и давайте подумаем, что произойдет, когда мы сделаем это,

scala>:pa
// Entering paste mode (ctrl-D to finish

for{
  i <- List( 1, 2, 3 )
  j <- List( 1, 2, 3 )
  k <- List( 1, 2, 3 )
} yield( i, j, k )

// Exiting paste mode, now interpreting.

res1: List[(Int, Int, Int)] = List((1,1,1), (1,1,2), (1,1,3), (1,2,1),
(1,2,2), (1,2,3), (1,3,1), (1,3,2), (1,3,3), (2,1,1), (2,1,2), (2,1,3),
(2,2,1), (2,2,2), (2,2,3), (2,3,1), (2,3,2), (2,3,3), (3,1,1), (3,1,2),
(3,1,3), (3,2,1), (3,2,2), (3,2,3), (3,3,1), (3,3,2), (3,3,3))

Проще говоря, for comprehensions сделать что-то похожее на развертывание monad и получить итератор значений внутри него... а затем он оборачивает полученное значение в monad снова.

Итак, если вы делаете что-то вроде,

scala>:pa
// Entering paste mode (ctrl-D to finish

for{
  l <- Some( List( 1, 2, 3 ) )
  i <- Some( 1 )
} yield ( l, i ) 

// Exiting paste mode, now interpreting.
res1: Option[(List[Int], Int)] = Some((List(1, 2, 3),1))

Кроме того... Ваша модель данных выглядит неправильно.

Что такое recipients?? Скажите мне, и, возможно, я смогу решить вашу проблему лучше и эффективнее.

Но, учитывая то, что я могу догадаться о вашей модели данных, теперь, если вы хотите, чтобы список получателей был верным, вам придется сделать что-то вроде:

// List[ ( Message, List[ Recipients] ) ]
val messageAndRecipentsList = ( for {

  // First get all possible recipents
  possibleRecipient <- recipients if possibleRecipient.targetID === targetID

  // Now get all relevant messages for sender and possibleRecipeint
  message <- messages if message.senderID === senderID || message.id === possibleRecipient.messageID

  // Now get list of recipents for each of these messages
  messageRecipients <- for {
    messageRecipient <- recipients if messageRecipient.messageID === message.id
  } yield ( messageRecipient ).list

} yield ( message, messageRecipients ) ).list

// Now lets add sender for each of these messages, I am guessing sender
// should be exactly one for each sendorId. So... instead of querying for
// same user for every message lets just query it once and add to every
// tuple of the above list,

val sender = ( for {
  sender <- Users.users if sender.id === senderID
} yield sender ).list.head


val finalList = messageAndRecipentsList.map ( {
  case ( message, msaageRecipents ) => new FullMessage( message, sender, messageRecipients )
} )
Другие вопросы по тегам