[Oracle Text Search] Vous avez une doc en ligne ?

Vous avez une doc en ligne ? [Oracle Text Search] - SQL/NoSQL - Programmation

Marsh Posté le 19-10-2004 à 10:30:44    

Bonjour,
 
Si vous avez un peu suivi mes problèmes ces dernières semaines, je galère depuis un moment sur le moteur de recherche d'un site.
 
J'ai réussi à obtenir de la part de la direction informatique européenne une entorse aux règles de gestion des serveurs afin d'installer Oracle Text Search sur le serveur que j'utilise.
 
Maintenant, j'ai enfin une base de données qui répond au doigt et à l'oeil (172 ms pour retourner une liste de résultats parmi une table contenant un CLOB et 1 300 000 lignes, ça fait plaisir :))
 
Par contre, maintenant je sèche un peu, car je n'ai pas trouvé de docs "précises".
 
J'ai trouvé des exemples basiques de requêtes, qui fonctionne bien, ainsi qu'un PDF récapitulant la liste des fonctions utilisables. Mais ce dernier ne dispose pas d'exemple, ni même de pattern pour la syntaxe...
 
Actuellement, je fais cette requête (en test) :
 
SELECT SCORE(1) score, codpro, nompro
FROM   search
WHERE  CONTAINS(keyword, 'paper', 1) > 0
AND CODLAN = 'ENG'
ORDER BY SCORE(1) DESC;
 
Ca me retourne les 730 lignes qui contiennent le mot "paper" parmi mes produits décrits en anglais. Parfait.
 
Cependant, si je fait cette requête :
SELECT SCORE(1) score, codpro, nompro
FROM   search
WHERE  CONTAINS(keyword, 'papers', 1) > 0
AND CODLAN = 'ENG'
ORDER BY SCORE(1) DESC;
 
Je n'ai plus que 5 lignes.
 
