Cela faisait plusieurs mois que je butais sur ce post:
If you are searching for text in more than one TVs, it can’t find the correct entries.
TV1="hi"
TV2="huhu"
search for "hi huhu", you get "nothing found".
http://modxcms.com/forums/index.php/topic,5357.msg143876.html#msg143876
A savoir comment
simplement pouvoir faire une recherche de plusieurs mots non seuleument dans les champs du document (1 ligne dans la table site_content) mais aussi dans les TVs (plusieurs lignes dans la table tmplvar_contentvalues). Et puis j’ai découvert l’instruction
GROUP_CONCAT, qui permet de concaténer les valeurs d’un champ de plusieurs lignes:
GROUP_CONCAT(DISTINCT stc.value ORDER BY stc.value SEPARATOR " ") AS tv_content
L’algorithme de recherche de AjaxSearch est maintenant le suivant:
1/ le paramètre &parents ou &documents défini la liste des documents où doit avoir lieu la recherche
2/ le paramètre &filter défini les documents à exclure (class filter de Ditto)
Pour cela parmi les docs précédents on cherche ceux qui satisfont la clause du filtre et on les écartent de la liste de recherche. A noter que tous les champs utilisés pour une recherche peuvent etre filtrés. Notamment tous les champs de TVs, Jot, maxigallery
3/ un premier select (subselect) construit une liste de lignes avec l’ensemble des champs que l’utilisateur veut voir afficher. Les champs des tables jointes, sont constuits par concaténation des valeurs de lignes. Les champs sont pris dans la liste de tables que l’utilisateur peut lui même définir. Par défaut: site_content, tv. Il peut facilement ajouter les champs de Jot et/ou de maxigallery dans sa recherche. Et par définition
dans le fichier config ajouter ces propres tables avec ces propres champs. Le subselect produit une sous-requête de ce type:
SELECT sc.id, sc.pagetitle, sc.longtitle, sc.description, sc.introtext, sc.content,
GROUP_CONCAT(DISTINCT stc.value ORDER BY stc.value SEPARATOR " ") AS tv_content
FROM `modx0961`.`mod2_site_content` sc
LEFT JOIN `modx0961`.`mod2_site_tmplvar_contentvalues` stc ON sc.id = stc.contentid
WHERE (
(sc.id IN (63,64,65,66,67,68,69,70,71,72,73,97))
AND (sc.published=1)
AND (sc.searchable=1)
AND (sc.deleted=0)
AND (sc.type='document')
AND (sc.privateweb=0)
) GROUP BY sc.id
A ce stade on a pas encore recherché le moindre mot
4/ on rajoute les clauses where tenant compte des mots recherchés (ici "school" avec l’option= oneword) :
SELECT cnt.id, cnt.pagetitle, cnt.longtitle, cnt.description, cnt.introtext, cnt.content, cnt.tv_content
FROM (
SELECT sc.id, sc.pagetitle, sc.longtitle, sc.description, sc.introtext, sc.content,
GROUP_CONCAT(DISTINCT stc.value ORDER BY stc.value SEPARATOR " ") AS tv_content
FROM `modx0961`.`mod2_site_content` sc
LEFT JOIN `modx0961`.`mod2_site_tmplvar_contentvalues` stc ON sc.id = stc.contentid
WHERE (
(sc.id IN (63,64,65,66,67,68,69,70,71,72,73,97))
AND (sc.published=1)
AND (sc.searchable=1)
AND (sc.deleted=0)
AND (sc.type='document')
AND (sc.privateweb=0)
) GROUP BY sc.id
) AS cnt
WHERE (
cnt.pagetitle LIKE '%school%'
OR cnt.longtitle LIKE '%school%'
OR cnt.description LIKE '%school%'
OR cnt.introtext LIKE '%school%'
OR cnt.content LIKE '%school%'
OR cnt.tv_content LIKE '%school%'
)
5/ le paramètre &order permet d’ordonner les résultats de la recherche en fonction des champs des tables
6/ les résultats de recherche sont stockés dans un tableau de lignes résultats. Le paramètre &extract permet alors de définir quels sont les champs à prendre en compte dans l’affichage de l’extrait trouvé et combien d’extraits on veut afficher.
7/ le paramètre &rank, permet de définir la fonction de ranking (classement en français ?) en précisant par exemple qu’on accorde plus de poids si le mot est trouvé dans le titre du doc que dans le corps de texte du doc (content). Mias cet exemple est vrai avec n’importe quel champ des tables. &rank=`pagetitle:100,extract` : le mot trouvé dans le titre = 100points. 5 mots trouvés dans l’extract = 5*1 points. Total: 105 pts.
8/ chaque résultat de recherche se voit donc affecter une valeur de ranking en fonction du nombre de mots et de l’endroit où ils sont trouvés.
9/ les résultats sont affichés en fonction de cette valeur de ranking
Toutes ces options restent des options et les performances restent intactes pour peu j’imagine que sur des gros volumes on ne multiplient pas à l’infini les tables & les champs à prendre en compte (construction des placeholders associés) ainsi que les filtres à appliquer.
Je finirai en ajoutant que l’utilisateur peut définir ces propres tables (principale et liées par jointure) et utiliser Ajaxsearch de la même façon qu’avec la table site_content et tmplvar_contentvalues. Ces tables doivent simplement être définies dans le fichier de configuration.