Répondre à: Requête OData / pagination

  • Jeremy

    Membre
    27 février 2023 à 8h16

    Bonjour Xavier,

    J’ai déjà eu cela avec des limitation à 500 enr par appel. J’ai dû créer des fonctions en M pour gérer cela.

    Voici mes fonctions :

    importTablenletn    Source = (tableImport) =>n    letn        firstPageUrl = "https://<NomDuSite>/api/" & tableImport,nn        output = @GenerateByPage(n            (lastPage) =>n                letn                    next = if lastPage <> null then Value.Metadata(lastPage)[Next] else null,n                    urlToUse = if (next <> null) then next else firstPageUrl,n                    current = if (lastPage <> null and next = null) then null else getJson(urlToUse),n                    dataset = if (current <> null) then getDataset(current) else null,n                    link = if (current <> null) then current[next_page_url] else nulln                inn                    dataset meta [Next=link]n        ),nn        getDataset = (json) =>n            letn                ConvertirEnTable = Table.FromRecords({json}),n                Developper = Table.ExpandListColumn(ConvertirEnTable, "data"),n                GarderData = Table.SelectColumns(Developper,{"data"})n            in GarderData,n            n        getJson = (url) =>n            letn                waitForResult = WaitFor(n                    (iteration) =>n                        letn                            Source = Web.Contents(url, [Headers=[Authorization="Bearer " & ApiToken], ManualStatusHandling = {500}, IsRetry = iteration > 0]),n                            contentType = Value.Metadata(Source)[Content.Type],n                            actualResult = if contentType = "application/json" then Json.Document(Source) else nulln                        in actualResult,n                    (iteration)=> #duration(0, 0, 0, Number.Power(2, iteration)),n                    5n                )n            inn                if waitForResult = nulln                then error "Wait for gave up after too many retry"n                else waitForResultn    inn        outputninn    Source

    A noter que le Token est dans un paramètre que j’ai appelé “ApiToken”.

    Ensuite, j’ai une fonction qui permet de générer par page :

    GenerateByPagenletn    Source = (getNextPage as function) as table =>n    letn        listOfPages = List.Generate(n            () => getNextPage(null),            // get the first page of datan            (lastPage) => lastPage <> null,     // stop when the function returns nulln            (lastPage) => getNextPage(lastPage) // pass the previous page to the next function calln        ),n        // concatenate the pages togethern        tableOfPages = Table.FromList(listOfPages, Splitter.SplitByNothing(), {"Column1"}),n        firstRow = tableOfPages{0}?n    inn        // if we didn't get back any pages of data, return an empty tablen        // otherwise set the table type based on the columns of the first pagen        if (firstRow = null) thenn            Table.FromRows({})nt    // check for empty first tablen        else if (Table.IsEmpty(firstRow[Column1])) thenn            firstRow[Column1]n        elsen            Value.ReplaceType(n                Table.ExpandTableColumn(tableOfPages, "Column1", Table.ColumnNames(firstRow[Column1])),n                Value.Type(firstRow[Column1])n            )ninn    Source

    Enfin, parce qu’il y a une limite de nombre de transactions par minute, j’avais dû créer une fonction d’attente :

    WaitFornletn    Source = (producer as function, interval as function, optional count as number) as any =>n    letn        list = List.Generate(n            () => {0, null},n            (state) => state{0} <> null and (count = null or state{0} < count),n            (state) => if state{1} <> null then {null, state{1}} else {1 + state{0}, Function.InvokeAfter(() => producer(state{0}), interval(state{0}))},n            (state) => state{1})n    inn        List.Last(list)ninn    Source

    J’espère que cela pourra t’aider. Peut-être une idée d’article à faire dès que je pourrais car c’est une vraie problématique.

    ATTENTION : j’ai eu des problèmes avec ce genre de code car la source devient dynamique et elle ne peut pas être utilisée dans Power BI Services. En effet l’actualisation automatique des sources dynamiques ne fonctionne pas.

    CommentID=rPOfMdeNFioAZOK, PostID=IT9iFywp9PBDbYs