Langage de requêtes MDM et accès aux données REST

EnrichVersion
6.4
EnrichProdName
Talend Data Fabric
Talend MDM Platform
task
Gouvernance de données > Récupération de données
Gouvernance de données > Consolidation de données
EnrichPlatform
Talend MDM Server
Talend MDM Web UI

Langage de requêtes MDM et accès aux données REST

La solution MDM de Talend propose une API REST qui permet aux utilisateurs de réaliser plus facilement des opérations de type CRUD (Create/Request/Update/Delete) sur des enregistrements MDM.

Cet article est principalement axé sur les opérations de lecture et d'écriture de l'API REST de MDM et donne des exemples de requêtes simples et plus complexes que vous pouvez inclure aux appels de l'API REST.

Cet article est basé sur la version 6.0 et suivantes de la solution MDM de Talend.

API REST

L'API REST de la solution MDM de Talend est une API moderne destinée aux développeurs. Elle simplifie les interfaces avec MDM et permet ainsi aux développeurs d'interagir plus facilement et directement avec les données MDM.

Talend MDM Web UI fournit un accès à la documentation des ressources REST de MDM. Elle vous permet de consulter la syntaxe du langage de requêtes ainsi que les paramètres associés et de tester l'exécution des opérations.

Vous pouvez également intégrer l'API pour les données et l'API pour les transactions. Pour plus d'informations, consultez Intégration de l'API pour les transactions.

Création d'un enregistrement

Vous pouvez créer un nouvel enregistrement dans le conteneur de données spécifié.

Requête

POST /data/{containerName}

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}?container={containerType}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez créer un nouvel enregistrement de données.
  • containerType : Il s'agit d'une valeur String qui représente le type de conteneur de données. La valeur est soit ‘MASTER’ (par défaut), soit ‘STAGING’.

En-têtes

  • Content-Type : application/xml ou text/xml
  • Authorization : schéma d'authentification basique (Basic)

Corps de la requête

Représentation XML de l'enregistrement de données que vous souhaitez créer.

Corps de la réponse

Aucun contenu.

Code de la réponse

200 - Si l'opération est exécutée avec succès, l'enregistrement de données est écrit dans le conteneur de données spécifié.

Lecture d'enregistrements

Vous pouvez lire des enregistrements de données dans le conteneur de données spécifié.

Vous pouvez également récupérer un snapshot d'un enregistrement MDM spécifique et parcourir l'historique des enregistrements. Pour plus d'informations, consultez l'article MDM Time Machine (en anglais).

Requête

PUT /data/{containerName}/query

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}/query?container={containerType}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez lire des enregistrements de données.
  • containerType : Il s'agit d'une valeur String qui représente le type de conteneur de données. La valeur, qui n'est pas sensible à la casse, est soit ‘MASTER’ (par défaut), soit ‘STAGING’.

Corps de la requête

Pour plus d'informations sur le langage de requêtes, consultez Clauses SELECT.

En-têtes

  • Content-Type : doit être application/json.
  • Authorization : schéma d'authentification basique (Basic)
  • Accept : application/xml ou application/json. L'en-tête Accept dit au serveur de retrourner du contenu JSON ou XML. Par défaut, le résultat est retourné au format JSON.

Corps de la réponse

Enregistrement(s) de données interrogé(s) du conteneur de données spécifié.

Mise à jour d'un enregistrement

Vous pouvez mettre à jour un enregistrement de données en intégralité dans le conteneur de données spécifié.

Requête

PUT /data/{containerName}

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}?container={containerType}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez mettre à jour un enregistrement de données.
  • containerType : Il s'agit d'une valeur String qui représente le type de conteneur de données. La valeur est soit ‘MASTER’ (par défaut), soit ‘STAGING’.

Corps de la requête

Représentation XML du nouvel enregistrement de données que vous souhaitez utiliser pour remplacer l'enregistrement existant.

Élément(s) de l'identifiant dans le corps de la requête qui détermine(nt) l'enregistrement à mettre à jour.

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la réponse

Aucun contenu.

Code de la réponse

200 - Si l'opération est exécutée avec succès, l'enregistrement de données est remplacé dans son intégralité par les données fournies. Si vous souhaitez conserver des valeurs existantes, utilisez plutôt l'opération de mise à jour partielle. Pour plus d'informations, consultez Mise à jour partielle d'un enregistrement.

Mise à jour partielle d'un enregistrement

Vous pouvez mettre à jour partiellement un enregistrement de données dans le conteneur de données spécifié.

Requête

PATCH /data/{containerName}

