SPW-DIG / metawal-core-geonetwork

Metawal - Catalogue pour l'information géographique de Wallonie
http://metawal.wallonie.be
GNU General Public License v2.0
3 stars 1 forks source link

Kibana scripted fields #685

Closed vbombaerts closed 2 years ago

vbombaerts commented 2 years ago

Je souhaite créer un tableau qui utilise des scripted fields pour calculer des valeurs dans certaines conditions

  1. Ressource qui a été examinée pour définir si elle est dans INSPIRE ou pas : trois valeurs possibles

    • mot-clé "Reporting INSPIRE" --> Oui
    • mot-clé "Reporting INSPIRENO" --> Non
    • ni mot-clé "Reporting INSPIRE" ni mot-clé "Reporting INSPIRENO" --> indéfini
  2. Diviser une chaine de caractères

    • custodianOrgForResource doit être séparé en nom du gestionnaire et hiérarchie du gestionnaire : "Direction de la Protection des Sols (SPW - Agriculture, Ressources naturelles et Environnement - Département du Sol et des Déchets - Direction de la Protection des Sols)" devient "Direction de la Protection des Sols" + "SPW - Agriculture, Ressources naturelles et Environnement - Département du Sol et des Déchets - Direction de la Protection des Sols"
fxprunayre commented 2 years ago

Je pense que le pb vient du fait qu'on a un champ tag qui est un tableau de type object.

Ci-dessous on voit que contains marche pas image

Il nous faut donc boucler sur le tableau et regarder la valeur. A priori, ça

if(doc['tag.default'].size() != 0){
    for(int i=0; i < doc["tag.default"].size();i++){
      if (doc["tag.default"][i] == 'Zones à risque naturel') {
          return 'FOUND'
      }
    }
}
return 'NOT FOUND';

fonctionne. @vbombaerts je te laisse tester.

vbombaerts commented 2 years ago

Super !

Reporting INSPIRE

if(doc['th_infraSIG.default'].size() != 0){
    for(int i=0; i < doc["th_infraSIG.default"].size();i++){
      if (doc["th_infraSIG.default"][i] == 'Reporting INSPIRE') {
          return 'YES'
      }
    }
    for(int i=0; i < doc["th_infraSIG.default"].size();i++){
      if (doc["th_infraSIG.default"][i] == 'Reporting INSPIRENO') {
          return 'NO'
      }
    }
}
return 'UNDEFINED';

Custodian hierarchy - (la première ligne permet d'évacuer les cas où il n'y a pas de custodian, car ça causait une erreur dans le calcul de l'indicateur)

if (doc['custodianOrgForResource'].size() != 0){
 def path = doc['custodianOrgForResource'].value;
if (path != null) {
    int firstSlashIndex = path.lastIndexOf('(');
    int lastSlashIndex = path.lastIndexOf(')');
    if ((firstSlashIndex > 0) && (lastSlashIndex > 0)) {
    return path.substring(firstSlashIndex+1 , lastSlashIndex);
    }
}
return path;
}
return "undefined";

Custodian name (la première ligne permet d'évacuer les cas où il n'y a pas de custodian, car ça causait une erreur dans le calcul de l'indicateur)

if (doc['custodianOrgForResource'].size() != 0){
 def path = doc['custodianOrgForResource'].value;
if (path != null) {
    int firstSlashIndex = path.lastIndexOf('(');
    if (firstSlashIndex > 0) {
    return path.substring(0 , firstSlashIndex-1);
    }
}
return path;
}
return "undefined";
vbombaerts commented 2 years ago

J'ai remarqué qu'au niveau des visualisations, il y a 2 index portant le nom gn-records. (en prod) Le scripted field a été créé dans un des deux index et pas dans l'autre. Donc on ne peut l'exploiter que si on choisit le bon index. image

image Les deux index n'ont pas le même contenu image image

Peut-on supprimer l'index en doublon ? Lequel est le bon ?

fxprunayre commented 2 years ago

Peut-on supprimer l'index en doublon ? Lequel est le bon ?

Y'en a un qui a une étoile (ie. par défaut), on peut sans doute supprimer l'autre.

vbombaerts commented 2 years ago

Identifiant local

Comment afficher l'identifiant local dans Kibana ? C'est le code d'identifiant qui ne correspond pas au codespace http://geodata.wallonie.be/id

image

J'ai testé ce bout de code mais je ne suis manifestement pas encore au point avec la manipulation des différents types de données Kibana.

if (doc['resourceIdentifier'].size() != 0){
    def localcode = 'undefined';
     for(int i=0; i < doc['resourceIdentifier'].size();i++){
         def blocIdentifiant = doc['resourceIdentifier'][i] ;
         if ((blocIdentifiant.codespace) != 'http://geodata.wallonie.be/id/') {
             localcode = blocIdentifiant.code ;
         }
     }
     return localcode ;
}
return 'undefined';
fxprunayre commented 2 years ago

J'aurai dit quelquechose comme

if (doc['resourceIdentifier.code'].size() > 0) {
    for(int i = 0; i < doc['resourceIdentifier.code'].size(); i++){
        if (doc['resourceIdentifier.codeSpace'][i] == '') {
         return i + ':' +  doc['resourceIdentifier.codeSpace'][i] + ':' + doc['resourceIdentifier.code'][i];
        }
     }
}
return ''

mais non, sans doute car resourceIdentifier est de type object et non nested - A tester.

On peut utiliser

if (doc['resourceIdentifier.code'].size() > 0) {
    for(int i = 0; i < doc['resourceIdentifier.code'].size(); i++){
        if (!doc['resourceIdentifier.code'][i].contains('-')) {
         return doc['resourceIdentifier.code'][i];
        }
     }
}
return ''
ou 
if (doc['resourceIdentifier.code'].size() > 0) {
    for(int i = 0; i < doc['resourceIdentifier.code'].size(); i++){
        if (!(doc['resourceIdentifier.code'][i] =~ /\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/)) {
         return doc['resourceIdentifier.code'][i];
        }
     }
}
return ''
vbombaerts commented 2 years ago

INSPIRE View service

Si un view service INSPIRE est renseigné dans la fiche, donne le thème de ce service. Sinon renvoie 'no service'

if(doc['linkUrl'].size() != 0){
    for(int i=0; i < doc['linkUrl'].size();i++){
      if (doc['linkUrl'][i].contains('geoservices.wallonie.be/INSPIRE/WMS')){
          def path = doc['linkUrl'][i] ;
          int WMSIndex = path.indexOf('WMS/');
          return path.substring(WMSIndex+4 , WMSIndex+6) ;
      }
    }
}
return 'no service';

INSPIRE Download service

Si un download service INSPIRE de type atom est renseigné dans la fiche, donne le thème de ce service. Sinon renvoie 'no service'

if(doc['linkUrl'].size() != 0){
    for(int i=0; i < doc['linkUrl'].size();i++){
      if (doc['linkUrl'][i].contains('geoservices.wallonie.be/inspire/atom')){
          def path = doc['linkUrl'][i] ;
          int atomIndex = path.indexOf('atom/');
          return path.substring(atomIndex+5 , atomIndex+7) ;
      }
    }
}
return 'no service';
vbombaerts commented 2 years ago

Conformité donnée

Bloqué avec ce champ specificationConformance pour récupérer la valeur de pass de la conformité dont le title correspond à "1089/2010"

image

Ce serait plus facile avec du xml ;-p

vbombaerts commented 2 years ago

Limitations à l'usage

Pas optimal car pas réussi à looper dans toutes les valeurs de l'objet, mais mieux que rien, j'ai la première et la dernière. On suppose qu'on ne mélange par les conditions INSPIRE avec les autres, donc qu'elles sont soit tout en haut, soit tout en bas. Si qqun arrive à parser toutes les valeurs, je suis preneur...

Renvoie l'ancre de la licence si la première ou la dernière entrée correspond à la valeur "noLimitations" d'INSPIRE

if(params._source.MD_LegalConstraintsOtherConstraintsObject!=null && params._source.MD_LegalConstraintsOtherConstraintsObject.size()>0) {
    def data = params._source.MD_LegalConstraintsOtherConstraintsObject;
    def taille = params._source.MD_LegalConstraintsOtherConstraintsObject.size()-1;
    def licence = "other";
    def licenceTaille = data[taille].link;
    def licence0= data[0].link;
    if(licenceTaille =='http://inspire.ec.europa.eu/metadata-codelist/LimitationsOnPublicAccess/noLimitations'){
        licence=licenceTaille
    }
    if(licence0 =='http://inspire.ec.europa.eu/metadata-codelist/LimitationsOnPublicAccess/noLimitations'){
        licence=licence0
    }
    return licence;
}

Probablement que le même type d'approximation est faisable pour la SpecificationConformance.

vbombaerts commented 2 years ago

Conformité donnée

Bloqué avec ce champ specificationConformance pour récupérer la valeur de pass de la conformité dont le title correspond à "1089/2010"

image

Ce serait plus facile avec du xml ;-p

En approximation (vérification de la première et de la dernière valeur)

Vérifie si la conformité au règlement 2010/1089 est déclarée dans la première ou dernière entrée des rapports de conformité. Si elle est déclarée, la valeur de la conformité par rapport à ce règlement (true/false) est renvoyée. Si le règlement est référencé mais la conformité n'est pas déclarée, renvoie la valeur unknown. Si le règlement n'est pas référencé ne renvoie rien.

if(params._source.specificationConformance!=null && params._source.specificationConformance.size()>0) {
    def data = params._source.specificationConformance;
    def taille = params._source.specificationConformance.size()-1;
    def conformance = "unknown";
    def conformanceSpecTaille = data[taille].link;
    def licenceSpec0= data[0].link;
    if(conformanceSpecTaille =='http://data.europa.eu/eli/reg/2010/1089' && data[taille].pass!=null){
        conformance=data[taille].pass
    }
    if(licenceSpec0 =='http://data.europa.eu/eli/reg/2010/1089' && data[0].pass!=null){
        conformance=data[0].pass
    }
    return conformance;
}

Edit du 13/12 - prise en compte de la conformité des services

if(params._source.specificationConformance!=null && params._source.specificationConformance.size()>0) {
        def data = params._source.specificationConformance;
        def taille = params._source.specificationConformance.size()-1;
        def conformance = "unknown";
        def conformanceSpecTaille = data[taille].link;
        def conformanceSpec0 = data[0].link;
        def INSPIRESpec = 'http://data.europa.eu/eli/reg/2010/1089';
        if (doc['resourceType'].value=='service'){
            INSPIRESpec = 'http://data.europa.eu/eli/reg/2009/976';
        }
        if(conformanceSpecTaille == INSPIRESpec && data[taille].pass!=null){
            conformance=data[taille].pass ;
        } else if(conformanceSpec0 == INSPIRESpec && data[0].pass!=null){
            conformance=data[0].pass ;
        }
return conformance ;
}
vbombaerts commented 2 years ago

Priority Dataset Regulation

Concatène les valeurs des mots-clés contenus dans le thésaurus des INSPIRE Priority Datasets

if(params._source.allKeywords!=null && params._source.allKeywords.INSPIREprioritydataset !=null && params._source.allKeywords.INSPIREprioritydataset.keywords!=null && params._source.allKeywords.INSPIREprioritydataset.keywords.size()>0) {
    def data = params._source.allKeywords.INSPIREprioritydataset.keywords;
    def taille = params._source.allKeywords.INSPIREprioritydataset.keywords.size();
    def priority = data[0].default;
    for(int i=1;i<taille;i++){
        priority = priority +  " | " + data[i].default ;
    }
    return priority;
}