Je cherche donc la fonction (et sa syntaxe) permettant de :
1) Faire une recherche sur les mots de la même racine.
2) Faire une recherche sur les mots d'orthographe voisine.
3) Faire une recherche (si c'est possible) sur les synonymes.
 
PS: sur notre serveur, nous n'avons que les dictionnaires anglais et français. Le site est aussi en italien, espagnol et allemand. Donc pour le point 3, je ne sais pas si c'est possible. De toute façon, ce n'est pas du tout critique. Par contre les deux premiers me semblent bien plus importants !
 
PS²: Ah, et aussi la fonction "mots proches les uns des autres". En effet, je fais faire un petit parseur pour les query de façon à être plus ou moins compatible avec la syntaxe google.
 
Ah euh... Et... Ben ça c'est vraiment la merde :/
 
Comment faire la recherche sur deux mots ???
 
Ca ça marche pas : :/
SELECT SCORE(1) score, codpro, nompro
FROM   search
WHERE  CONTAINS(keyword, 'glossy', 1) > 0
AND CONTAINS(keyword, 'paper', 1) > 0
AND CODLAN = 'ENG'
ORDER BY SCORE(1) DESC;

Reply

Marsh Posté le 19-10-2004 à 10:30:44   

Reply

Marsh Posté le 19-10-2004 à 10:35:41    

Voilà, par exemple, j'ai trouvé ce type de docs :
http://www.oracle.com/technology/p [...] techwp.pdf
 
(à partir de la page 13).
 
Le problème c'est que j'ai bien le nom des fonctions et leur signification, mais si je remplace bêtement mon "contains" par ces fonctions, ça ne marche pas forcément... :/

Reply

Marsh Posté le 19-10-2004 à 10:45:50    

Pour le coup de l'orthographe, j'ai trouvé ça :
 
SELECT SCORE(1) score, codpro, nompro
FROM   search
WHERE  CONTAINS(keyword, 'fuzzy(paper)', 1) > 0
AND CODLAN = 'ENG'
ORDER BY SCORE(1) DESC;
 
Par contre, pour chercher sur plusieurs mots à la fois, j'ai bien la possibilité de faire 'fuzzy(paper) | fuzzy(glossy)' mais ça commence à devenir lent...
Il y a une fonction "accumulate(,)"  d'après la doc, mais je n'arrive pas à m'en servir :sweat:
 
Une idée ?

Reply

Marsh Posté le 19-10-2004 à 12:23:52    

Ca passionne les foules problèmes c'est fou !
 
Bon, j'ai laissé tomber accumulate, en fin de compte je fais des & et ça marche pas trop mal, c'est bien plus rapide que le | (sauf qu'au lieu d'être cumulatif, c'est filtrant)
 
Bon, maintenant, mon souci, c'est que j'ai une autre table...
 
Dedans, j'ai une chiée de champs qui sont indexés. Et la recherche doit porter sur tous les champs :cry:
 
Et je me trouve bloqué avec le problème de tout à l'heure : une query ne peut pas comporter plus d'un CONTAINS, et ce dernier ne porte que sur un champ :sweat:

Reply

Marsh Posté le 19-10-2004 à 14:23:30    

Tu peux pas maintenir un champ supplémentaire (ou dans une autre table) qui contient la concaténation des champs sur lesquels tu veux faire ta recherche ?
 
Avec un petit trigger, ça se met en place facilement, et ensuite, tu fais à nouveau une recherche dans un cas simple : un seul champ, et un CONTAINS() ...
 
D'autre part, comment se manipule le résultat d'une requête contenant un CONTAINS ? tu peux faire des jointures avec ? :)

Reply

Marsh Posté le 19-10-2004 à 15:03:51    

[:drapal] Courage Arjuna !

Reply

Marsh Posté le 19-10-2004 à 20:20:25    

Bon, j'ai fini par trouver (pur hasard fortuit)
 
J'avais fini par me faire une raison pour les requêtes sur des colonnes multiples.
Et à un moment, je sais pas pas pourquoi, je me pose la question "qu'est-ce que c'est que ce 1 qui est utilisé avec la fonction score ?". Le 1 qui est le dernier paramètre de "contains" me semblait être la pondération du résultat d'après les souvenirs de la lecture d'une doc il y a deux semaine, donc je n'avais pas tilté.
 
Alors je change pour mettre "score(2)". Là, j'ai un message d'erreur comme quoi l'identifiant est incorrect. Zarb.
Je fais alors une recherche sur google avec les mots-clés "score oracle text search".
Premiers liens, je trouve rien. Alors je décide de caller l'affaire (après tout, ça marchait comme ça).
Et au moment où je vais pour fermer IE, je vois du coin de l'oeil "score function" pour un site dont le titre est "Oracle Text Functions".
 
Zou ! Je clique. Et miracle !
 
En fait, le 1 de score fait référence au 1 du contains !
Et si je veux mettre plusieurs clauses contains, il suffit que je change la valeur du dernier paramètre afin de ne jamais avoir de doublon, car ce paramètre est en réalité l'identifiant interne de l'expression !!!
 
Et du coup, ça marche :)
 
SELECT SCORE(1) score1, SCORE(2) score2, SCORE(3) score3, title, header, body  
FROM   news  
WHERE  (CONTAINS(title, 'fuzzy(paper)', 1) > 0  
OR CONTAINS(header, 'fuzzy(paper)', 2) > 0  
OR CONTAINS(body, 'fuzzy(paper)', 3) > 0)
AND CODLAN = 'ENG'  
ORDER BY SCORE(1) DESC;  
 
Seule limitation, c'est que du coup je suis obligé de mettre des | et non des & dans les expressions contains, sinon la recherche ne retourne que les lignes où l'un des champs contient tous les mots.
 
Il ne me reste plus qu'à trouver comment marche "accumulate(,)", mais cela reste tout à fait marginal. Là j'ai un moteur de recherche qui fonctionne parfaitement, avec d'excellents temps de réponse : en recherchant parmis les 1 300 000 lignes de produits plus toutes les news (news, promotions, faq, familles de produit, etc.) je n'arrive pas à dépasser 1.5 secondes !
 