Même si "PATCH" est un verbe HTTP valide, tous les outils REST ne le supportent pas. Pour plus d'informations, consultez http://stackoverflow.com/questions/4260084/testing-tools-for-rest-that-support-http-patch (en anglais).

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}?container={containerType}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez mettre à jour partiellement un enregistrement de données.
  • containerType : Il s'agit d'une valeur String qui représente le type de conteneur de données. La valeur est soit ‘MASTER’ (par défaut), soit ‘STAGING’.

Corps de la requête

Représentation XML du nouvel enregistrement de données que vous souhaitez utiliser pour remplacer l'enregistrement existant.

Élément(s) de l'identifiant dans le corps de la requête qui détermine(nt) l'enregistrement à mettre à jour.

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la requête

Aucun contenu.

Code de la réponse

200 - Si l'opération est exécutée avec succès, l'enregistrement de données, identifié par les éléments de l'ID, est mis à jour partiellement en fonction des données fournies.

Suppression d'un enregistrement (par ID)

Vous pouvez supprimer un enregistrement de données par ID spécifié.

Requête

DELETE /data/{containerName}/{type}/{id}

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}/{type}/{id}

Par défaut, une opération de suppression d'un enregistrement par ID génère une entrée dans le rapport UpdateReport.

Cependant, pour éviter qu'une entrée ne se génère dans le rapport UpdateReport, ajoutez le paramètre de requête 'updateReport=false' dans l'URL de la requête. Par exemple, http://localhost:8180/talendmdm/services/rest/data/Customer/Address/1?updateReport=false.

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez supprimer un enregistrement de données.
  • type : Il s'agit d'une valeur String qui spécifie le nom de l'entité dans laquelle vous souhaitez supprimer un enregistrement de données.
  • id : Spécifie l'ID de l'enregistrement de données à supprimer. Pour des ID composés, utilisez le point comme séparateur. Par exemple, pour supprimer une instance Address ayant pour ID "1" dans le conteneur de données Customer, utilisez http://localhost:8180/talendmdm/services/rest/data/Customer/Address/1. Pour supprimer une instance Address ayant pour ID "1" et "2", utilisez http://localhost:8180/talendmdm/services/rest/data/Customer/Address/1.2.

Corps de la requête

Aucun contenu.

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la réponse

Aucun contenu.

Code de la réponse

200 - Si l'opération est exécutée avec succès, l'enregistrement de données spécifié par les éléments de l'ID est supprimé.

Suppression d'un enregistrement (par requête)

Vous pouvez supprimer un ou plusieurs enregistrement(s) de données correspondant à la requête fournie.

Requête

PUT /data/{containerName}/delete

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}/delete

Les opérations de suppression des enregistrements par requête ne génèrent aucune entrée dans le rapport UpdateReport.

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez supprimer les enregistrements de données interrogés.

Corps de la requête

Requête au format JSON. Pour plus d'informations, consultez Clauses SELECT.

Par exemple, pour supprimer toutes les instances de Type1, utilisez la requête suivante :

{
  "select": {
    "from": ["Type1"]
  }
}

Pour supprimer les instances de Type1 où la valeur de Type1/value1 est supérieure à 1, utilisez la requête suivante :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "gt": [
        {"field": "Type1/value1"},
        {"value": "1"}
      ]
    }
  }
}

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la réponse

Aucun contenu.

Code de la réponse

200 - Si l'opération est exécutée avec succès, tous les enregistrements correspondant à la requête fournie sont supprimés.

Obtention des ID uniques dans tous les documents

Vous pouvez obtenir des ID uniques dans tous les documents.

Requête

GET /data/{containerName}/documents/uniqueIds

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}/documents/uniqueIds?type={typeName}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez obtenir des ID uniques dans tous les documents.
  • containerType : Il s'agit d'une valeur String qui représente le type de conteneur de données. La valeur est soit ‘MASTER’ (par défaut), soit ‘STAGING’.
  • typeName : Il s'agit d'une valeur String qui spécifie le nom de l'entité.

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la requête

Aucun contenu.

Corps de la réponse

Tableau d'ID uniques des documents de toutes les entités ou de l'entité spécifiée.

Par exemple, utilisez http://localhost:8180//talendmdm/services/rest/data/Product/documents/uniqueIds?type=Product pour retourner les ID uniques des documents de l'entité Product uniquement :

[
  "Product.Product.1",
  "Product.Product.2"
]

Code de la réponse

200 - Si l'opération est exécutée avec succès, les ID uniques des documents de toutes les entités ou de l'entité spécifiée sont retrounés dans un tableau.

Obtention d'une chaîne de caractères XML d'un document

Vous pouvez obtenir une chaîne de caractères XML d'un document.

Requête

GET /data/{containerName}/documents/{uniqueId}

