7
votes

Pourquoi ne puis-je pas utiliser les options à l'intérieur d'une requête slick

Afin de me sauver avoir à créer tant de méthodes, j'ai essayé de passer en option dans ma méthode, puis de vérifier si l'option est définie, si oui, appliquez le filtre.

polymorphic expression cannot be instantiated to expected type;

IntelliJ errors are expected Boolean actual Column[Boolean].


0 commentaires

5 Réponses :


6
votes

Je ne peux pas vous dire pourquoi, mais cela compile pour moi:

def getUsers(locationId: Option[Int], companyId: Int, salary: Option[Int]): List[User] = {
  val query = for {
    u <- users if u.companyId === companyId && locationId.isDefined && u.locationId === locationId.get && salary.isDefined && u.salary >= salary.get
  } yield(u)
  query.list()
}


5 commentaires

Ça fait à un "vrai" à ma requête, c'est là où (... ... et vrai)


UHM à moi compile sans erreurs, avez-vous retiré la parenthèse autour des conditions? Par exemple. Au lieu de si true && (id === THIID) doit être si true && id === thatid . Dans la fin, le si dans la compréhension de la compréhension de la variante paresseuse du filtre , nommément avecfilter et il devrait compiler si vous avez un True à l'intérieur, je viens d'essayer d'identifier.


Oui, il compile bien, je viens de dire qu'il insère un vrai dans la requête SQL.


Je vois, j'ai mal interprété votre commentaire. Pour être honnête, je doute que cela puisse travailler mais je ne pouvais pas courir une requête. Probablement la condition du filtre complet est traduite en SQL de Slick où il n'a pas de sens (mais cela fait dans Scala). Je suis curieux de savoir comment Slick traduira un Aucun et la condition successive dans cette situation. Vous pourriez diviser la requête en petits morceaux, par ex. Faites le premier filtre, puis si ISDEfinefin est vrai, appliquez la seconde et ainsi de suite, mais cela sera verbeux et manquez le point de la compréhension. C'est aussi loin que je peux aller, espérons que quelqu'un d'autre donnera une meilleure réponse.


Slick traduit le non plus comme SQL NULL, y compris la propagation null SQLS 3-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Valued-Logic Null Propagation. comme faux. Pareil pour &&. Donc, fondamentalement, si quelque chose n'est pas dans l'expression, l'expression entière n'en sera pas, de sorte que l'expression du filtre sera traitée comme fausse et le résultat de la requête sera vide.



-1
votes

Parce que la requête slick est traduite en SQL, qui n'a aucune notion de la classe ISDefinine et d'obtenir des méthodes de la classe d'options. Mais vous pouvez résoudre ce problème en appelant les méthodes en dehors de la requête et en passant les résultats (via la fonction de carte sur les options).

Le code suivant doit le corriger: p>

def getUsers(locationId: Option[Int], companyId: Int, salary: Option[Int]): List[User] = {
    val locationAndSalary = for {
        locId <- locationId;
        sal <- salary
    } yield (locId, sal)

    locationAndSalary.map(locAndSal => {
        val query = for {
            u <- users if u.companyId === companyId && u.locationId === locAndSal._1 && u.salary >= locAndSal._2)  
        } yield u
        query.list()
    }).getOrElse(List[User]()) //If the locationID or salary is None, return empty list.
}


1 commentaires

Salut, mais ce n'est pas ce que je suis après. Je veux ignorer l'emplacementid et le salaire où les filtres s'ils n'en sont pas et ont juste une entreprise de compagnie. Votre requête n'est pas la même chose que la liste de retour [utilisateur] () si elles ne sont pas.



1
votes

Pourquoi cela ne fonctionne pas

comme CVOT a noté Dans son commentaire , la raison pour laquelle cela ne fonctionne pas est parce que: p>

SLICK Traduit le non plus en tant que SQL NULL, y compris la propagation null SQLS 3-Valued-Logic-logique, donc (aucun === a) n'est pas quelle que soit la valeur d'un ... essentiellement si quelque chose n'est pas dans l'expression, l'ensemble L'expression n'aura aucun, de sorte que l'expression du filtre sera traitée comme fausse et le résultat de la requête sera vide. P> blockQuote>

qui dit, il existe un moyen d'obtenir le même comportement em> que vous voulez (filtrage uniquement si une valeur optionnelle est fournie). P>

Un moyen d'arriver Au comportement souhaité h3>

Le traitant clé à noter est que pour les compréhensions sont compilées par SCALA à une combinaison de mappe code> / platmap code> / / avecfilter code> / Filtre code> Appels. Slick, si je comprends bien, fonctionne avec la structure résultante lorsqu'elle compile la compréhension Scala dans une requête SQL. P>

Ceci nous permet de construire une requête en pièces: P>

query
  .ifPresent[Int](locationId, (q, id) => q.withFilter(u => u.locationId === id))
  .ifPresent[Int](salary, (q, s) => q.withFilter(u => u.salary >= s))
  .list()


0 commentaires

3
votes

Bien sûr, ne voyez pas de problème ici, utilisez simplement le filtre (ou avecfilter) et carapez sur les options.

def getUsers(locationId: Option[Int], companyId: Int, salary: Option[Int]): List[User] = (for {
  u <- users filter(u=>
    if (u.companyId === companyId.bind) && 
    (locationId.map(_.bind === u.locationId).getOrElse(true)) && 
    (salary.map(_.bind <= u.salary).getOrElse(true))
  )
} yield u).list()


0 commentaires

1
votes

Vous pouvez utiliser la solution suivante (avec SLICK 3.3.x):

def getUsers(locationId: Option[Int], companyId: Int, minSalary: Option[Int]) = 
  users.
    .filter(_.company === companyId)
    .filterOpt(locationId)(_.locationId === _)
    .filterOpt(minSalary)(_.salary >= _)


0 commentaires