JDONREFv4 Query : Différence entre versions

De JDONREF Wiki
(Change de champ pour la recherche)
Ligne 286 : Ligne 286 :
 
Ces exemples ne présentent pas la prise en compte de la phonétique, qui n'intervient pas dans la notation. Deux requêtes qui disposent de la même phonétique ont les mêmes résultats.
 
Ces exemples ne présentent pas la prise en compte de la phonétique, qui n'intervient pas dans la notation. Deux requêtes qui disposent de la même phonétique ont les mêmes résultats.
   
=====Change de champ pour la recherche=====
+
=====Changer de champ pour la recherche=====
 
Si vous avez personnalisé votre mapping, il vous est peut-être nécessaire de modifier le champ utilisé par défaut pour la recherche.
 
Si vous avez personnalisé votre mapping, il vous est peut-être nécessaire de modifier le champ utilisé par défaut pour la recherche.
 
Il s'agit d'utiliser le paramètre default_field. Par défaut, il vaut fullName, mais vous pouvez le modifier.
 
Il s'agit d'utiliser le paramètre default_field. Par défaut, il vaut fullName, mais vous pouvez le modifier.

Version du 2 novembre 2014 à 20:43

La requête jdonrefv4 du plugin éponyme permet de chercher efficacement des adresses correspondant aux types de JDONREFv4.

Requête et résultat
 {
   "query": {
     "jdonrefv4" : {
        "value" : "24 BOULEVARD DE L HOPITAL 75 PARIS"
     }
   }
 }

Les résultats de la requête dépendent de la configuration du plugin.

En version 0.1beta, l'attribut sur lequel doit porter la recherche est "fullName".

En version 0.2, de nombreux champs sont utilisés (tous ceux qui sont indexés). Avec une requête POST du type :

 curl -XPOST 'http://localhost:9200/jdonref/_search' -d '{
   "query": {
     "jdonrefv4" : {
       "value" : "24 BOULEVARD DE L HOPITAL 75005 PARIS"
     }
   }
 }'

le résultat est de la forme :

 {
   "_shards":{
       "total" : 5,
       "successful" : 5,
       "failed" : 0
   },
   "hits":{
       "total" : 1,
       "hits" : [
           {
               "_index" : "jdonref",
               "_type" : "adresse",
               "_id" : "1",
               "_score" : 200.0,
               "_source" : {
                   "adr_id" : "123456789X",
                   "code_insee" : "75105",
                   "code_departement": "75",
                   "numero" : "24",
                   "type_de_voie" : "BOULEVARD",
                   "article" : "DE L",
                   "libelle" : "HOPITAL",
                   "commune" : "PARIS",
                   "code_postal" : "75005",
                   "ligne4": "24 BOULEVARD DE L HOPITAL",
                   "ligne6": "75005 PARIS",
                   "ligne7": "FRANCE",
                   "geometrie": { "type" :"point", "coordinates": [123, 456] }
               }
           }
       ]
   }
 }

Les types "voie", "commune", "departement", "pays" peuvent aussi être retournés. Les coordonnées sont en WGS84 par défaut dans la version 0.2, une version ultérieure permettra de le transformer à la volée en Lambert 93.

Filtres

Il est possible de la combiner avec des filtres, par exemple pour limiter les résultats à un département précis :

 {
   "filtered" : {
     "query": {
       "jdonrefv4" : {
         "value" : "24 BOULEVARD DE L HOPITAL 75 PARIS"
       }
     },
     "filter": {
       "term" : { "code_departement" : "75" }
     }
   }
 }

Ou de restreindre la recherche à une zone géographique :

 {
   "filtered" : {
     "query": {
       "jdonrefv4" : {
         "value" : "24 BOULEVARD DE L HOPITAL 75 PARIS"
       }
     },
     "filter" : {
       "geo_shape": {
          "geometrie" : {
            "shape" : {
               "type" : "enveloppe",
               "coordinates": [[13,53],[14,52]]
            }
          }
       }
     }
   }
 }
Fonctionnement

