Critères de recherche variable

Bonjour,

Je me suis lancé dans le développement avec ORDA. Je suis confronté a un problème.
Peut on faire un recherche avec des critère variable ce qui éviterait de définir n recherche que l’on va utiliser dans des cas précis.

Voici un exemple :

lstclient:=ds.Clients.query("(Telephone in :1 | Telephone2 in :1 | Portable in :1) OR (Nom=:2 AND Prenom=:3 AND DateNais = :4)";col_TelRecherche;$nom,$prenom,$DateNais)

Cette exemple contient la recherche complète. Maintenant si mon utilisateur ne renseigne pas le prénom ni la date de naissance (ce qui est optionnel), je devrais écrire la recherche suivante :
lstclient:=ds.Clients.query("(Telephone in :1 | Telephone2 in :1 | Portable in :1) OR (Nom=:2)";col_TelRecherche;$nom)

Y a t’il une solution ?

Merci

Bonne journée a tous

Bonjour,
dans https://doc.4d.com/4Dv18/4D/18/dataClassquery.305-4505887.fr.htmlla doc>, l’exemple 2 (“Recherche avec des placeholders nommés pour les attributs et les valeurs”) m’a l’air de répondre à ça.

De mon côté, je rédige toute la partie de la requête dans une string que je modifie au fur et a mesure des besoins de la requête et je place cette string dans une variable. Les placeholders peuvent évidemment servir, mais dans mon cas, il est plus simple de fonctionner comme mentionne et surtout que les placeholder concernant les attributs sont assez nouveaux.

Bonjour,

Effectivement l’exemple donnée par Arnaud de Montard est bien approprié au cas.

Je suis à votre disposition si vous avez des questions relatives à l’utilisation.

Bonjour,

Merci pour tous vos retours.
Par contre dans cette exemple je ne vois pas comment gérer les opérateur (AND / OR)

Merci

: Pierre-Olivier HOEBEKE

Bonjour,

Merci pour tous vos retours.
Par contre dans cette exemple je ne vois pas comment gérer les
opérateur (AND / OR)

Merci

Pas sûr de mesurer la profondeur de la question mais la réponse est peut être ici:

https://doc.4d.com/4Dv18/4D/18/dataClassquery.305-4505887.fr.htmlhttps://doc.4d.com/4Dv18/4D/18/dataClassquery.305-4505887.fr.html>

Si je reprends l’exemple

<code 4D>
C_OBJET($querySettings;$es)
$querySettings:=Creer objet
$querySettings.attributes:=Creer objet(“attName”;“name”;“attWord”;Creer collection(“softwares”;“Word 10.2”))
$es:=ds.Employee.query(":attName = ‘Marie’ and :attWord = ‘Installed’";$querySettings)

</code 4D>

Tout est bien paramétrable (attributs + valeurs) mais pas les opérateurs AND ou OR

Bonjour,

Oui effectivement.

Si vous utilisez les placeholders nommés pour les valeurs, vous pouvez tester ce qui est renseigné dans l’objet parameters et faire un AND ou un OR.

C_OBJET($querySettings;$managedCustomers)
$querySettings:=Creer objet
$querySettings.parameters:=Creer objet(“userId”;1234;“extraInfo”;Creer objet(“name”;“Smith”))

// Ici vous pouvez ajouter un test if $querySettings.parameters.userId # Null and
// $querySettings.parameters.name # Null

$managedCustomers:=ds.Customer.query(“salesperson.userId = :userId and name = :extraInfo.name”;$querySettings)

https://doc.4d.com/4Dv18/4D/18/dataClassquery.305-4505887.fr.html

Je suis désolé mais je ne comprend pas comment définir mes conditions AND OR en fonction des paramètre utilisateur.
Comment savoir si dans ma collection de critères 4D va utiliser AND ou OR pour leur combinaison.

Voici mon code :
<code 4D>
C_TEXT($rech)
C_OBJECT($critereOB)
C_COLLECTION($collatt;$CollValeur)
C_TEXT($critere)

$rech:="@"+TelRech+"@"

$critereOB:=New object

$collatt:=New collection()
$CollValeur:=New collection()