URL de la requête

http://{serverurl}/talendmdm/services/rest/data/{containerName}/documents/{uniqueId}?encoding={encoding}

Paramètres de la requête

  • containerName : Il s'agit d'une valeur String qui spécifie le nom du conteneur de données dans lequel vous souhaitez obtenir une chaîne de caractères XML d'un document.
  • uniqueId : Il s'agit d'une valeur String qui représente l'ID unique du document.
  • encoding : La valeur par défaut est UTF-8 et représente le jeu de caractères du résultat.

En-têtes

  • Authorization : schéma d'authentification basique (Basic)

Corps de la requête

Aucun contenu.

Corps de la réponse

Chaîne de caractères qui représente l'enregistrement correspondant à l'ID fourni.

Par exemple, si vous utilisez http://localhost:8180/talendmdm/services/rest/data/Product/documents/Product.Product.S1?encoding=UTF-8, la chaîne de caractères suivante est retournée :

<ii><c>Product</c><dmn>Product</dmn><dmr/><sp/><t>1484275339047</t><taskId>null</taskId><i>S1</i><p><Product><Id>S1</Id><Name>Shirt</Name><Description>A Shirt</Description><Features><Sizes><Size>Small</Size></Sizes><Colors><Color>White</Color></Colors></Features><Price>11.99</Price><Family>[1]</Family><OnlineStore>Talend Shop@@http://www.cafepress.com/Talend.231035933</OnlineStore><Stores></Stores></Product></p></ii>
.

Code de la réponse

200 - Si l'opération est exécutée avec succès, l'enregistrement correspondant à l'ID fourni est retourné sous la forme d'une chaîne de caractères.

Langage de requêtes

Dans les appels de l'API REST, vous pouvez utiliser le langage de requêtes pour réduire le nombre d'enregistrements de données correspondant à la requête, trier les résultats de requêtes ou exécuter d'autres fonctions selon vos besoins.

Clauses SELECT

Vous pouvez utiliser des clauses SELECT basiques dans les appels de l'API REST.

Sélection de toutes les instances d'une entité

Vous pouvez interroger toutes les instances d'une entité. Par exemple, pour retourner toutes les instances des enregistrements de "Type1", utilisez la requête :

{
  "select": {
    "from": ["Type1"]
  }
}

L'élément "from" constitue un type de tableau, vous permettant de sélectionner plusieurs types. Cela ne signifie pas que la requête peut retourner toutes les instances de Type1 et de Type2. Le tableau est utilisé pour des jointures.

Pagination : début et limite

La pagination peut être nécessaire dans certains cas d'utilisation, tels que la construction d'une table. Elle peut être réalisée à l'aide des éléments "start" et "limit".

Par exemple, pour retourner les résultats commençant avec la première instance de "Type1" (index à 0), ainsi que les 10 instances suivantes, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "start": 0,
    "limit": 10
  }
}
Prenez en compte les points suivants :
  • L'exécution standard de telles requêtes implique la création d'une liste de limites de taille sur le serveur. Si vous spécifiez une valeur élevée, des problèmes de performances ou une erreur de type OutOfMemoryError peuvent survenir. Par conséquent, assurez-vous d'utiliser la pagination avec des valeurs relativement basses pour l'élément limit.

  • Pour le code MDM, un élément limit ayant pour valeur Integer.MAX_VALUE (2^31 -1) n'indique aucune limite ("no limit"). Assurez-vous d'utiliser une stratégie de streaming plutôt qu'une liste de résultats. Cependant, cela signifie qu'une limite de (2^31 - 2) essayera de créer une liste de cette taille (causant généralement une erreur de type OutOfMemoryError).

Sélection des valeurs de champs

Plutôt que d'interroger l'enregistrement en entier, vous pouvez interroger un seul de ses champs.

Par exemple, pour retourner des valeurs du champ "id" de type "Type1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/id"}
    ]
  }
}

Pour sélectionner plus d'un champ, répétez l'élément "field". Par exemple, pour retourner des valeurs des champs "id", "value1" et "value2" pour chaque enregistrement de "Type1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/id"},
      {"field": "Type1/value1"},
      {"field": "Type1/value2"}
    ]
  }
}

Renommage (aliasing)

Pour des raisons client ou de nommage, vous souhaitez nommer différemment l'élément retourné. Ce type de renommage (aliasing) peut aider à différencier des valeurs en cas de problèmes de noms. Cette action peut être réalisée à l'aide de l'élément "alias".

Par exemple, pour retourner toutes les valeurs du champ "id" de toutes les instances de Type1, mais à la place de mettre des valeurs à l'intérieur d'un élément "id", l'élément entourant est nommé "a", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/id"},
      {
        "alias": [
          {"name": "a"},
          {"field": "Type1/id"}
        ]
      }
    ]
  }
}

