
L'attribut Multi-valued attribute (MVA) de sphinx est une petite merveille que j'ai enfin appréhendé.
Un exemple
des étudiants
Je pars sur un exemple fictif.
Si j'ai des fiches étudiants à indexer. Je peux ajouter des attribut pour les filtrer.
- date de naissance
- genre (m=1/f=2)
- Année (1,2,3,4,5,6)
- Section (latin-grec=1, électricité=2,...)
Dans tous ces attributs, pour une ressource donnée (pour un étudiant), je n'ai qu'une valeur possible.
pour n'avoir que les garçons j'aurais
filter=genre,1;
pour n'avoir que les sections math (code 4) et sciences (code 9) j'aurais
filter=section,4,9
Si je mets
filter=genre,1;filter=section,4,9
j'aurais les garçons d'une de ces sections.
Complétons l'exemple
Maintenant selon la section j'ai jusqu'à 15 tranches horaires en cours à options (à la carte).
Comme ces cours à option ont des durées variables, l'étudiant doit remplir ses 15 périodes.
En composant avec les 40 options proposées, il peut se retrouver avec 15 cours d'une période ou 3 de 5 périodes ou 2 de 5h + 5 de une ...
Je veux chercher (ca tombe bien j'ai sphinx)
Comment indexer cela si dans ma recherche je veux pouvoir trouver les étudiants qui ont pris une option de type "langue"
Imaginant que dans la liste j'en ai 4 :
- anglais (code 15),
- néerlandais (code 18),
- allemand (code 19)
- et espagnol (code 21).
Ce qui ne marchera pas (sans les MVA)
Avec sphinx on en peut pas passer plusieurs filtres et dire matcher ce qui passe au moins un de ces filtres
Avec sphinx tous les filtres seront appliqués
Donc je ne peux pas créer 15 attributs (un par tranche) et dire
filter=attribut_1,15,18,19,21;filter=attribut_2,15,18,19,21;filter=attribut_3,15,18,19,21;....
Parce qu'il faudrait que TOUS les attributs soient matchant pour la liste et donc ne me donnerai que ceux qui ont pris les 4 options et que celles là
Je ne peux pas non plus créer 40 attributs (un par option).
filter=attribut_15,1;filter=attribut_18,1;filter=attribut_19,1;filter=attribut_21,1;
ne me donnerai que ceux qui ont pris les 4 options
Avec les MVA
C'est là que les MVA entrent en jeux.
On va avoir 1 attribut "options" et pour chaque ressource l'attribut va contenir plusieurs valeurs
Lors de la recherche on passe dans la query
filter=attribut_options,15,18,19,21;
Sphinx va matcher toutes les ressources qui ont au moins une de ces valeurs parmis celles qui lui sont attribuées
Indexation avec des attributs MVA
Maintenant qu'on a la façon de "chercher" il faut encore voir comment indexer cela.
Un petit coup d'oeil sur la doc.
Sphinx
sql_attr_multi = ATTR-TYPE ATTR-NAME 'from' SOURCE-TYPE \
[;QUERY] \
[;RANGE-QUERY]
where
ATTR-TYPE is 'uint' or 'timestamp'
SOURCE-TYPE is 'field', 'query', or 'ranged-query'
QUERY is SQL query used to fetch all ( docid, attrvalue ) pairs
RANGE-QUERY is SQL query used to fetch min and max ID values, similar to 'sql_query_range'
Si j'ai bloqué tout un temps c'est parce que c'était trop simple.
J'utilise sql_query pour ma source d'indexation.
Il suffit de produire un champs avec des valeurs séparée par des virgules.
puis on met
sql_attr_multi = unit lenomduchamps from field
Et nous y voilà.
Il y a aussi moyen de demander une sous-requete avec FROM query ou ranged-query
sql_attr_multi = uint tag from query; SELECT id, tag FROM tags
Rien compris à mon exemple d'étudiant ?
En voici un autre.
J'ai une liste d'enregistrements, ces enregistrements sont qualifiés par des tags.
C'est à dire qu'on est pas dans un classement par catégories dans un arbre tout simple.
Chaque enregistrement peut être associés à plusieurs tags.
Admettons que j'aie les tag grand, beau, bleu, jaune, ....
J'ai besoin de trouver tous les grands et bleus de ma base
id name
---
5 bleu
11 grand
je vais faire une MVA pour pouvoir faire une recherche filter:tag_id,5,11