j’ai un objet BCSIApplication contenant 20 champs dont 5 indexables.
J’ai ensuite un objet BCSIRCMApplication héritié de BCSIApplication avec le filtre sur un champ non indexé (je ne sais pas si cela a un impact).
La recherche indexée sur BCSIRCMApplication revient toujours vide.
Ci-dessous ma page publique. Un search classique est exécuté afin d’afficher dans un tableau les BCSIRCMApplication. Un champ texte en haut à droite permet de faire une recherche indexée.
Dans notre cas, le search classique retourne bien une appli dont le nom court est 0202. Or la recherche indexée (alors que le champs Nom court est bien indexé) ne retourne rien.
L’index se crée sur l’entité qui fait la création/mise à jour, mais pas sur les héritiers (regarder dans la table m_index / menu Exploitation > Indexes d’objet ce qui est indexé par défaut).
Il faudrait qu’on analyse ce point pour faire évoluer la recherche et y inclure les héritiers flagués comme “indexable”, on va regarder ce point.
En attendant, il est toujours possible de modifier le résultat d’une recherche via Hook, dans votre cas substituer les noms d’objet dans les SearchItem trouvés (en gardant le même row_id) :
en V4 dans les GrantHooks
public static List<SearchItem> postSearchIndex(Grant g, List<SearchItem> rows) {
if (rows!=null) {
for (SearchItem item : rows) {
if ("ObjectX".equals(item.object))
item.object = "ObjectY";
}
}
return rows;
}
En V5 dans le PlatformHooks : même signature de méthode mais non static permettant un reload dynamique sans redémarrer tomcat
Merci @Francois pour votre retour. Je ne comprends toutefois pas votre solution, je pense qu’elle arrive “trop” tard.
Dans le postSearchIndex, je n’ai pas de résultats donc je ne peux pas changer la valeur du champs object. Comment mettre dans le preSearchIndex qu’il doit remplacer BCSIRCMApplication par BCSIApplication.
De ce que je comprends de votre solution, il faudrait que je fasse la recherche indexée sur l’objet parent or l’objet fils rajoute une contrainte sql. Dans votre exemple, je récupérerai des objets ne respectant pas le filtre du fils.
De plus, y a t’il moyen de ne pas mettre le code dans un objet commun à tous ? N’est-il pas possible que le postSearchIndex soit exécuté comme Hook de notre objet plutôt que dans un singleton commun à tous. Le GrantHook risque de devenir illisible très rapidement.
C’est forcement un script commun car l’index est sur des objets hétérogènes / l’ensemble des objets indexables. Il n’est pas nécesaire d’avoir la définiton d’un objet, mais uniquement son nom… tout comme le menu est une ressource commune/fusionnée de tous les modules, avec un seul point d’entrée pour filtrer l’ensemble.
Le preSearchIndex permet uniquement d’agir sur la requête demandée.
Le postSearchIndex arrive justement après ce que trouve Simplicité.
Donc ça comprend aussi de pouvoir y ajouter des résultats ou de les réordoner suivants vos propres règles, ou requetes dans m_index ou ailleurs. C’est comme un postSearch mais centralisé et appliqué à des objets disparates.
Les règles de filtrage sur vos objets s’appliquent forcement après recherche dans m_index qui n’a aucune notion de droit. Simpicité fait une recherche “fulltext” sur la table m_index en pondérant plus la clé fonctionnelle que le contenu, puis élague les objets qui ne sont pas remontés par un “select(row_id)” dans la session utilisateur.
Votre formulaire et vos recherches étant spécifiques pourquoi ne faites vous pas vous même le select dans le table m_index qui vous convient ? en complement ou en override de celui de Simplicité ?
Vu que l’appel en JS se faisait de la façon suivante : appSimplicite.getBusinessObject("BCSIApplication", "public_BCSIRCMApplication").indexsearch(function(results) { .. });
J’avais l’espoir qu’on passe par du code de mon BusinessObjet et non pas dans une méthode commune à tous les objets possible.
Justement c’est bien le preSearchIndex que je voudrais modifier pour lui dire que si l’objet demandé est BCSIRCMApplication alors il doit chercher idx_object = “BCSIApplication”.
Comment puis-je lui “imposer” le idx_object" ?
Je ne comprends pas votre phrase “puis élague les objets qui ne sont pas remontés par un “select(row_id)” dans la session utilisateur.”
En soit nos recherches ne me semblent pas spécifiques, on veut juste faire des recherches sur des objets héritiers. Notre BCSIApplication possèdent une dizaine d’héritiers sur lesquels on aimerait faire des recherche full text.
Pourriez-vous me donner la requête SQL généré pour le requêter votre table m_index svp ?
Je pensais que la colonne idx_all contenait la concaténation de tous les champs indexés mais cela ne semble pas être le cas.
Sur BCSIApplication, nous avons indexé, le nom couirt, le nom long FR et EN et les descriptions EN et FR. Dans la table m_index je ne retrouve que (pour l’application GPI) :
Si ça ne remonte rien, comme j’ai déjà dit il faut voir si la donnée est dans la table m_index.
A mon avis, il faut reconstuire votre index dont les colonnes indexables ont dû être ajoutées après l’insertion de données (bouton “rebuild” depuis la liste des index).
En front la méthode indexsearch appliquée à un objet est bien un filtre sur la colonne idx_object en back. On peut en fait passer une liste d’objets dans l’API back, mais le front ne s’en sert pas, on peut faire des recherche fulltext mono-objet depuis la fenêtre de recherche d’un objet donné.
La recherche full text SQL dépend de votre base de données car ce n’est pas normalisé.
sur hsqldb ce n’est pas supporté et ça reste un “like” de base.
Activez temporairement les traces via param système LOG_SQL* pour la voir passer.
Cette recherche fulltext ne tient pas compte des droits / habilitations / search-spec
Donc au retour Simplicité vérifie que chaque ligne est bien accéssible, c’est à dire effectue un search sur le row_id avec les droits du user : regarde l’accès READ de l’objet + applique les filtres + les search-spec + les hook pre/postSearch de l’objet… comme si l’utilisateur voulait afficher l’objet = ce genre de recherche coute donc très cher en nombre de requêtes et de hooks appelés.
Ce résultat filtrée est enfin envoyé au hook postSearchIndex.
Justement je dois bien agir sur le preSearchIndex.
Reprenons mon besoin (je n’ai pas du être assez claire, désolée) :
J’ai un objet BCSIApplication contenant un type et dont les champs : nom long et descriptions sont indexés. J’ai donc des records dans la table m_index avec idx_object = “BCSIApplication”.
J’ai l’objet BCSIRCMApplication qui hérite de BCSIApplication en ajoutant un filtre SQL t.type = ‘RCM’
J’ai l’objet BCSIType2Application qui hérite de BCSIApplication en ajoutant un filtre SQL t.type = ‘TYPE2’.
Lorsque je fais une recherche indexée sur BCSIRCMApplication ou BCSIType2Application, la requête ne retourne rien (aucune row dans le postSearchIndex) car l’indexation a été faite sur l’élément parent.
J’aimerai donc dans un premier temps intercepter la requête (via preSearchIndex ?) pour lui dire si l’objet requêté est BCSIRCMApplication ou BCSIType2Application alors il faut chercher idx_object = “BCSIApplication”.
Ensuite dans le hook postSearchIndex, y a t’il un moyen de retrouver le ‘vrai’ objet sur lequel on a lancé la requête ? Comme ca je laisse Simplicité faire les opérations normalement (regarde l’accès READ de l’objet + applique les filtres + les search-spec + les hook pre/postSearch de l’objet).
Parce que le problème dans votre solution c’est que l’on fait un remplacement systématique de item.object. Cela signifie qu’un utilisateur ne pourra pas faire de recherche indexée sur le parent puisqu’une substitution est toujours réalisée.
public static List<SearchItem> postSearchIndex(Grant g, List<SearchItem> rows) {
if (rows!=null) {
for (SearchItem item : rows) {
if ("BSCIApplication".equals(item.object) && !"monVraiObjetRequete".equals(item.object))
item.object = "monVraiObjetRequete";
}
}
return rows;
}
Oui j’avais bien compris le besoin de “reroutage” des recherches fulltext des héritiers par le parent. Ca me semble infaisable en l’état des hooks. En première analyse :
getTargetObject
Il faudrait que dans ce contexte de recherche fulltext, le hook getTargetObject soit appelé (c’est le hook du reroutage par excellence). Ca permettrait de chercher sur l’objet parent mais de retourner les héritiers (dans le postSearchIndex il n’y aurait plus rien à faire).
preSearchIndex avant d’appliquer SQL+droits
Il permet d’accéder à la requête utilisateur (l’input textuel, pas la requete SQL). Il faudrait en effet ajouter plus de paramètres pour pouvoir surcharger ce qui est demandé avant recherche :
la liste des objets ciblés (afin d’en enlever ou d’en ajouter, si on imagine par exemple indexer tous les héritiers et non plus le parent)
le contexte d’appel (comme une recherche de référence)
l’objet parent optionnel pour récupérer des informations contextuelles (recherche de référence)
postSearchIndex avec le résultat
Idem il faudrait passer tous les paramètres, pour modifier le résultat en fonction du contexte d’usage.
Je passe votre besoin en feature request, car en l’état je ne vois pas commet on pourrait faire sauf à indexer tous les héritiers et faire une recherche sur chacun et mixer les résultats à l’écran…
ce qui serait très lourd.
L’approche par getTargetObject me semble la meilleur (si on peut la faire fonctionner dans ce contexte)
Sinon il faudra indexer tous les héritiers (l’index aura la même taille et les row_id déjà dans le “bon” objet), et substituer l’objet parent par tous les fils dans le hook preSearchIndex quand on aura fait l’évolution d’ajouter des paramètres.
Ca peut être fait rapidement car ça n’impacte pas grand chose.
Le hook getTargetObject est bien désormais appelé lors d’un recherche fulltext.
On recherche donc les objets cibles dans une rechrche globale, donc sauf dans le cas d’une recherche de référence qui peut être sur l’objet chapeau/parent.