Voilà...
 
Merci pains-aux-raisins pour ton soutient, même si je ne le vois que maintenant ;)

Reply

Marsh Posté le 19-10-2004 à 21:40:53    

Topic d'enfer, j'ai appris des choses.....
 
Désolé de n'avoir pu aider, pour le coup c'est moi qui l'ai été.
 
L.

Reply

Marsh Posté le 19-10-2004 à 22:07:03    

en fait, le gros problème, c'est que cette fonctionnalité d'Oracle a l'air d'être très peu utilisée, et par conséquent on trouve peu d'infos sur le net ;)
 
et pourtant, vu tes résultats, ça marche plutôt bien :)

Reply

Marsh Posté le 19-10-2004 à 22:12:16    

c'est clair, je pense que je vais directement faire migrer la base de 8i à 10g :sol:

Reply

Marsh Posté le 19-10-2004 à 22:12:16   

Reply

Marsh Posté le 19-10-2004 à 23:19:07    

En fait, cette solution est très peu utilisée, car jusqu'à la 9i, Oracle Text Search était connu sous le nom de InterMedia Text. Et ce petit module coûtait aussi cher que Oracle tout seul, donc forcément, il n'était pas souvent implémenté. Maintenant, c'est chose réglée, grâce à Microsoft (et oui) qui a intégré son Freetext Search dans SQL Server 2000 sans supplément de license, Oracle s'est senti obligé de suivre avec la version 9i, pour le grand bonheur de tous :)
 
Il faut ajouter à ça un avertissement cependant.
 
De la même façon que Microsoft recommande une machine super-puissante pour faire tourner son Freetext Search, Oracle Text Search est lui aussi très consommateur.
Pour ce qui est des requêtes elles-même, c'est plutôt léger, ça ne consomme que très peu.
Par contre, la place utilisée par les index est monstrueuse : le moteur se crée un dictionnaire de tous les mots trouvés dans toutes les lignes indexées, avec une chiée d'informations, telles que les différentes positions du mot pour chaque occurence, des informations linguistiques permettant de trouver des mots de même radical ou synonymes...
 
Les index sont par conséquent extrêment douloureux pour le serveur à reconstruire. Au point qu'ils ne se reconstruisent pas seuls ! Lorsqu'on ajoute une ligne dans la base, il ne se passe rien au niveau de l'index. Par contre, si on modifie une ligne, ou qu'on la met à jour, cette dernière est simplement supprimée de l'index, pour s'assurer que les résultats retrouvés sont cohérents !
Il faut donc, par tâches schédulées et plans de maintenance interposés, regénérer les index à interval régulier.
Côté administration du serveur Oracle, ce n'est pas moi qui m'en occupe du tout (c'est ça de bosser pour une multi-nationnale), par contre, pour ce qui est de SQL Server (que j'utilise chez moi et dans mon agence), il y a heureusement plusieurs systèmes de mise à jour de l'index. Généralement, on choisi une indexation incrémentielle avec un interval très court (une demi-heure ou une heure), puis une réindexation complète journalière par exemple.
 
Je n'ai jamais eu l'occasion de gérer des bases très volumineuses avec SQL Server (le plus que j'ai fait, c'était 180 Mo...), donc je n'ai jamais senti la charge du serveur (il pédale quelques secondes en tout en pour tout). Mais avec une base de plusieurs Go, et une charge constante élevée, j'imagine qu'il faut à l'aise doubler les capacités de la machine si on veut conserver des performances correctes même pendant l'indexation, et éviter que cette dernière ne dure des heures...
 
Il faut bien garder en mémoire que ces fonctions sont à l'origine faites pour indexer des fichiers stockés dans la base, et pas des brides de bouts de texte comme sur un forum ou le site que je suis en train de faire ;)
La mise en garde est donc à relativiser : on a vraiment un besoin important à condition qu'à la base on avait déjà un besoin énorme.
 