JDONREFv4Query s'appuie intégralement sur la requête PayloadCheckerSpanQuery avec le paramétrage décrit ci-après. Outre ce paramètrage, il découpe simplement la requête qui lui est donnée en token suivant l'analyzer de recherche du champ qui lui est donné (par défaut fullName). Si vous avez suivi JDONREFv4_plugin_GettingStarted votre analyzer de recherche sera alors jdonrefv4_search.


 { "type": "And", "checkers" : [
      { "type" : "Grouped" },
      { "type" : "Switch", "field": "_type", "clauses": {
          "poizon" : { "type": "And", "checkers" : [ // pour le poizon :
              { "type": "Or" , "checkers" : [ 
                  { "type" : "One", "payload" : 1}, // ligne1 ou
                  { "type" : "One", "payload" : 2}, // ligne4
                ]
              },
              { "type" : "BeforeAnother", "payloadbefore": 11, "another" : 2} // et numero avant ligne4
            ]
          },
          "adresse" : { "type": "And", "checkers" : [  // pour les adresses :
              { "type" : "All", "payload": 11},        // numero complet
              { "type" : "One", "payload" : 2},        // un élément de ligne4
              { "type" : "BeforeAnother", "payloadbefore": 11, "another" : 2} // numero avant ligne4
            ]
          },
          "voie" : { "type": "And", "checkers" : [  // pour les voies :
              { "type" : "One", "payload" : 2},        // un élément de ligne4
            ]
          },
          "commune" : { "type": "And", "checkers" : [  // pour les communes :
              { "type": "Or" , "checkers" : [ 
                  { "type" : "One", "payload" : 5}, // un élément de la commune ou
                  { "type": "Or" , "checkers" : [ 
                      { "type" : "One", "payload" : 8}, // un code département ou
                      { "type" : "One", "payload" : 4}, // un code arrondissement ou
                      { "type" : "One", "payload" : 3}, // un code postal ou
                      { "type" : "One", "payload" : 7}, // un code insee ou
                      { "type" : "One", "payload" : 6}  // un code insee de la commune ou
                    ]
                  }
                ]
              }
            ]
          }
          "departement" : { "type": "And", "checkers" : [  // pour les départements :
                  { "type" : "One", "payload" : 8} // un élément du code département
            ]
          }
          "pays" : { "type": "And", "checkers" : [  // pour les départements :
                  { "type" : "One", "payload" : 9} // un élément de la ligne7
            ]
          }
        }
      }
   ]
 }

Ce qui signifie plus clairement que les types suivant ne sont retournés en résultat que lorsque les filtres spécifiés sont vérifiés :

type filtres
poizon un élément de la ligne1 ou un élément de la ligne 4
adresse le numéro exact présent devant un ou des éléments de la ligne 4
voie un élement de la ligne 4
commune un élément de la commune ou un code postal, insee, département, arrondissement voire le code insee de la commune
departement le code département
pays un élément de la ligne7

Et que seuls les résultats dont les éléments sont regroupés sont retournés. Par exemple, la recherche de "230 RUE DE L HOPITAL" ne retournera pas "230 BIS RUE DE L HOPITAL" car le numéro exact n'a pas été spécifié. La recherche de "PARIS" ne retournera jamais "BOULEVARD DE L HOPITAL 75013 PARIS" car aucun élément de la ligne4 n'a été spécifié. etc ...

A noter que les payloads utilisés dans ces checkers sont ceux correspondant à la clause "transform" des mappings proposés.

Modes (mode bulk - en attente de réimplémentation)

Le mode bulk s'active simplement en utilisant le paramètre "mode" avec la valeur "bulk" de la sorte :

 {
   "query": {
     "jdonrefv4" : {
        "value" : "24 BOULEVARD DE L HOPITAL 75 PARIS",
        "mode": "bulk"
     }
   }
 }

Le paramètre mode prend deux valeurs actuellement.

  1. "autocomplete", il s'agit du mode par défaut, le calcul de la note correspond à la somme de la note des termes trouvés
  2. "bulk", la note de l'autocomplete est divisée par la somme des termes qui auraient pu être trouvés, rapporté sur 200.
Exemples de calcul en mode bulk

Les exemples qui suivent ne sont pas exhaustifs mais présentent le comportement recherché par la requête en mode bulk. La note donnée ici est indicative, car en réalité elle s'appuie sur la fréquence des termes recherchés et trouvés, suivant la logique du moteur à indexation inverse.

requête résultat note indicative calcul
130 RUE REMY DUHEM 59500 DOUAI 130 RUE REMY DUHEM 59500 DOUAI FRANCE 200 Tous les éléments de ligne4, code postal, et commune sont présents. Le pays est absent, mais son poids est de 0.
130 RUE REMY DUHEM 59 DOUAI 130 RUE REMY DUHEM 59500 DOUAI FRANCE 200 Tous les éléments de ligne4 et commune sont présents. Le code de département est correct. Le pays est absent, mais son poids est de 0.
130 RUE REMY 59500 DOUAI DUHEM 130 RUE REMY DUHEM 59500 DOUAI FRANCE 166 = ((50 + 50 + 50 + 50)*0.5/4 + 50 + 50 + 0)*200/150 Tous les éléments de ligne4 (50+50+50+50), code postal et commune (50+50) sont présents. Le pays est absent, mais son poids est de 0. L'ordre des éléments de la ligne 4 n'est pas respecté (*0.5). Le tout pondéré (/150) et ramené à 200 (*200).
RUE REMY DUHEM 59500 DOUAI RUE REMY DUHEM 59500 DOUAI FRANCE 200 Tous les éléments de ligne4, code postal, et commune sont présents. Le pays est absent, mais son poids est de 0.
RUE REMY DUHEM 59500 DOUAI 130 RUE REMY DUHEM 59500 DOUAI FRANCE 0 Tous les éléments du code postal et commune sont présents. Le pays est absent, mais son poids est de 0. Un malus est toutefois appliqué du fait de l'absence du numéro d'adresse dans la requête, ce qui attribue une note de 0 au total.
RUE REMY 59 DOUAI RUE REMY DUHEM 59500 DOUAI FRANCE 177 = ((50 + 50)/3 + 50 + 50 + 0) * 200 / 150 Le code postal et la commune sont présent (50 + 50). Le pays est absent, mais son poids est de 0. Seuls 2 termes sur 3 sont présents dans la ligne 4 ((50 + 50)/3). Le tout pondéré (/150) et ramené à 200 (*200).
RUE REMY 59 DOUAI RUE REMY DUHEM 59500 DOUAI FRANCE 177 = ((50 + 50)/3 + 50 + 50 + 0) * 200 / 150 Le code postal et la commune sont présent (50 + 50). Le pays est absent, mais son poids est de 0. Seuls 2 termes sur 3 sont présents dans la ligne 4 ((50 + 50)/3). Le tout pondéré (/150) et ramené à 200 (*200).
RUE REM DUH 59 DOUAI RUE REMY DUHEM 59500 DOUAI FRANCE 163 = ((50*75/100 + 50*60/100)/3 + 50 + 50 + 0) * 200 / 150 Le code postal et la commune sont présent (50 + 50). Le pays est absent, mais son poids est de 0. Seuls 2 termes sur 3 sont présents dans la ligne 4, et partiels ((50*75/100 + 50*60/100)/3). Le tout pondéré (/150) et ramené à 200 (*200).
59500 DOUAI 59500 DOUAI FRANCE 200 Le code postal et la commune sont présent. Le pays est absent, mais son poids est de 0.
59500 DOUAI RUE REMY DUHEM 59500 DOUAI FRANCE 133 = (0 + 50 + 50 + 0) * 200 / 150 Le code postal et la commune sont présent (50+50). La ligne 4 est absente (0). Le pays est absent, mais son poids est de 0. Le tout pondéré (/150) et ramené à 200 (*200).
59505 DOUAI 59500 DOUAI FRANCE 100 = (0 + 50 + 0) * 200 /100 La commune est présente (50), mais le code postal est faux (0). Le pays est absent, mais son poids est de 0. NB: pour améliorer cette note (le code postal est très proche), une évolution du TokenFilter de JDONREF devrait être effectuée).
59 59 FRANCE 200 Le code département est présent.
FRANCE FRANCE 200 La ligne 7 est présente.

Ces exemples ne présentent pas la prise en compte de la phonétique, qui n'intervient pas dans la notation. Deux requêtes qui disposent de la même phonétique ont les mêmes résultats.

Changer de champ pour la recherche

Si vous avez personnalisé votre mapping, il vous est peut-être nécessaire de modifier le champ utilisé par défaut pour la recherche. Il s'agit d'utiliser le paramètre default_field. Par défaut, il vaut fullName, mais vous pouvez le modifier. Attention à ce que votre champ contienne bien les payloads attendus par les checkers de la requête.

{
  "query": {
    "jdonrefv4" : {
       "value" : "24 BOULEVARD DE L HOPITAL 75 PARIS",
       "default_field" : "fullName"
    }
  }
}
Optimisation

Si vous avez réparti vos types sur de multiples index (ce qui est conseillé pour les communes, pays et départements qui nécessite un sharding de 1 pour éviter les effets de bords), le paramètre "maxSizePerType" vous permettra de filtrer les requêtes sur les adresses ou les voies qui seraient en trop grand nombre. Par exemple, une requête comme

 {
   "query": {
     "jdonrefv4" : {
        "value" : "RUE"
     }
   }
 }

retourne un très grand nombre de documents sur l'ensemble des index. Dans la France entière, il y a environ 695 000 documents qui disposent du terme 'RUE'. La requête prend alors environ (sur mon environnement de test) 2 minutes de calcul, même une fois en cache. Ces performances sont liées au très grand nombre de document à parcourir et à traiter avant de retourner le résultat. Toutefois, il existe des pays et des communes correspondant à ce terme, et il pourrait être utile d'obtenir ces réponses !

Si vous avez segmenté vos types par index, la requête :

 {
   "query": {
     "jdonrefv4" : {
        "value" : "RUE",
        "maxSizePerType": 50000
     }
   }
 }

ne retournera pas les résultats de type "adresse", ni même ceux de type "voie" dont la quantité est supérieure à 50000 (chacun pris séparemment, tout dépend de l'organisation de vos index). Seuls les pays et communes seront alors retournées, en quantité raisonnable.

Dans une requête multi-terme, c'est la fréquence du terme le moins fréquent qui est pris en compte.

J'insiste sur le fait que ce paramètre n'est valable que si les types sont répartis sur plusieurs index. Lorsqu'ils sont dans le même index, la requête n'est pas en mesure de faire la différence entre les types de manière efficace.

Effets de bord

Les exemples présentés ci-dessus induisent nécessairement des effets de bords compréhensibles sur certaines recherches.

Par exemple :

  1. Il ne faut pas s'attendre à trouver comme meilleur résultat l'avenue de France en effectuant une recherche sur le seul mot clé "FRANCE". C'est bien entendu le pays qui aura la meilleure note ...