Forum Discussion
Help Needed with Recursive Pagination based on the value of a parameter
I was wondering if anyone could help me, I am tying to pull around 3k records from Qualys API however they have a max limit of 1000 per query.
I have managed to get a working query that extracts the first 1000 records then passes the lastId back into the post parameters to start the new query at the lastId this works fine however I am really struggling with the recursion and final output.
I have included my code with some comments around what I would like to do, any help appreciated.
let
//Recursive Loop Here while hasMoreRecords = true
url = "https://qualysapi.qualys.eu/qps/rest/2.0/search/am/hostasset/",
authKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
Headers = [
#"Content-Type" = "text/xml",
#"Accept" = "application/xml",
#"Authorization" = "Basic " & authKey,
#"X-Requested-With" = "AHARP_BI",
#"Cache-Control" = "no-cache",
#"lastID" = lastId,
#"hasMoreRecords" = hasMoreRecords
],
postData = "<ServiceRequest><preferences><limitResults>10000</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId&"</Criteria></filters></ServiceRequest>",
jsonResponse = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData)]))],
//End and output once hasMoreRecords = false
data = jsonResponse{0}[data],
HostAsset = data{0}[HostAsset,
#"Changed Type" = Table.TransformColumnTypes(HostAsset,{{"id", Int64.Type}, {"name", type text}, {"created", type datetime}, {"modified", type datetime}, {"type", type text}, {"qwebHostId", Int64.Type}, {"lastVulnScan", type datetime}, {"lastSystemBoot", type datetime}, {"lastLoggedOnUser", type text}, {"domain", type text}, {"fqdn", type text}, {"os", type text}, {"dnsHostName", type text}, {"netbiosName", type text}, {"networkGuid", type text}, {"address", type text}, {"trackingMethod", type text}, {"manufacturer", type text}, {"model", type text}, {"totalMemory", Int64.Type}, {"timezone", type text}, {"biosDescription", type text}, {"isDockerHost", type logical}, {"cloudProvider", type text}})
in
#"Changed Type"
I want to do something like this..
if hasMoreRecords = "true"
then @Query
else output all results
2 Replies
- v-jingzhang
Community Support
Hi DLEATE
I'm not able to provide detailed suggestions as I don't have much experience in this kind of recursive pagination. I found some articles and videos for related topics. Hope they would be helpful.
Fibonacci Sequence: Understanding the Power Query Recursive Function for Power BI
Start of series: Programming loops with M-language in Power Query
How to do Pagination without knowing the number of pages (Part 2) in Power Query | List.Generate
How to Use List Generate to Make API calls in Power Query
Iterate Over Dynamic Web API Pages With Power Query – How To Resolve Cursor-Based Pagination
Best Regards,
Community Support Team _ Jing
If this post helps, please Accept it as Solution to help other members find it. - DLEATEFrequent Visitor
So a Quick Update:
I am struggling with pagination recursion in M but I have built a manual loop with manual iterations just to make sure I had the code right... I am finding functional language fairly hard to wrap my head around!
I think i need to create a function and call it whilst the variable hasMoreRecords = true but this is day 4 and my brain is literally melting.. 🙂
Anyway whilst the code is crude and ugly I thought it may help someone that was struggling to create a power Query integration with Qualys.
Any advice on how should be done in M is very welcome 🙂
let
url = "https://qualysapi.qualys.eu/qps/rest/2.0/search/am/hostasset/",
authKey = "xxxxxxxxxxxxxxxxxxxxx",
Headers = [
#"Content-Type" = "text/xml",
#"Accept" = "application/xml",
#"Authorization" = "Basic " & authKey,
#"X-Requested-With" = "AHARP_BI"
//#"Cache-Control" = "no-cache",
//#"lastID" = lastId,
//#"lastID1" = lastId1,
//#"hasMoreRecords" = hasMoreRecords
],
//lastId1 = jsonResponse{0}[lastId],
//Recursive Loop Here while hasMoreRecords = true//Manual test Loop
postData = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">0</Criteria></filters></ServiceRequest>",
jsonResponse = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData)])),
lastId1 = jsonResponse{0}[lastId],
data = jsonResponse{0}[data],
postData1 = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId1&"</Criteria></filters></ServiceRequest>",
jsonResponse1 = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData1)])),
lastId2 = jsonResponse1{0}[lastId],
data1 = jsonResponse1{0}[data],
postData2 = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId2&"</Criteria></filters></ServiceRequest>",
jsonResponse2 = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData1)])),
lastId3 = jsonResponse2{0}[lastId],
data2 = jsonResponse2{0}[data],postData3 = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId3&"</Criteria></filters></ServiceRequest>",
jsonResponse3 = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData1)])),
lastIda4 = jsonResponse3{0}[lastId],
data3 = jsonResponse3{0}[data],postData4 = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId4&"</Criteria></filters></ServiceRequest>",
jsonResponse4 = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData1)])),
lastId5 = jsonResponse4{0}[lastId],
data4 = jsonResponse4{0}[data],postData5 = "<ServiceRequest><preferences><limitResults>10</limitResults></preferences><filters><Criteria field=""tagName"" operator=""EQUALS"">Cloud Agent</Criteria><Criteria field=""id"" operator=""GREATER"">"&lastId5&"</Criteria></filters></ServiceRequest>",
jsonResponse5 = Xml.Tables(Web.Contents(url, [Headers = Headers, Content = Text.ToBinary(postData1)])),
lastId6 = jsonResponse5{0}[lastId],
data5 = jsonResponse5{0}[data],
HostAsset = data{0}[HostAsset] & data1{0}[HostAsset] & data2{0}[HostAsset] & data3{0}[HostAsset] & data4{0}[HostAsset] & data5{0}[HostAsset],
#"Changed Type" = Table.TransformColumnTypes(HostAsset,{{"id", Int64.Type}, {"name", type text}, {"created", type datetime}, {"modified", type datetime}, {"type", type text}, {"qwebHostId", Int64.Type}, {"lastVulnScan", type datetime}, {"lastSystemBoot", type datetime}, {"lastLoggedOnUser", type text}, {"domain", type text}, {"fqdn", type text}, {"os", type text}, {"dnsHostName", type text}, {"netbiosName", type text}, {"networkGuid", type text}, {"address", type text}, {"trackingMethod", type text}, {"manufacturer", type text}, {"model", type text}, {"totalMemory", Int64.Type}, {"timezone", type text}, {"biosDescription", type text}, {"isDockerHost", type logical}, {"cloudProvider", type text}})
in
#"Changed Type"