Par exemple, utilisez la requête suivante pour retourner les résultats de "Type1/containedField1/value1" mis dans "v1" et "Type1/containedField2/value1" mis dans "v2", en évitant ainsi l'éventuel problème de noms. Ce problème aurait été retourné si "Type1/containedField1/value1" et "Type1/containedField2/value1" avaient été mis tous les deux dans un élément "value1" :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {
        "alias": [
          {"name": "v1"},
          {"field": "Type1/containedField1/value1"}
        ]
      },
      {
        "alias": [
          {"name": "v2"},
          {"field": "Type1/containedField2/value1"}
        ]
      }
    ]
  }
}

Valeurs de champs distinctes

Vous pouvez utiliser le mot-clé "distinct" pour obtenir toutes les valeurs distinctes pour le champ d'une entité.

Par exemple :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"distinct": {"field": "Type1/value1"}}
    ]
  }
}

Cette requête retourne toutes les valeurs distinctes pour le champ "value1" dans le type "Type1".

Vous pouvez également nommer différemment un résultat à l'aide de l'élément "alias". Par exemple :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {
        "alias": [
          {"name": "a0"},
          {"distinct": {"field": "Type1/value1"}}
        ]
      }
    ]
  }
}

Cette requête retourne toutes les valeurs distinctes pour le champ "value1", mais à l'intérieur d'un élément nommé "a0".

Compte

Vous pouvez compter le nombre de résultats retournés par une requête.

Par exemple, pour compter le nombre d'instances de Type1 disponibles, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"count": {}}
    ]
  }
}

Vous pouvez également associer l'opération de compte à des conditions afin de compter le nombre d'instances correspondant au critère spécifié.

Par exemple, pour retourner le nombre d'instances de Type1 ayant une valeur supérieure à 1 pour le champ "value1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"count": {}}
    ],
    "where": {
      "gt": [
        {"field": "Type1/value1"},
        {"value": "1"}
      ]
    }
  }
}

Le compte peut également être utilisé dans des clauses ORDER_BY.

Maximum et minimum

Vous pouvez sélectionner la valeur maximale et/ou minimale d'un champ dans une entité.

Par exemple, pour récupérer la valeur la plus faible du champ "id" dans l'entité Type1, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"min": {"field": "Type1/id"}}
    ]
  }
}

Par exemple, pour récupérer la valeur la plus élevée du champ "id" dans l'entité Type1, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"max": {"field": "Type1/id"}}
    ]
  }
}

Par exemple, pour récupérer la valeur la plus élevée et la plus faible du champ "id" dans Type1, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"max": {"field": "Type1/id"}},
      {"min": {"field": "Type1/id"}}
    ]
  }
}

Tri par valeur de champ

Vous pouvez utiliser autant de clauses "order_by" que nécessaire dans une requête pour configurer l'ordre de tri dans le résultat retourné, soit par ordre décroissant ou croissant.

Par exemple, pour sélectionner toutes les instances de Type1 et trier les résultats par ID (du plus élevé au plus faible) et par valeur de champ "value1" (du plus faible au plus élevé), utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "order_bys": [
      {
        "order_by": [
          {"field": "Type1/id"},
          {"direction": "DESC"}
        ]
      },
      {
        "order_by": [
          {"field": "Type1/value1"},
          {"direction": "ASC"}
        ]
      }
    ]
  }
}

Tri par occurrence de valeur de champ

Vous pouvez également trier par occurrence de valeur de champ pour retourner la valeur la plus fréquente en premier jusqu'à la valeur la moins fréquente (en cas de tri par ordre décroissant "DESC").

Par exemple, cette requête permet de retourner de la valeur la plus fréquente à la valeur la moins fréquente pour le champ "value1" :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/value1"},
    ],
    "order_bys": [
      {
        "order_by": [
          {"count": {"field": "Type1/value1"}},
          {"direction": "DESC"}
        ]
      }
    ]
  }
}

Vous pouvez également inclure un champ "limit" dans la requête pour obtenir les N valeurs les plus fréquentes.

Par exemple, cette requête permet d'obtenir les 10 valeurs les plus fréquentes :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/value1"},
    ],
    "order_bys": [
      {
        "order_by": [
          {"count": {"field": "Type1/value1"}},
          {"direction": "DESC"}
        ]
      }
    ],
    "limit": 10
  }
}

Conditions

Comparaisons de valeurs (=, <, <=, >, >=)

Par exemple, utilisez la requête ci-dessous pour retourner toutes les instances de Type1 dont la valeur "id" vaut 1 :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"field": "Type1/id"},
        {"value": "1"}
      ]
    }
  }
}

Prenez en compte les points suivants :

  • Il n'existe aucune valeur de saisie pour l'élément "value". Le type de la valeur est choisi par le serveur MDM en fonction du type de champ. Si "id" est de type string, MDM interprète la valeur comme une chaîne de caractères ; si "id" est de type integer, MDM interprète la valeur comme un nombre entier. Il est important que la valeur soit correcte pour le type de l'élément, par exemple Type1/id = "abc" est incorrecte si l'ID est de type integer.
  • La structure est toujours la suivante : "operand": { field, value }.

Les opérandes suivants peuvent être utilisés :

Opérande du langage de requêtes

Siginification

eq

égal à

gt / gte

supérieur à/supérieur ou égal à

lt / lte

inférieur à/ inférieur ou égal à

startsWith

commence par

contains

contient

Condition sur les index

Vous pouvez spécifier un index pour votre condition, si le champ est un élément répétable. L'index vaut 0.

Par exemple, pour retourner toutes les instances de Type1 dont la seconde valeur du champ "list" est égale à "1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"index": [
          {"field": "Type1/list"},
          1
        ]},
        {"value": "1"}
      ]
    }
  }
}

Conditions entre champs

Vous pouvez utiliser des conditions entre différents champs. Généralement, seul "eq" (EQUALS) est supporté pour de telles comparaisons.

Par exemple, pour retourner les instances de Type1 dont la valeur "id" est égale à "value1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"field": "Type1/id"},
        {"value": {"field": "Type1/value1"}}
      ]
    }
  }
}

Opérateurs logiques

Pour permettre des requêtes plus complexes, des opérateurs booléens (and/or/not) peuvent être inclus. La structure est similaire à ce qui a été présenté précédemment "operator": { left, right }left et/ou right peuvent également être des opérateurs logiques.

Par exemple, pour retourner toutes les instances de Type1 où "id = 1 OR value1 = 0", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "or": [
        {
          "eq": [
            {"field": "Type1/id"},
            {"value": "1"}
          ]
        },
        {
          "eq": [
            {"field": "Type1/value1"},
            {"value": "0"}
          ]
        }
      ]
    }
  }
}

Un opérateur logique binaire (and/or) doit forcément avoir deux enfants. Par exemple, vous pouvez écrire une condition avec "a OR b OR c" :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "or": [
        {
          "eq": [
            {"field": "Type1/id"},
            {"value": "1"}
          ]
        },
        {
          "or": [
            {
              "eq": [
                {"field": "Type1/id"},
                {"value": "2"}
              ]
            },
            {
              "eq": [
                {"field": "Type1/value1"},
                {"value": "4"}
              ]
            }
          ]
        }
      ]
    }
  }
}

Vous pouvez également mélanger les opérateurs logiques. Il n'existe aucune ambiguïté dans l'ordre d'évaluation des conditions.

Par exemple, pour retourner toutes les instances de Type1 où "(id = 1 OR (id = 2 and value1 = 4))", utilisez la requête qui mélange and et or :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "or": [
        {
          "eq": [
            {"field": "Type1/id"},
            {"value": "1"}
          ]
        },
        {
          "and": [
            {
              "eq": [
                {"field": "Type1/id"},
                {"value": "2"}
              ]
            },
            {
              "eq": [
                {"field": "Type1/value1"},
                {"value": "4"}
              ]
            }
          ]
        }
      ]
    }
  }
}  

Opérateur Not

L'opérateur Not est supporté et suit la structure suivante : "not": { condition }.

Par exemple, pour retourner toutes les instances de Type1 où la valeur "id" n'est pas égale à 1, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "not": {
        "eq": [
          {"field": "Type1/id"},
          {"value": "1"}
        ]
      }
    }
  }
}

Vous pouvez également utiliser l'opérateur Not dans une condition plus complexe. Par exemple :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "not": {
        "or": [
          {
            "eq": [
              {"field": "Type1/id"},
              {"value": "2"}
            ]
          },
          {
            "eq": [
              {"field": "Type1/id"},
              {"value": "4"}
            ]
          }
        ]
      }
    }
  }
}

Plein texte (dans le cadre du champ)

Le langage de requêtes inclut un support pour la recherche en plein texte.

Par exemple, pour réaliser une recherche en plein texte sur le champ "Type1/id" avec la valeur "1", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "full_text": [
        {"field": "Type1/id"},
        {"value": "1"}
      ]
    }
  }
}

La requête en plein texte fonctionne également sur les sous-éléments. Par exemple, si vous avez la structure type suivante :

Type1
  * id
  * element
    * value1
    * value2

Puis la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "full_text": [
        {"field": "Type1/element"},
        {"value": "1"}
      ]
    }
  }
}

Équivaut à :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "or": [
        {
          "full_text": [
            {"field": "Type1/element/value1"},
            {"value": "1"}
          ]
        },
        {
          "full_text": [
            {"field": "Type1/element/value2"},
            {"value": "1"}
          ]
        }
      ]
    }
  }
}

Plein texte (dans le cadre de l'entité)

Si vous ne souhaitez spécifier aucun champ, mais que vous recherchez une valeur dans l'entité, la requête suivante vous montre comment le faire :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "full_text": [
        {"value": "1"}
      ]
    }
  }
}

Si vous omettez de préciser le champ, MDM effectue la recherche en plein texte sur tous les champs de Type1.

Champs de métadonnées

MDM ajoute des champs "metadata" pour les enregistrements qu'il gère. Ces champs ne sont pas présents dans le modèle de données utilisateur, mais peuvent être utilisés dans la requête.

Les champs de métadonnées supportés sont :

  • taskId (aussi connu comme groupId)
  • timestamp (dernière date de modification)
  • groupSize

Pour le stockage de préparation, des champs de métadonnées supplémentaires existent :

  • Erreur (staging)
  • Source (staging)
  • Statut (staging)
  • Clé de bloc (staging)

Si la requête contient des champs "staging_" uniquement, vous pouvez rencontrer une erreur qui indique les expressions incompatibles. Les expressions incompatibles sont vérifiées dans les champs, les conditions, les expressions de tri et de jointure sélectionnés.

Obtention de valeurs de champs de métadonnées

Pour obtenir un champ de métadonnées, utilisez l'élément "metadata" plutôt que "field" dans les champs sélectionnés, comme l'exemple suivant le montre :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"metadata": "timestamp"},
      {"metadata": "task_id"},
      {"metadata": "group_size"},
      {"metadata": "staging_error"},
      {"metadata": "staging_source"},
      {"metadata": "staging_status"},
      {"metadata": "staging_blockkey"}
    ]
  }
}

Vous pouvez également mélanger les champs de l'entité et ceux de l'enregistrement :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"metadata": "timestamp"},
      {"metadata": "task_id"},
      {"field": "Type1/id"}
    ]
  }
}

Vous pouvez utiliser le mot-clé "distinct" pour les champs de métadonnées. Par exemple, pour retourner toutes les valeurs distinctes de "taskId" mises dans un élément nommé "distinctTaskId", utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {
        "alias": [
          {"name": "distinctTaskId"},
          {"distinct": {"metadata": "task_id"}}
        ]
      }
    ]
  }
}

Conditions incluant des champs de métadonnées

Vous pouvez inclure des champs de métadonnées dans des conditions. Quant aux champs sélectionnés, utilisez simplement l'élément "metadata" plutôt que "field". Par exemple :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"metadata": "task_id"},
        {"value": "1"}
      ]
    }
  }
}

Mise en cache

MDM peut mettre en cache les résultats de la requête. Dans ce cas, il garde la requête en cache et remet le résultat mis en cache chaque fois que cette requête est exécutée.

Par exemple, pour mettre en cache le résultat d'une requête, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"field": "Type1/id"},
        {"value": "1"}
      ]
    },
    "cache": true
  }
}

Par défaut, la valeur de l'élément "cache" est false, mais la requête est toujours valide :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"field": "Type1/id"},
        {"value": "1"}
      ]
    },
    "cache": false
  }
}

Un résultat mis en cache peut contenir au maximum 50 enregistrements. Lorsque la requête produit beaucoup trop de résultats, le log suivant s'affiche dans le log de MDM au niveau de DEBUG : Query is yielding more results than cache is allowed to keep, bypassing cache for query.

Jointure entre différents types

Les jointures sont un moyen de récupérer des données d'un autre type suivant les clés étrangères.

Par exemple, vous pouvez récupérer l'élément "Address's street" en suivant la clé étrangère entre les types Person et Address.

Voici un exemple de jointure simple :

{
  "select": {
    "from": [
      "Type1",
      "Type2",
    ],
    "fields": [
      {"field": "Type1/id"},
      {"field": "Type2/value1"}
    ],
    "joins": [
      {
        "from": "Type1/fk2",
        "on": "Type2/id"
      }
    ]
  }
}

Cette requête retourne tous les éléments "id" de Type1 ainsi que les éléments "value1" situés dans Type2. La jointure s'effectue en utilisant l'élément "fk2" dans Type1.

Vous pouvez également effectuer plusieurs jointures dans la requête. Par exemple :

