API GraphQL с Помощью Microsoft Purview (предварительная версия)

Важно!

Сейчас эта функция доступна в предварительной версии. Дополнительные условия использования предварительных версий Microsoft Azure включают дополнительные юридические условия, применимые к Azure функциям, которые находятся в бета-версии, в предварительной версии или еще не выпущены в общедоступную версию.

В этом руководстве описано, как программно взаимодействовать с Microsoft Purview с помощью API GraphQL. Дополнительные сведения о GraphQL в целом см. в этой статье введение в GraphQL.

Использование GraphQL аналогично rest API, так как вы отправляете полезные данные JSON в конечную точку службы. Однако GraphQL позволяет нам возвращать полную информацию за один выборку, устраняя необходимость в нескольких вызовах API.

GraphQL также использует декларативную выборку данных. Декларативная выборка данных полезна для выборочной выборки полей, таких каксвязанная стермином/классификации/ сущность, связанная с исходной сущностью. Используя GraphQL с этими шаблонами запросов, мы можем оптимизировать получение и передачу данных серверной базы данных. Хорошим примером является "Получение сущности с отфильтрованными связанными сущностями, разделенными псевдонимами".

Благодаря функции самоанализа API GraphQL становится самоописательным, позволяя клиентам получать сведения о схеме, такие как доступные запросы, типы и параметры запроса. См. дополнительные сведения о самоанализе.

Предварительные условия

Конечная точка GraphQL

Для всех запросов можно отправить запрос в следующую POST конечную точку:

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

Базовый запрос

Сущность — перечисление по 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
    }
}

Пример ответа:

{
    "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"
            }
        ]
    }
}

Запрос сущностей по типу и полному имени

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

Оператор in используется для запроса нескольких полных имен.

Возможные операторы: exists|eq|ne|in|nin|gt|ge|lt|le. Дополнительные сведения о схеме сервера можно найти с помощью самоанализа.

Декларативная выборка данных

Получение сущности с выбранными полями

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

Получение сущности со всеми полями

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
        }
    }
}

Получение сущности с классификациями

— со всеми классификациями

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

— с отфильтрованными классификациями

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
            }
        }
    }
}

Получение сущности с терминами глоссария

— со всеми терминами глоссария;

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

— с отфильтрованными терминами глоссария

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

Фильтрация (предварительная версия)

Производительность точного сопоставления для "GUID" и "Квалифицированного имени" гарантируется в примерах, приведенных в разделе "Базовые запросы". Однако существуют некоторые ограничения для других шаблонов фильтрации:

  • Фильтрация по неиндексированным полям. Поля, отличные от GUID & полное имя, в настоящее время не индексируются (как примеры в разделе "Простой фильтр"). Фильтрация по неиндексированным полям без условий по GUID/Qualified-name приведет к сканированию таблицы и может привести к проблемам с производительностью больших наборов данных.
  • Вложенная фильтрация. Как и в случае с неиндексными полями, вложенная фильтрация может привести к сканированию таблиц, что может привести к проблемам с производительностью больших наборов данных. Например, поиск сущности со связанной классификацией, термином или связанной сущностью.

Несмотря на эти ограничения, этот шаблон вызова превосходит фильтрацию на стороне клиента и в настоящее время используется нашим внутренним клиентом.

Простой фильтр

Запрос сущностей по типу и системным атрибутам

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

Запрос сущностей по типу и атрибутам

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

Запрос сущностей по типам и бизнес-атрибутам

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

Запрос сущностей по коллекции

В настоящее время этот шаблон запроса не поддерживается для поднаборов.

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

Сочетание фильтров

Ключи в объекте (карте) объединяются в виде логического И.

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
    }
}

Вложенный фильтр

В настоящее время этот шаблон запроса не поддерживается для поднаборов.

Запрос сущности по классификации

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
    }
}

Запрос сущности по терминам глоссария

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

Другие запросы

Получение связи

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

Пример ответа:

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

Lineage

Получение набора данных с подчиненными наборами данных

Этот запрос возвращает подчиненные наборы данных на 2 градуса.

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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Пример ответа:

{
    "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": "..."
                                                            }
                                                        }
                                                    ]
                                                }
                                            }
                                        ]
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        ]
    }
}

Ограничения

Ограничение глубины получения запроса:

Запросы ограничены глубиной запроса. Максимальная глубина — 5. Например, следующий запрос завершится ошибкой:

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
                                            ...
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Ограничение времени получения и стоимости выполнения.

Запросы ограничены стоимостью выполнения запроса. Максимальная допустимая стоимость составляет 100 единиц.

Затраты на выборку выполнения вычисляются каждый раз, когда мы стремимся получить связанные сущности, назначенные термины или классификации для данной сущности или термина.

Пример

Рассмотрим сценарий, в котором мы запрашиваем 3 сущности, каждая из которых имеет две связанные сущности. Затраты будут вычислить следующим образом:

  • Одна единица для корневого запроса
  • Три единицы для каждой сущности уровня 1

Таким образом, общая стоимость этого запроса будет составлять 1 (root query) + 3 (level-1 entities) = 4.

Производительность фильтрации

Фильтрация в настоящее время является предварительной версией и имеет некоторые ограничения. Дополнительные сведения см. в разделе Фильтрация .

GraphQL запросы начинаются с корневого запроса, который извлекает узлы верхнего уровня. Затем он рекурсивно извлекает связанные узлы.

Производительность вложенного запроса в основном определяется корневым запросом, так как связанные узлы извлекаются из известной начальной точки, аналогичной внешнему ключу в SQL.

Для оптимизации производительности важно избегать корневых запросов с подстановочными знаками, которые могут вызвать проверку таблиц на узлах верхнего уровня.

Например, следующий запрос может вызвать проблемы с производительностью больших наборов данных, так как name поле не индексировано:

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

Чтобы избежать таких проблем с производительностью, обязательно примените фильтр к guid или qualifiedName.

Дальнейшие действия