Paginación de Power Query Rest API con @odata.nextLink

Un usuario Pregunto ✅

mariob84

Hola a todos,

Necesito tu ayuda. En una llamada a la API Rest en Power Query. La API siempre devuelve 1000 filas por llamada y luego las siguientes 1000 filas. Tengo que llamar a odate.nextLink in a Loop para obtener todos los datos. ¿Cómo puedo hacer esto en un bucle?
Esto es lo que obtuve de la primera llamada y con odata.nextLink, la siguiente llamada de URL es visible

let
  Source= Json.Document(
    Web.Contents(
      "https://Website.net/external/Sales?$skip=0",
      [
        Headers = [
          #"accept" = "application/json",
          #"Authorization"
            = "Api Key"
        ]
      ]
    )
  ),
  #"In Tabelle konvertiert" = Record.ToTable(Source),
  Value = #"In Tabelle konvertiert"{1}[Value],
  #"In Tabelle konvertiert1" = Table.FromList(
    Value,
    Splitter.SplitByNothing(),
    null,
    null,
    ExtraValues.Error
  )
in
#"In Tabelle konvertiert1"

MarioB84_0-1626427663579.png

mariob84

En respuesta a jones jones jones

Gracias por su ayuda, configuré sus ejemplos y encontré una buena solución, lo que funciona bien para mí. Con la activación de @odata.count, obtengo el número máximo y un bucle de las entidades por página. y adjuntar cada uno a una tabla grande

let 
    BaseUrl         = "SampleAPIUrl",
    ApiKey           = "SampleKey",
    EntitiesPerPage = 1000,
 
    GetJson = (Url) =>
        let Options = [
        Headers = [
          #"accept" = "application/json",
          #"Authorization"
            = ApiKey
        ]
      ],
            RawData = Web.Contents(Url, Options),
            Json    = Json.Document(RawData)
        in  Json,
 
    GetEntityCount = () =>
        let Url   = BaseUrl & "?$count=true&$top=0",
            Json  = GetJson(Url),
            Count = Json[#"@odata.count"]
        in  Count,
 
    GetPage = (Index) =>
        let Skip  = "?$skip=" & Text.From(Index * EntitiesPerPage),
            Top   = "$top=" & Text.From(EntitiesPerPage),
            Url   = BaseUrl & Skip,
            Json  = GetJson(Url),
            Value = Json[#"value"]
        in  Value,
 
    EntityCount = List.Max({ EntitiesPerPage, GetEntityCount() }),
    PageCount   = Number.RoundUp(EntityCount / EntitiesPerPage),
    PageIndices = { 0 .. PageCount - 1 },
    Pages       = List.Transform(PageIndices, each GetPage(_)),
    Entities    = List.Union(Pages),
    Table       = Table.FromList(Entities, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
    Table

mahoneypat

Vea este video con un tutorial de una buena manera de hacer esto.

Power BI – Historias desde el frente – API REST – YouTube

Palmadita

mahoneypat

En respuesta a mahoneypat

Por lo general, puede hacer una llamada de $count para obtener eso por sí mismo. Sin embargo, si conoce el número aproximado que puede esperar, podría adaptar el enfoque que mostré para superar eso con un número fijo de llamadas y luego simplemente eliminar las pocas filas de ese error.

Palmadita

mariob84

En respuesta a mahoneypat

Hola @mahoneypat Gracias por el enlace, lamentablemente no puedo usar esto porque no obtengo un valor para el número total en mi salida. Y así, siempre obtenga un valor de texto con la siguiente URL. Aquí necesito un bucle hasta que se llegue al final y esto ya no se muestra

jones jones jones

En respuesta a mariob84

Aquí está la sección relevante del código que uso para conectarme a una API de graphql. Deberá hacer algunos ajustes para que se alinee. La primera línea llama a otra función que toma una página, luego List.Generate continúa ejecutándose a través de las páginas hasta que los valores de datos = nulos. Con suerte, te dará algo para empezar.

fngetpages = (nextpg) as record =>
let 
    Source = fxGetPages(QueryType, Fields, Campaign, additional, nextpg),
    data = try Source[data] otherwise null,
    next = try data[pageInfo] [endCursor] otherwise null,
    res = [Data = data, Next=next]
in
    res,

   GeneratedList =
  List.Generate(
      ()=> [res=fngetpages(null)],
      each [res] [Next] <> null,
      each [res = fngetpages([res] [Next])],
      each [res] [Data]
  )

mariob84

En respuesta a jones jones jones

Gracias por su ayuda, configuré sus ejemplos y encontré una buena solución, lo que funciona bien para mí. Con la activación de @odata.count, obtengo el número máximo y un bucle de las entidades por página. y adjuntar cada uno a una tabla grande

let 
    BaseUrl         = "SampleAPIUrl",
    ApiKey           = "SampleKey",
    EntitiesPerPage = 1000,
 
    GetJson = (Url) =>
        let Options = [
        Headers = [
          #"accept" = "application/json",
          #"Authorization"
            = ApiKey
        ]
      ],
            RawData = Web.Contents(Url, Options),
            Json    = Json.Document(RawData)
        in  Json,
 
    GetEntityCount = () =>
        let Url   = BaseUrl & "?$count=true&$top=0",
            Json  = GetJson(Url),
            Count = Json[#"@odata.count"]
        in  Count,
 
    GetPage = (Index) =>
        let Skip  = "?$skip=" & Text.From(Index * EntitiesPerPage),
            Top   = "$top=" & Text.From(EntitiesPerPage),
            Url   = BaseUrl & Skip,
            Json  = GetJson(Url),
            Value = Json[#"value"]
        in  Value,
 
    EntityCount = List.Max({ EntitiesPerPage, GetEntityCount() }),
    PageCount   = Number.RoundUp(EntityCount / EntitiesPerPage),
    PageIndices = { 0 .. PageCount - 1 },
    Pages       = List.Transform(PageIndices, each GetPage(_)),
    Entities    = List.Union(Pages),
    Table       = Table.FromList(Entities, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
    Table

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *