# Vérifier le graphe et l'API

> **En bref :**
> Compter et contrôler le graphe, puis vérifier que l'API Apollo rend ce qu'il contient.
> Les noms de nœuds du code lu ne sont pas tous ceux de l'instance : une table de correspondance corrige les requêtes. Statut : **Non exécuté**. Inutile pour le POC de novembre.

## Pourquoi ce tutoriel

Avant de lire des données pour une vitrine, il faut savoir si le graphe contient ce qu'on y a chargé, et si l'API le restitue fidèlement. Étape 4 sur 4.

## Avant de commencer

- Structures, personnes et publications chargées ([étapes 2](./charger-structures-et-personnes) et [3](./enrichir-les-publications)).
- La clé `SOVISUPLUS_GRAPHQL_API_KEY` définie à l'[étape 1](./preparer-donnees-et-pile). **La même clé ouvre les lectures et les écritures** ([sécurité et droits](/03-crisalid/03-fonctionnement-transversal/securite-droits-donnees-personnelles)) : jamais de clé de production pour ces essais.

## Les noms du code et ceux de l'instance

Les requêtes des tutoriels ont d'abord été écrites d'après le code lu. L'instance de développement observée le 29 octobre 2026 n'emploie pas toujours les mêmes noms. Les requêtes de cette page et de l'étape 3 utilisent la colonne de droite.

| Dans le code lu | Observé sur l'instance (dev) | Statut |
| --- | --- | --- |
| `Document` (posé par IKG avec les labels de sous-type) | `ScholarlyPublication` et ses sous-types ; aucun `Document` | Observé sur instance (dev) ; équivalence **à confirmer** |
| `OrganizationUnit` | `OrganizationUnit`, à côté de `ResearchUnit` et `Institution` | Observé sur instance (dev) ; label des 235 unités à code RNSR **à confirmer** |
| `Organisation` (posé avec `ResearchUnit` et `Institution`) | Non relevé | À confirmer |
| `Person`, `Contribution`, `SourceRecord`, `Concept` | Mêmes noms | Observé sur instance (dev) |
| `MEMBER_OF`, `HAS_CONTRIBUTION`, `RECORDED_BY`, `HAS_SUBJECT` | Mêmes noms | Observé sur instance (dev) |
| `HAS_TITLE`, `Literal`, `HAS_IDENTIFIER`, `AgentIdentifier` | Non relevés | À confirmer |
| Requêtes Apollo `people`, `organizationUnits`, `documents` | API non interrogée sur l'instance | À confirmer |

## Étapes

### Étape 1 — Compter et contrôler le graphe

**Pourquoi :** comparer les volumes aux lignes chargées et aux notices moissonnées révèle ce qui s'est perdu en route.

```cypher
// Volumétrie par combinaison de labels
MATCH (n) RETURN labels(n) AS labels, count(*) AS nombre ORDER BY nombre DESC;

// Membres d'une unité et leurs publications, hors publications marquées à supprimer
MATCH (s {uid: $structure_uid})<-[:MEMBER_OF]-(p:Person)
OPTIONAL MATCH (p)-[:HAS_CONTRIBUTION]->(:Contribution)<-[:HAS_CONTRIBUTION]-(d:ScholarlyPublication)
WHERE coalesce(d.to_be_deleted, false) = false
RETURN p.display_name, count(DISTINCT d) AS publications;

// Rattachements avec et sans dates
MATCH (:Person)-[m:MEMBER_OF]->() RETURN count(m) AS total, count(m.start_date) AS avec_date;
```

La deuxième requête ne fixe pas le label de l'unité, faute de certitude sur la correspondance. Le filtre `to_be_deleted` écarte les publications marquées à supprimer mais non purgées ([suppressions](/03-crisalid/01-donnees/contrats-api-evenements#suppressions-non-propagées)). La troisième doit renvoyer `avec_date = 0` ([modèle de données](/03-crisalid/01-donnees/modele-de-donnees)).

### Étape 2 — Interroger Apollo

**Pourquoi :** un service tiers lirait les données par cette API, pas directement dans le graphe.

Apollo sert `/graphql` et `/health` ; l'en-tête `x-api-key` porte la clé. Les noms de requêtes sont ceux des tests d'intégration d'Apollo.

```bash
curl -s -X POST "http://localhost:${APOLLO_API_PORT}/graphql" \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${SOVISUPLUS_GRAPHQL_API_KEY}" \
  -d '{"query":"query { organizationUnits(where: { uid: \"<uid>\" }) { uid long_labels { language value } identifiers { type value } } }"}'
```

Le schéma expose `start_date` et `end_date` sur les rattachements, mais IKG ne les renseigne pas : ils devraient revenir vides (**à confirmer**).

## Ce que vous devez obtenir

- Des volumes par label cohérents avec les lignes chargées et les notices moissonnées.
- Pour une unité, ses membres et leur nombre de publications.
- Une réponse GraphQL pour l'unité demandée, avec ses libellés et identifiants.

## Limites

- **Non exécuté** : aucune requête de cette page n'a été lancée ; aucune réponse n'est montrée.
- La table de correspondance repose sur les labels relevés sur l'instance, pas sur une requête de cette page.
- L'extrait qui alimente le POC n'est pas produit par ce parcours.

## Et ensuite

C'est la fin du parcours. La spécification de l'extrait CRISalid utilisé par le POC fait foi dans [Extrait et comparatif du POC](/01-cadrage-saclay/02-scenarios/03-extrait-et-comparatif-du-poc). Pour vérifier une brique précise : les [contrôles exécutés](/03-crisalid/04-tutoriels/00-par-ou-commencer#les-huit-contrôles-et-leurs-résultats).

Révision lue : `crisalid-ikg` `ebdaae75`, `crisalid-apollo` `d377579a`.