{
  "select": {
    "from": [
      "Type1",
      "Type2",
      "Type3"
    ],
    "fields": [
      {"field": "Type1/id"},
      {"field": "Type2/value1"},
      {"field": "Type3/value1"}
    ],
    "joins": [
      {
        "from": "Type1/fk2",
        "on": "Type2/id"
      },
      {
        "from": "Type2/fk3",
        "on": "Type3/id"
      }
    ]
  }
}

Cette requête affiche la valeur "id" de Type1, la valeur "value1" de Type2 et la valeur "value1" de Type3. La valeur "value1" de Type3 est obtenue via une jointure entre Type1, Type2 et Type3.

Opérateurs liés à l'historique - opérateur “as of"

L'opérateur "as_of" vous permet de récupérer un enregistrement tel qu'il était à une date donnée.

Par exemple :

{
  "select": {
    "from": ["Type1"],
    "as_of": {
      "date": "1000"
    }
  }
}

L'opérateur "as of" n'échoue pas si aucun historique n'est disponible. À la place, il retourne l'enregistrement à son état actuel.

La navigation dans l'historique dépend du journal. Si vous insérez des données directement dans la base de données SQL ou si vous désactivez la création d'événements pour les composants tMDMOutput/tMDMDelete, vous n'aurez qu'un historique partiel.

MDM peut uniqument construire un historique des enregistrements basé sur les informations qu'il a stocké au niveau des mises à jour : si vous désactivez le journal pour des mises à jour, l'historique ne peut être complet et précis.

Par exemple, pour retourner toutes les instances de Type1 ayant comme valeur celle qu'elles avaient une seconde après le 1er janvier 1970 (1 000 ms après EPOCH), utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "as_of": {
      "date": "1970-01-01T00:00:01"
    }
  }
}

Raccourcis de navigation dans l'historique

Les éléments "date" pour les éléments "as_of" supportent des raccourcis utiles :

  • "yesterday" : il y a 24 heures.
  • "creation" : date de création de l'enregistrement. Lorsque vous utilisez l'élément "creation", vous ne pouvez pas utiliser le paramètre "swing". Autrement, vous devez vous attendre à ce qu'une erreur survienne.
  • "now" : date actuelle.

Par exemple, pour retourner toutes les instances de Type1 comme elles étaient hier (il y a 24 heures), utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "as_of": {
      "date": "yesterday"
    }
  }
}

Filtrage de l'historique (par ID)

Vous souhaitez filtrer les enregistrements de l'historique au lieu d'obtenir toutes les instances.

Par exemple, pour retourner l'instance de Type1 ayant comme valeur "id = 1", comme elle l'était au 1er janvier 1970, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "eq": [
        {"field": "Type1/id"},
        {"value": "1"}
      ]
    },
    "as_of": {
      "date": "1000"
    }
  }
}

Vous pouvez améliorer cette requête en utilisant toutes les conditions avec "as_of", vous permettant d'interroger les valeurs précédentes. Les conditions n'ont pas besoin d'être uniquement sur des éléments "id".

Par exemple, pour retourner l'instance de Type1 qui contenait "text" au 1er janvier 1970, utilisez la requête :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "contains": [
        {"field": "Type1/value"},
        {"value": "text"}
      ]
    },
    "as_of": {
      "date": "1000"
    }
  }
}

Cependant, cette requête rencontre des problèmes d'extensibilité, puisqu'elle peut forcer MDM à construire un jeu complet d'instances de Type1. Cela mène alors à des problèmes de mémoire, si des états sont calculés en mémoire.

Utilisation de jointure avec as_of

Vous pouvez utiliser l'élément "joins" dans une requête avec l'opérateur "as_of".

Par exemple, utilisez la requête ci-dessous pour retourner trois champs ("id", "value1", "value2") venant de deux types ("Type1", "Type2") :

{
  "select": {
    "from": [
      "Type1",
      "Type2"
    ],
    "fields": [
      {"field": "Type1/id"},
      {"field": "Type1/value1"},
      {"field": "Type2/value2"}
    ],
    "joins": [
      {
        "from": "Type1/fk2",
        "on": "Type2/id"
      }
    ],
    "as_of": {
      "date": "1000"
    }
  }
}

Les valeurs retournées ont les caractéristiques ci-dessous :

  • L'élément "as_of" retourne les valeurs de "Type1" comme elles étaient au 01/01/1970.
  • La valeur de la clé étrangère utilisée pour Type2 est la valeur de la clé étrangère au 01/01/1970.
  • Les valeurs pour Type2 sont celles au 01/01/1970.

Sécurité et rôles utilisateur