A noter que je ne sais pas si Oracle gère ça de la même façon que SQL Server, mais ce dernier est capable, lors de l'indexation de fichiers, de retrouver des informations dans les headers (PDF, fichiers Office, HTML, etc.) à propos de l'auteur, de la société émetrice, le résumé, etc. SQL Server est même capable de pondre lui-même un résumé du document (ça c'est bleuffant, parcequ'en plus c'est intelligible !)
J'ai vu qu'Oracle donne la possibilité de faire porter la recherche sur des nodes d'un fichier XML, donc je suppose qu'il est aussi capable des autres points que traîte SQL Server.
 
Bref. A bencher impérativement avant de choisir la solution, mais si elle répond aux besoins, oui, c'est réellement LE truc à faire pour faire un moteur de recherche.
 
Un exemple tout à l'heure :
 
SELECT SCORE(1) score, codpro, nompro  
FROM   search  
WHERE  CONTAINS(keyword, fuzzy('1A00473'), 1) > 0  
AND CODLAN = 'ENG'  
ORDER BY SCORE(1) DESC;  
 
=> Moins de 200 ms. "fuzzy()" permet de recherche le mot et toutes ces variations de 2 lettres pour 7 caractères (paramètre standard)
 
Maintenant :
 
SELECT codpro, nompro  
FROM   search  
WHERE  CODPRO LIKE '%1A00473%'
AND CODLAN = 'ENG'  
ORDER BY CODPRO;  
 
=> Avec un index unique sur (CODPRO, CODLAN), et CODPRO varchar2(16)... Bah ça a duré 13 secondes, alors que le champ est pourtant indexé en cluster, et en plus le like ne porte que sur le pattern exact ! :lol:
 
Bref, y'a pas photo, Text Search est infiniment plus puissant, pour un résultat infiniment plus rapide.


Message édité par Arjuna le 19-10-2004 à 23:25:11
Reply

Marsh Posté le 21-10-2004 à 22:37:15    

Merci pour ton dernier message, ça m'a remis un peu au gout du jour. Je passe si rarement sur ce forum. J'ai connu l'arrière grand-père de Text Search il y a 9 ans et je vois qu'il a fait du chemin !
Pour la petite histoire, Oracle avait racheté une boite (anglaise, je crois) qui avait développé un petit moteur d'indexation bitmap. Oracle l'a incorporé à son offre commerciale sous le nom de Text Retrieval et déjà à l'époque, ça tuait tout en terme de rapidité de comptage ! Les bench nous avaient troué le c...
Mais il fallait les bécanes adhoc pour faire tourner le bestiau.
Ensuite ça s'est appelé Text Server, puis ConText puis InterMedia Text.
:hello:  

Reply

Marsh Posté le 19-01-2009 à 18:13:54    

Bonjour,
 
Effectivement topic tres interessant et enorme deterrage de ma part. Je travaille actuellement sur une recherche avec des outils comme Oracle Text Search ou Lucene.  
Mon probleme concerne la mise a jour de l'index. Si j'ai bien compris il n'existe aucun moyen pour le tenir a jour a chaque modification de la bdd. Dans ce cas on est obligé de faire des crons qui vont mettre a jour l'index selon les dernieres modifications de la base ?
 
Comment detectez vous dans ton organisation les changements en base ?  
Qu'appelle tu indexation incrémentielle (toutes les 30mn/1h a priori) ?
 
Bon je ne sais pas si j'aurais une reponse mais ca ne coute rien d'essayer :)


---------------
Tumblr - Flick r - Galerie Perso
Reply

Marsh Posté le 19-01-2009 à 23:01:52    

Avec Oracle, il y a plusieurs moyens de détecter les modifications en bases :
- Triggers.
- Oracle Streams Advanced Queuing.
- Logminer.
 
A toi de choisir :)


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
Reply

Marsh Posté le 20-01-2009 à 09:22:07    

OK donc il est facile de maintenir un index à jour avec Oracle. Je n'ai pas trouvé l'équivalent pour Lucene. Merci a toi :)


---------------
Tumblr - Flick r - Galerie Perso
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed