API GraphQL avec Microsoft Purview (préversion)

Importante

Cette fonctionnalité est actuellement en préversion. Les conditions d’utilisation supplémentaires des préversions de Microsoft Azure incluent des conditions juridiques supplémentaires qui s’appliquent aux fonctionnalités Azure en version bêta, en préversion ou qui ne sont pas encore mises en disponibilité générale.

Dans ce tutoriel, apprenez à interagir par programmation avec Microsoft Purview à l’aide de l’API GraphQL. Pour plus d’informations sur GraphQL en général, consultez cette introduction à GraphQL.

L’utilisation de GraphQL est similaire à l’utilisation des API REST, car vous envoyez une charge utile JSON à un point de terminaison de service. Toutefois, GraphQL nous permet de retourner des informations complètes en une seule extraction, ce qui élimine le besoin de plusieurs appels d’API.

GraphQL utilise également la récupération déclarative des données. La récupération déclarative des données est utile pour l’extraction sélective sur des champs tels quel’entité liée auterme/ de classification/ liée à l’entité d’origine. En utilisant GraphQL avec ces modèles de requête, nous pouvons optimiser la récupération des bases de données back-end et la transmission des données. Un bon exemple est « Obtenir une entité avec des entités associées filtrées, séparées par des alias ».

Avec sa fonctionnalité d’introspection, l’API GraphQL devient auto-descriptive, ce qui permet aux clients de récupérer les détails du schéma, tels que les requêtes, les types et les paramètres de requête disponibles. En savoir plus sur l’introspection.

Configuration requise

point de terminaison GraphQL

Pour toutes les demandes, vous pouvez envoyer une POST requête au point de terminaison suivant :

POST https://{{endpoint}}/datamap/api/graphql

Requête de base

Entité - Lister par GUID

query {
    entities(where: { guid: ["<guid1>", "<guid2>"] }) { #Values in the array are combined as a logical-OR.
        guid
        createTime
        updateTime
        typeName
        attributes
        name
        qualifiedName
        description
    }
}

Exemple de réponse :

{
    "data": {
        "entities": [
            {
                "guid": "9fb74c11-ac48-4650-95bc-760665c5bd92",
                "createTime": 1553072455110,
                "updateTime": 1553072455110,
                "typeName": "azure_storage_account",
                "attributes": {
                    "qualifiedName": "https://exampleaccount.core.windows.net",
                    "name": "ExampleStorageAccount",
                },
                "name": "ExampleStorageAccount",
                "qualifiedName": "https://exampleaccount.core.windows.net",
                "description": "Example Storage Account"
            }
        ]
    }
}

Interroger des entités par type et par nom qualifié

query {
    entities(
        where: {
            type: { typeName: ["<entityType1>", "<entityType2>"] }
            qualifiedName: { in: ["<qualifiedName1>", "<qualifiedName2>"] }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

L’opérateur in est utilisé pour interroger plusieurs noms qualifiés.

Les opérateurs possibles peuvent être exists|eq|ne|in|nin|gt|ge|lt|le. Vous trouverez plus de détails sur le schéma de serveur avec l’introspection.

Extraction de données déclaratives

Obtenir l’entité avec les champs sélectionnés

query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        businessAttributes
        qualifiedName
    }
}

Obtenir l’entité avec tous les champs

query {
    entities(where: { guid: "<guid>" }) {
        guid
        createTime
        createdBy
        updateTime
        updatedBy
        lastModifiedTS
        typeName
        attributes
        businessAttributes
        collectionId
        customAttributes
        hierarchyInfo {
            ...hierarchyInfoFields
        }
        labels
        sensitivityLabel {
            ...sensitivityLabelFields
        }
        source
        sourceDetails
        qualifiedName
        name
        description
        displayName
        userDescription
        classifications {
            ...classificationFields
        }
        relatedEntities {
            ...relatedEntitiesFields
        }
        assignedTerms {
            ...assignedTermsFields
        }
    }
}

Obtenir une entité avec des classifications

- avec toutes les classifications

query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        classifications {
            typeName
            attributes
        }
    }
}

- avec des classifications filtrées

query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        classifications(where: { type: { typeName: "<classificationType>" } }) {
            typeName
            attributes
        }
    }
}
query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        relatedEntities {
            relationshipAttributeName
            relationship {
                guid
                typeName
                attributes
            }
            entity {
                guid
                typeName
                qualifiedName
                attributes
            }
        }
    }
}
query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        relatedEntities(where: { relationshipAttributeName: "<relAttrName1>" }) {
            entity {
                guid
                typeName
                qualifiedName
                attributes
            }
        }
    }
}
query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        alias1: relatedEntities(where: { relationshipAttributeName: "<relAttrName1>" }) {
            entity {
                guid
                typeName
                attributes
            }
        }
        alias2: relatedEntities(where: { relationshipAttributeName: "<relAttrName2>" }) {
            entity {
                guid
                typeName
                attributes
            }
        }
    }
}

Obtenir une entité avec des termes de glossaire

- avec tous les termes du glossaire

query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        assignedTerms {
            confidence
            createdBy
            description
            expression
            steward
            source
            status
            term {
                qualifiedName
                name
                shortDescription
                longDescription
            }
        }
    }
}

- avec des termes de glossaire filtrés

query {
    entities(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        assignedTerms {
            confidence
            createdBy
            description
            expression
            steward
            source
            status
            term {
                qualifiedName
                name
                shortDescription
                longDescription
            }
        }
    }
}

Filtrage (préversion)

Les performances de la correspondance exacte pour « GUID » et « Qualified-Name » sont garanties dans les exemples fournis dans la section « requêtes de base ». Toutefois, il existe certaines limitations pour d’autres modèles de filtrage :

  • Filtrage sur les champs non indexés : les champs autres que GUID & nom qualifié ne sont actuellement pas indexés (comme exemple dans la section « Filtre simple »). Le filtrage sur des champs non indexés sans critères sur guid/nom qualifié entraîne une analyse de table et peut entraîner des problèmes de performances sur les jeux de données volumineux.
  • Filtrage imbriqué : comme pour les champs non indexés, le filtrage imbriqué peut entraîner des analyses de table, ce qui peut entraîner des problèmes de performances sur des jeux de données volumineux. Par exemple, la recherche d’une entité avec une classification/un terme/une entité liée.

Malgré ces limitations, ce modèle d’appel est supérieur au filtrage côté client et est actuellement utilisé par notre client interne.

Filtre simple

Interroger des entités par type et attributs système

query {
    entities(
        where: {
            type: { typeName: "<entityType>" }
            name: { eq: "<value>" }
            createTime: { timerange: LAST_7D }
            updateTime: { gt: "<timestamp>" }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Interroger des entités par type et attributs

query {
    entities(
        where: {
            type: { typeName: "<entityType>" }
            attribute: { field: "<attrName>",operator: eq, value: "<attrValue>" }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Interroger des entités par type et attributs métier

query {
    entities(
        where: {
            type: { typeName: "<entityType>" }
            businessAttribute: { field: "<BusinessMetadataName>.<BusinessAttributeName>", operator: eq, value: "<BizAttrValue>" }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Interroger des entités par collection

Actuellement, ce modèle de requête n’est pas pris en charge pour les sous-ensembles.

query {
    entities(
        where: {
            type: { typeName: "<entityType>" }
            collectionID: "<collectionId>"
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Combinaison de filtres

Les clés d’un object(map) sont combinées en tant qu’AND logique.

query {
    entities(
        where: {
            type: { typeName: "<entityType>" }
            or: [
                {
                    and: [
                        { attribute: { field: "<attrName1>", value: "<attrValue1>" } }
                        { attribute: { field: "<attrName2>", value: "<attrValue2>" } }
                    ]
                }
                {
                    not: {
                        businessAttribute: {
                            field: "<BusinessMetadataName>.<BusinessAttributeName>", value: "<BizAttrValue>"
                        }
                    }
                }
            ]
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Filtre imbriqué

Actuellement, ce modèle de requête n’est pas pris en charge pour les sous-ensembles.

Interroger l’entité par classification

query {
    entities(
        where: {
            classification: { type: { typeName: "<classificationType>", includeSubTypes: true } }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}
query {
    entities(
        where: {
            relatedEntity: {
                relationshipAttributeName: "<relAttrName>"
                entity: {
                    type: { typeName: "<entityType>" }
                }
            }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Interroger l’entité par termes de glossaire

query {
    entities(
        where: {
            assignedTerm: {
                term: {
                    qualifiedName: { eq: "<termName>" }
                }
            }
        }
    ) {
        guid
        typeName
        qualifiedName
        attributes
    }
}

Autres requêtes

Obtenir la relation

query {
    relationships(where: { guid: "<guid>" }) {
        guid
        typeName
        attributes
        end1 {
            guid
            typeName
            qualifiedName
            attributes
        }
        end2 {
            guid
            typeName
            qualifiedName
            attributes
        }
    }
}

Exemple de réponse :

{
    "data": {
        "relationships": [
            {
                "guid": "...",
                "typeName": "ExampleRelationship",
                "attributes": {},
                "end1": {
                    "guid": "...",
                    "typeName": "column",
                    "qualifiedName": "...",
                    "attributes": {}
                },
                "end2": {
                    "guid": "...",
                    "typeName": "column",
                    "qualifiedName": "...",
                    "attributes": {}
                }
            }
        ]
    }
}

Traçabilité

Obtenir un jeu de données avec des jeux de données en aval

Cette requête retourne les jeux de données en aval à 2 degrés.

query {
    entities(where: { guid: "<guid>" }) {#dataset
        guid
        typeName
        qualifiedName
        relatedEntities(where: { relationshipAttributeName: "inputToProcesses" }) {
            entity {#process
                guid
                typeName
                relatedEntities(where: { relationshipAttributeName: "outputs" }) {
                    entity {#dataset
                        guid
                        typeName
                        qualifiedName
                        relatedEntities(where: { relationshipAttributeName: "inputToProcesses" }) {
                            entity {#process
                                guid
                                typeName
                                qualifiedName
                                relatedEntities(where: { relationshipAttributeName: "outputs" }) {
                                    entity {#dataset
                                        guid
                                        typeName
                                        qualifiedName
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Exemple de réponse :

{
    "data": {
        "entities": [
            {
                "guid": "...",
                "typeName": "Dataset",
                "qualifiedName": "...",
                "relatedEntities": [
                    {
                        "entity": {
                            "guid": "...",
                            "typeName": "Process",
                            "relatedEntities": [
                                {
                                    "entity": {
                                        "guid": "...",
                                        "typeName": "Dataset",
                                        "qualifiedName": "...",
                                        "relatedEntities": [
                                            {
                                                "entity": {
                                                    "guid": "...",
                                                    "typeName": "Process",
                                                    "relatedEntities": [
                                                        {
                                                            "entity": {
                                                                "guid": "...",
                                                                "typeName": "Dataset",
                                                                "qualifiedName": "..."
                                                            }
                                                        }
                                                    ]
                                                }
                                            }
                                        ]
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        ]
    }
}

Limitations

Limitation de la profondeur de récupération des requêtes :

Les requêtes sont limitées par la profondeur des requêtes. La profondeur maximale est de 5. Par exemple, la requête suivante échoue :

query {
    entities { #depth 1
        relatedEntities { #depth 2
            entity {
                relatedEntities { #depth 3
                    entity {
                        assignedTerms{ #depth 4
                            term {
                                classifications { #depth 5
                                    ...
                                }
                            }
                        }
                        relatedEntities { #depth 4
                            entity {
                                assignedTerms{ #depth 5
                                    term {
                                        classifications { #depth 6
                                            ...
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Limitation du coût de récupération au moment de l’exécution :

Les requêtes sont limitées par le coût d’exécution des requêtes. Le coût maximal autorisé est défini à 100 unités.

Le coût d’extraction d’exécution est calculé chaque fois que nous visons à récupérer des entités associées, des termes attribués ou des classifications pour une entité ou un terme donné.

Exemple

Prenons l’exemple d’un scénario où nous interrogeons 3 entités, chacune avec deux entités associées. Le calcul du coût est le suivant :

  • Une unité pour la requête racine
  • Trois unités pour chaque entité de niveau 1

Par conséquent, le coût total de cette requête serait 1 (root query) + 3 (level-1 entities) = 4.

Performances de filtrage

Le filtrage est actuellement en préversion et présente certaines limitations. Pour plus d’informations , consultez Filtrage.

GraphQL requêtes commencent par une requête racine qui récupère les nœuds de niveau supérieur. Il récupère ensuite de manière récursive les nœuds associés.

Les performances d’une requête imbriquée sont principalement déterminées par la requête racine, car les nœuds associés sont extraits à partir d’un point de départ connu, similaire à une clé étrangère dans SQL.

Pour optimiser les performances, il est essentiel d’éviter les requêtes racines génériques qui pourraient déclencher une analyse de table sur les nœuds de niveau supérieur.

Par instance, la requête suivante peut entraîner des problèmes de performances sur des jeux de données volumineux, car le name champ n’est pas indexé :

query {
    entities(where: { name: { eq: "<value>" } }) {
        guid
        typeName
        attributes
        relatedEntities {
            entity {
                guid
                typeName
                attributes
            }
        }
    }
}

Pour éviter de tels problèmes de performances, veillez à appliquer un filtre sur guid ou qualifiedName.

Étapes suivantes