Closed streino closed 1 month ago
Résultats des essais avec DatARA.
Prodige 4.4
Utilisation de la fonctionnalité de CSW virtuels au niveau Geonetwork.
Nous n'arrivons pas à mettre en place un filtre sur l'organisation avec la config de base quelle que soit la requête Lucene formulée (exact match, tokens, etc.).
Le filtre marche en ajoutant orgName
dans la liste des champs tokenisés dans Lucene (le champ est le seul en commentaire dans la config par défaut).
Prochaines étapes :
orgName
en 3.10.4.orgName
(possibilité de tester sur Prodige Ecolab ?)Prodige 5
Utilisation de la fonctionnalité de portails. Testé sur le Prodige 5 Ecolab. La requête renvoie une erreur :
POST https://catalogue-test.prodige-ecolab.fr/geonetwork/DREAL_ARA/fre/csw
Content-Type: application/xml
<csw:GetRecords xmlns:csw="http://www.opengis.net/cat/csw/2.0.2"
xmlns:gmd="http://www.isotc211.org/2005/gmd"
service="CSW" version="2.0.2" resultType="results"
startPosition="1" maxPosition="20"
outputSchema="http://www.isotc211.org/2005/gmd">
<csw:Query typeNames="csw:Record">
<csw:ElementSetName>full</csw:ElementSetName>
</csw:Query>
</csw:GetRecords>
<?xml version="1.0" encoding="UTF-8"?>
<ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2.0" xsi:schemaLocation="http://www.opengis.net/ows http://schemas.opengis.net/ows/1.0.0/owsExceptionReport.xsd">
<ows:Exception exceptionCode="NoApplicableCode">
<ows:ExceptionText>java.lang.RuntimeException: org.fao.geonet.csw.common.exceptions.InvalidParameterValueEx: code=InvalidParameterValue, locator=elementName has invalid XPath : , message=Invalid XPath expression: "/csw:Record//": Expected one of '.', '..', '@', '*', <QName></ows:ExceptionText>
</ows:Exception>
</ows:ExceptionReport>
La même requête sans ElementSetName fonctionne. Et la requête d'origine avec ElementSetName fonctionne sur https://catalogue.datara.gouv.fr/geonetwork/srv/fre/csw-dreal_opendata (Prodige 5 sans portail).
Le problème a été remonté à Prodige.
Attention à désactiver le moissonnage Géocatalogue avant passage en prod du moissonneur DatARA direct. Cf https://github.com/ecolabdata/ecospheres/issues/55.
Suite de l'investigation du problème de filtrage en Prodige 4.4 pour archive (j'ai fait quelques edits mineurs par rapport au mail original).
En attente de tests par Prodige de la solution proposée.
Le problème provient bien d'une incohérence entre indexation et search sur le champ orgName
(c'est loin d'être le seul) :
orgName
est indexé "tel quel", c'est-à-dire que le contenu est stoké en un seul bloc (token) sans aucune modification.
DDT de l'Ain
.orgName
est parsé avec un StandardQueryParser
, c'est-à-dire qu'on applique des transformations (tokenize/normalize + lowercase + stopwords).
orgName:(DDT de l'Ain)
(terms query), le query Lucene généré sera orgName:ddt orgName:de orgName:l'ain
(term query sur 3 tokens).orgName:"DDT de l'Ain"
(phrase query), le query Lucene généré sera orgName:"ddt de l ain"
(phrase query sur 3 tokens).Aucun de ces deux queries qui cherchent 3 tokens normalisés ne peut matcher le token stocké dans l'index.
=> Echec.
Cf Option 2.2 pour les détails.
orgName
Dans config-lucene.xml
, ajouter :
<fieldSpecificAnalyzer>
<Field name="orgName" analyzer="org.apache.lucene.analysis.core.KeywordAnalyzer"/>
</fieldSpecificAnalyzer>
Le filtre CSW matchera alors en mode "keyword" (exact match, absolument aucune transformation à l'indexation ou au search).
Donc il faudra spécifier dans le filtre le texte exact figurant dans gmd:contact/gmd:CI_ResponsibleParty/gmd:organisationName
(= champs indexés dans orgName
).
Par exemple :
orgName:"Direction Régionale de l’Environnement de l’Aménagement et du Logement d'Auvergne-Rhône-Alpes (DREAL Auvergne-Rhône-Alpes)"
(on notera que cet exemple pousse le vice jusqu'à utiliser deux types d'apostrophes... ce qui a une importance en exact match)
responsiblePartyEmail
On pourrait peut-être simplifier l'élaboration du filtre CSW en se basant sur le champ responsiblePartyEmail
plutôt qu'orgName
(si le champ est tjs renseigné dans les métadonnées ?).
D'un côté, un email est une sorte d'entité nommée, donc on peut espérer avoir moins de variations dans ce champ que dans orgName
(ou alors on a un autre problème d'emails invalides...). De l'autre côté, "responsible party" semble mieux correspondre à ce qu'on veut filtrer, plutôt qu'orgName
qui peut contenir les noms de plusieurs entités avec différents rôles.
Dans ce cas, dans config-lucene.xml
, ajouter :
<fieldSpecificAnalyzer>
<Field name="responsiblePartyEmail" analyzer="org.apache.lucene.analysis.core.KeywordAnalyzer"/>
</fieldSpecificAnalyzer>
Filtre correspondant :
responsiblePartyEmail:"ddt-geomatique@ain.gouv.fr"
Je n'ai pas testé cette piste au delà de vérifier qu'on remonte bien des résultats cohérents avec le filtre.
orgName
Lors de nos précédents tests, nous avions activé la tokenization du champ orgName
dans config-lucene.xml
.
En conséquence, le champ orgName
va être indexé avec l'analyzer custom GeoNetworkAnalyzer
, qui fait globalement la même chose qu'un StandardAnalyzer
.
On va donc indexer 3 tokens : ddt
, de
, l'ain
.
Les queries de filtre CSW orgName:(DDT de l'Ain)
ou orgName:"DDT de l'Ain"
vont matcher car on a bien les mêmes tokens dans l'index et le query.
En dehors de déterrer un changement vieux de 13 ans qui n'a par l'air d'avoir de rapport avec orgName
, le véritable problème est qu'orgName
n'est en fait pas configuré comme un champ de recherche, mais comme un champ de facettes.
Donc si on change son type, on risque d'avoir des surprises au niveau des facettes (je ne me rappelle plus si Lucene s'en sort dans ce cas).
Ca pourrait expliquer le fait que le champ orgName
ait été commenté dans la config (mais il aurait été préférrable de le supprimer).
=> Echec.
orgName
Geonetwork utilise un PerFieldAnalyzerWrapper
qui comme son nom l'indique permet d'avoir des Analyzers différents par champs.
Le fichier config-lucene.xml
contient les deux sections suivantes :
<!-- Field analyzer
Define here specific analyzer for each fields stored in the index
...
-->
<fieldSpecificAnalyzer>
<Field name="_uuid" analyzer="org.fao.geonet.kernel.search.GeoNetworkAnalyzer"/>
...
</fieldSpecificAnalyzer>
<fieldSpecificSearchAnalyzer>
<!-- Define here analyzers to be overriden from fieldSpecificAnalyzer.
By default, indexing and searching per field analyzers are the same.
...
</fieldSpecificSearchAnalyzer>
orgName
ne se trouve dans aucune des deux sections par défaut puisque c'est un champ de facettes, et la construction de facettes se fait différement. En gros, le texte d'un champ facetté est stocké sans traitement en un seul token. Ca tombe bien, c'est aussi ce que fait le KeyworkAnalyzer
.
Là où il y a un piège, c'est que le code qui parse les filtres CSW (la fonction parseLuceneQuery
) utilise l'analyzer d'indexation et non celui de search.
Je ne sais pas si c'est un bug, mais ça nous arrange 😅
orgName
(côté search)Si parseLuceneQuery
utilisait l'analyzer de search (ce qui pourrait paraitre plus logique), nous devrions customiser fieldSpecificSearchAnalyzer
pour utiliser un KeywordAnalyzer
pour orgName
.
Le filtre orgName:"DDT de l'Ain"
serait alors parsé en orgName:DDT de l'Ain
(ici "DDT de l'Ain" est un seul token), et on matcherait le keyword dans l'index.
Mais on changerait le comportement du search sur le champ orgName
dans tout Geonetwork.
Le search n'étant pas vraiment configuré sur orgName
on peut imaginer que ça n'est pas trop grave, mais il est possible que ça affecte la sélection ou le drill-down par facettes, donc ça reste risqué.
Note par rapport au mail d'origine : Mon analyse est probablement incorrecte ou du moins incomplète. Mais comme cette approche n'est de toute façon pas une option, je laisse tel quel sans creuser.
=> Echec.
orgName
(côté index)Par chance (?) parseLuceneQuery
utilise l'analyzer d'indexation, donc il faut customiser fieldSpecificAnalyzer
pour avoir un effet sur le filtre CSW.
Et comme orgName
n'est pas un champ indexé pour la recherche mais un champ de facettes (qui n'utilise pas les analyzers d'indexation et indexe "à la façon" d'un KeywordAnalyzer
), la déclaration explicite d'un analyzer d'indexation KeywordAnalyzer
pour orgName
(qui ne sera pas appelé) est un no-op au niveau de l'index final.
J'ai confirmé par :
Dans les deux cas le contenu de l'index pour le champ orgName
est identique à celui avec la config d'origine.
Donc au niveau index :
orgName
est indexé uniquement pour les facettes et donc n'utilise pas la config fieldSpecificAnalyzer
.orgName
).orgName
puisque l'indexation des facettes revient au même qu'une indexation via un KeywordAnalyzer
.Et au niveau search :
orgName
).orgName
).parseLuceneQuery
, et uniquement pour le champ orgName
, donc les filtres sur d'autres champs ne sont pas affectés.parseLuceneQuery
est utilisé uniquement à deux endroits dans le code Geonetwork (filtres CSW et filtres Portails).
Donc en plus on corrige le même bug au niveau des portails, si jamais on préférait utiliser des portails plutôt que des CSW virtuels 👌
Le risque d'effet de bord est donc limité aux filtres CSW ou portails filtrant sur orgName
, ce qui me semble raisonnable.
=> Succès ?
Côté search, passer le log Geonetwork à SEARCH
depuis l'interface d'administration (section Paramètres > Serveur > Niveau de log).
Par exemple la transformation du filtre CSW en véritable query Lucene :
geonetwork-1 | 2024-04-04 19:27:28,291 INFO [geonetwork.csw.search] - LuceneSearcher cswCustomFilter:
geonetwork-1 | +orgName:"DRAAF Rhône-Alpes"
geonetwork-1 | 2024-04-04 19:27:28,292 INFO [geonetwork.csw.search] - LuceneSearcher cswCustomFilterQuery:
geonetwork-1 | orgName:"draaf rhone alpes"
Côté indexation, Geonetwork ne log pas grand chose, c'est dans Lucene que ça se passe.
On voit tout de même passer les documents juste avant l'indexation, ce qui permet de confirmer que le champ orgName
contient bien l'info :
geonetwork-1 | <Field name="orgName" string="DDT 69 (Direction Départementale des Territoires du Rhône)" store="true" index="true" />
Pour en voir plus il faut télécharger Luke et charger l'index Lucene de Geonetwork (attention à ce que la version de Luke corresponde à la version Lucene de Geonetwork).
On voit tout de suite la différence de contenu entre :
@streino Aucune idée
Autre problème rencontré sur DatARA -> https://github.com/geonetwork/core-geonetwork/issues/8020
Benoist a validé les fixes ci-dessus sur un environnement de test Prodige 4.4 (autre que ARA). Il va voir avec Julien pour tester sur DatARA et si ok déployer en prod.
Feu vert de Julien pour déployer sur DatARA 🥳
Update :
En attente de validation par Julien mais tout a l'air OK.
Fixes validés et moissonneur (re)mis en place par Julien sur https://demo.data.gouv.fr/fr/admin/harvester/66549feccb972ee8e5d76b93 :tada:
Vu avec Julien, on mettra en prod après #194.
Plateforme de test pour la mise en place d'endpoints virtuels CSW sur Prodige/GN.
L'objectif est la création d'un endpoint avec filtre sur organisation pour remonter uniquement les données de la DREAL ARA présentes sur DatARA.