## Co-deduplicate

L'instance 
L'instance `co-deduplicate` utilise l'application ezmaster
[`lodex-workers-python`](https://github.com/Inist-CNRS/lodex-workers-python).

Elle permet de dédoublonner des notices biblographiques au format `Conditor` (bientot `Corhal`). 

Dans ce qui suit, nous décrirons le fonctionnement de l'algorithme de dédoublonnage.

### 1 - Choix des champs utiles
L'algorithme reçoit en entrée un couple de notices bibliographiques (Conditor) à valider automatiquement. </br> 
Une extraction des champs est effectuée. Les champs extraits sont ensuite regroupés en catégories. </br>
Ce sont entre autre :

| catégorie | champs utilisé |
| :---: | :---: |
| identifiant | doi, pmId, nnt |
| pagination | pageRange |
| volumaison | issue, volume |
| publication | issn, issn, eissn, title.meeting, title.journal, isbn, eisbn, teiBlob |
| titre |title.default, title.en, title.fr |

Avant la comparaison, un prétraitement des champ est effectué.</br>

**Remarque** : Le champ `idConditor` est rajouté automatiquement. 

### 2 - Comparaison des champs dans chaque catégorie

#### 2.1 La comparaison des champs
La comparaison entre les champs se fait selon 2 cas :

- **1er cas** : Les champs sont tous deux renseignés :</br>
    S'ils sont identiques, alors on retourne 1 sinon on retourne -1
- **2e cas** : Au moins un des champs n'est pas renseignés:</br>
    on retourne 0

On se retrouve pour chaque comparaison avec un nombre inclus dans {-1, 0, 1.

#### 2.2 La comparaison dans un catégorie
Dans chaque catégorie, les comparaisons se font selon une certaine hiérarchie. L'idée est de
commencer la comparaison avec les champs les plus pertinents vers les ceux qui le sont moins.</br>
On passe au champ suivant lorsque on a une donnée manquante dans l'un des champ en cours.</br>
Pour étayer, prenoms l'exmple de la catégorie `identifiant` (cf. tableau ci-dessous). le `DOI` étant un identifiant fort, c'est par celui-ci que nous commencerons les comparaisons.</br> Si les `DOI` sont renseignés identiques on retourne 1 s'ils ne sont pas identiques, on retourne -1. Si l'un des `DOI` n'est pas renseignés, on passe au champ suivant.</br>
On passe  au `pmId` (champ important mais d'une importance inférieur par rapport au `DOI`). On compare selon la règle définit plus haut; c'est à dire si les `pmId` sont renseignés et qu'ils sont identiques on retourne 1 sinon -1. </br> Si l'un des `pmId` n'est pas renseignés, on passera  au `nnt`.Il faut noter que le  `nnt` étant le dernier champ du group, si pour l'une des notices, il n'est pas renseigné, on retournera 0.

Ainsi, pour chaque catégorie, on a aussi un resultat qui peut être soit -1, soit 0 ou soit 1.
Après la compararison de toutes catégories, on a un quintuple de valeurs comprises entre -1, 0 et 1.

### 3 - La règle de décision
Une règle de décision disponible [ici](http://vxgit.intra.inist.fr:60000/RichText/co-deduplicates/blob/master/deduplicate/params.py)
a été éléboré. Elle valide ou pas le couple de notices suivant le quintuple cité plus haut. La règle de décision 
est un `objet` clé -valeur dans lequel les clés sont toutes les combinaisons possibles  de quintuple de -1, 0 et 1 et en valeur la décision prise par les experts metiers pour chaque quintuple.

### 5 - La décision finale
Selon la règle de décision, il en ressort soit la valeur `1` correspondant à doublon, `-1` non doublon et `0` à incertain.


## Interrogation du WebService 
### Configuration

Il faut préciser dans le fichier de configuration de l'instance qu'elle utilise des paquets nodes:

- `@ezs/analytics`
- `@ezs/basics`
- `@ezs/storage`
- `@ezs/analytics`


### Example d'utilisation : 
Prend un corpus de notices bibliographique conditor-compatible au format json et retourne un fchier json qui est tableau de d'objets. 
Ci-dessous, la requête d'entrée : 

```bash
cat <<EOF | curl -X POST --data-binary @- "https://co-deduplicate.services.inist.fr/v1/duplicate"
[
    {"id": 0,
    "value": {
        "volume": "43",
        "pageRange": "2109-2114",
        "duplicates": [{"sourceUid": "crossref$10.1007/s11664-014-2982-z", "sessionName": "CROSSREF_2021-01-05_2014_1", "rules": ["Article : 1ID:doi+TiC_ENG", "Article : 1ID:doi+TiC"], "source": "crossref", "idConditor": "1sZqglsAiAXBZMeTynDh6fL77"}],
        "sourceUid": "hal$hal-00994781",
        "issn": ["0361-5235"],
        "documentType": ["ART"],
        "isbn": [],
        "typeConditor": "Article",
        "eissn": ["1543-186X"],
        "title": {"default": "Unconventional thin-film thermoelectric converters : structure, simulation, and comparative study", "monography": "", "journal": "Journal of Electronic Materials", "en": "Unconventional thin-film thermoelectric converters : structure, simulation, and comparative study", "fr": "", "meeting": ""}, 
        "publicationDate": "2014", 
        "doi": "10.1007/s11664-014-2982-z", 
        "_score": 0.7896045, 
        "_sort": [12200877]
        }
    }
]
EOF
```
L'objet retourné a l'allure suivante : 

```bash
{
    "id" : 99,
    "value" : {
        "duplicates" : [
            {
                "idConditor": "P9g5UicgAaldJMle8cAX2BF06",
                "sourceUid": "hal$tel-01512658",
                "type": "Thèse",
                "source": "hal",
                "comment": "1id, 1title, typeConditor=thèse"
            }
        ]
    }
}
```
Il faut noter les résultats sont stockés dant l'objet la clé `value`. C'est un tableau d'objet. Dans ce cas ci, nous avons un seul doublonn retourner.
Si aucun doublon n'a été retrouvé, le tableau sera vide, Si y'en a plus d'un doublon retourné, il va de soit que le tableau retournera autant d'objets que de doublons retrouvés.   