If (TelRech#"")
col_TelRecherche[1]:=TelRech
Else
col_TelRecherche.remove(1)
End if

Case of
: ((PrenomRech#""))
$collatt.push(“Prénom”)
$CollValeur.push(PrenomRech+"@")
//$critere:=$critere+“Prénom = “+PrenomRech+”@”+" AND "
: (NomRech#"")
$collatt.push(“Nom”)
$CollValeur.push(NomRech+"@")
//$critere:=$critere+“Nom = “+NomRech+”@”+" AND "
: (DateNRech#!00-00-00!)
$collatt.push(“DateNais”)
$CollValeur.push(DateNRech)
//$critere:=$critere+"DateNais = “+DateNRech+” AND "
End case

$critereOB.parameters:=New object(“lstTelephone”;col_TelRecherche;“AttName”;$collatt;“AttValue”;$CollValeur)

lstclient:=ds.Clients.query("(Téléphone in :lstTelephone | Téléphone2 in :lstTelephone | Portable in :lstTelephone) | :AttName = :AttValue )";$critereOB)

</code 4D>

du plus j’ai une erreur que je ne comprends pas.

[]33814921;“Erreur incompréhensible”[/]

Pour pour votre aide

: Pierre-Olivier HOEBEKE

Comment savoir si dans ma collection de critères 4D va utiliser AND
ou OR pour leur combinaison.
Si je reprends ta requête du début :
“(Telephone in :1 | Telephone2 in :1 | Portable in :1) OR (Nom=:2 AND
Prenom=:3 AND DateNais = :4)”
C’est toi qui décides de chercher par téléphone avec des |, puis de coupler avec un OU à la recherche nom&prénom&DDN. Je ne vois pas comment 4D peut déterminer ça à ta place.

Pour le dire autrement, réduisons à {nom, prénom, DDN} comme critères, et supposons que l’utilisateur saisisse les 3, ça te permet de chercher :

  • nom&prénom&DDN
  • nom|prénom&DDN
  • nom&prénom|DDN
  • nom|prénom|DDN
    Aucune de ces 4 recherches n’est à exclure a priori, ça va dépendre de la qualité des données, du nombre de résultats maxi/mini “tolérables”, du métier de l’utilisateur (genre : « a-t-il 10 secondes ou 1 heure pour trouver ? »), etc. Au final, je ne vois guère que le développeur pour décider des & et des |.

Mais peut-être que je ne pige de travers, avec le formulaire utilisateur ce serait peut-être plus clair pour moi.

Bonjour,

Votre query tente d’utiliser des placeholders nommés pour les valeurs et les attribute paths (:AttName = :AttValue )

Pour utiliser des placeholders nommés pour les attribute paths, il faut les donner dans l’objet attributes du querySettings.

De plus, dans $critereOB.parameters, attName et attValue sont de type collection, ce qui n’est pas possible.

Voici un exemple simple d’utilisation simultanée des placeholders nommés pour les valeurs et les attribute paths:

C_OBJECT($es;$queySettings)
C_TEXT($name)

$querySettings:=New object
//Named placeholders for values
//The user is asked for a name
$name:=Request(“Please enter the name to search:”)

If(OK=1)
$querySettings.parameters:=New object(“givenName”;$name)

//Named placeholders for attribute paths
$querySettings.attributes:=New object(“attName”;“name”)
$es:=ds.Employee.query(":attName= :givenName";$querySettings)
End if

https://doc.4d.com/4Dv18R2/4D/18-R2/dataClassquery.305-4803784.en.html

Bonjour,

Merci pour votre retour

Votre exemple :

: Marie-Sophie LANDRIEU

$querySettings:=New object
//Named placeholders for values
//The user is asked for a name
$name:=Request(“Please enter the name to search:”)

If(OK=1)
$querySettings.parameters:=New object(“givenName”;$name)

//Named placeholders for attribute paths
$querySettings.attributes:=New object(“attName”;“name”)
$es:=ds.Employee.query(":attName= :givenName";$querySettings)
End if

Je comprends parfaitement ce fonctionnement. Maintenant comment ajouter un critère de recherche “optionnel” ?
par exemple le prénom ? en sachant que si le prénom est présent dans la recherche, le nom lui peut y être ou pas.

Pour imager ce que je veux mettre en place, c’est un liste de client dans une listBox. Au dessus de cette listBox, je mets 3 champs ( 1 pour saisir le nom, 2 pour le prénom, 3 pour le nu de tel).
En fonction des champs remplis, je voudrais une recherche qui contient les critères remplis en sachant qu’ils ne sont pas obligatoires (comme des filtres).

Merci

Bonjour,

Je viens de trouver une solution qui répondrait a mon besoin.

Je fais des recherches différentes en fonction des critères et j’utilise la fonction .and pour combiner les entitySelection.

Bonn journée

Suite a un conseille d’un ami, voici le code final de ma solution.

<code 4D>
C_TEXT($rech)
C_OBJECT($critereOB;$EntitysTMP)
C_COLLECTION($collatt;$CollValeur)
C_TEXT($critere)

$rech:="@"+TelRech+"@"
$critereOB:=New object

$collatt:=New collection()
$CollValeur:=New collection()

If (TelRech#"")
col_TelRecherche[1]:=$rech
Else
col_TelRecherche.remove(1)
End if
lstclient:=ds.Clients.query("(Téléphone in :1 | Téléphone2 in :1 | Portable in :1))";col_TelRecherche)

If ((PrenomRech#""))
$rech:=PrenomRech+"@"
$EntitysTMP:=ds.Clients.query(“Prénom=:1”;$rech)
lstclient:=lstclient.or($EntitysTMP)
End if
If (NomRech#"")
$rech:=NomRech+"@"
$EntitysTMP:=ds.Clients.query(“Nom=:1”;$rech)
lstclient:=lstclient.or($EntitysTMP)

End if
If (DateNRech#!00-00-00!)

$EntitysTMP:=ds.Clients.query("DateNais=:1";DateNRech)
lstclient:=lstclient.or($EntitysTMP)

End if

</code 4D>