Rappelez-vous que la requête transmise au service n'est pas toujours celle que MDM exécute. Avant l'exécution de la requête, MDM réduit tous les éléments auxquels l'utilisateur connecté ne peut avoir accès, à savoir les champs, les conditions et les ordres de tri sélectionnés. Tous les éléments masqués aux utilisateurs sont retirés de la requête sans reporter d'erreur.

Par exemple :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/id"},
	  {"field": "Type1/secret_field"}
    ]
  }
}

Dans cet exemple, MDM retire automatiquement l'élément "secret_field" de la requête si l'utilisateur actuel (étant l'utilisateur connecté à l'API REST) n'a pas accès à l'élément "secret_field". Cependant, la requête exécutée actuellement est la suivante :

{
  "select": {
    "from": ["Type1"],
    "fields": [
      {"field": "Type1/id"}
    ]
  }
}

Autre exemple de ce genre de requêtes :

{
  "select": {
    "from": ["Type1"],
    "where": {
      "gt": [
        {"field": "Type1/secret_field"},
        {"value": "1"}
      ]
    }
  }
}

Cette requête est lue de la manière suivante "retourne toutes les instances de Type1 où la valeur secret_field de Type1 est supérieure à 1". Le résultat retourné doit être les instances de Type1 où secret_field > 1.

Cependant, si les rôles de l'utilisateur actuel ne lui donnent pas accès à l'élément "secret_field", la requête actuelle devient :

{
  "select": {
    "from": ["Type1"]
  }
}

Cette requête est lue de la manière suivante "retourne toutes les instances de Type1". Le résultat retourné doit être toutes les instances de Type1 car l'utilisateur actuel n'a pas accès à l'élément "secret_field".

Ceci empêche les utilisateurs dépourvus de droits d'accès de deviner indirectement les valeurs de l'élément "secret_field", en utilisant des conditions de valeurs sur ce champ.

Exemple d'exécution d'une opération GET HTTP avec l'API REST MDM dans Talend MDM Web UI

Dans Talend MDM Web UI, les utilisateurs ayant les droits d'accès peuvent utiliser le menu Tools pour accéder à la page de la documentation de l'API REST MDM basée sur Swagger et tester les opérations de l'API REST sur cette page, si nécessaire.

L'exemple suivant vous montre comment exécuter une opération avec l'API REST MDM pour lister toutes les clés primaires des enregistrements de données maître dans un conteneur sur le serveur MDM.

Avant de commencer

Assurez-vous d'avoir importé au préalable le projet démo MDM et créé plusieurs enregistrements de données maître pour l'entité Product du conteneur Product.

Procédure

  1. Ouvrez la page de la documentation de l'API REST dans Talend MDM Web UI.
  2. Dans la liste des opérations, sous la catégorie User data management, cliquez sur le lien GET qui est suivi par /data/{containerName}/{type} pour en afficher les détails. Vous pouvez également cliquer sur Lists all primary keys for container and type pour afficher les détails de l'opération.
  3. Dans la liste Container, sélectionnez Master.
  4. Dans le champ containerName, saisissez Product.
  5. Dans le champ type, saisissez Product.
  6. Cliquez sur Execute pour exécuter l'opération GET.

    L'URL de la requête HTTP, le corps, le code ainsi que les en-têtes de la réponse s'affichent. Dans cet exemple, toutes les clés primaires du conteneur Product sont listées.

  7. Pour vérifier le résultat d'exécution de cette opération GET, allez sur la page Master Data Browser. Recherchez ensuite les enregistrements de données maître du conteneur Product, puis confirmez que le résultat de l'exécution correspond au résultat de la recherche.

Intégration de l'API pour les transactions

L'API pour les transactions peut être intégrée à l'API pour les données.

Pour plus d'informations sur les transactions MDM, consultez Les transactions MDM.

Ajouter une requête REST à une transaction existante

Les modifications effectuées via l'API REST pour les données peuvent être ajoutées à une transaction créée via l'API pour les transactions.

Pour ajouter une requête REST à une transaction existante, configurez la valeur de l'en-tête HTTP personnalisé "transaction-id" avec l'identifiant de la transaction. Si l'identifiant de transaction fourni n'existe pas, il doit être créé.

Par exemple :
PUT /talendmdm/services/rest/transactions, crée une nouvelle transaction et retourne son id
POST /talendmdm/services/rest/data/Product (avec transaction-id configuré avec l'id retourné à l'étape 1), crée un nouveau produit mais ne commite pas les modifications dans la base de données
POST /talendmdm/services/rest/transactions/<id> commite les transactions et les modifications réalisées à l'étape 2

Cette fonctionnalité fonctionne également avec l'opération Insert de données par lots (/talendmdm/services/rest/data/Product/batch).