How do I get all pages of a paginated response in a Power Query query that also uses parameters? - rest

I'm trying to get all pages of the API responses using Power Query Editor for Power BI Desktop, but have run into some problems getting the query to run.
I've used This tutorial as a starting point (but am open to suggestions).
The Problem
Currently, when I invoke this function from the table with the ext_id, to, and from parameters, I get an Expression.Error that The parameter is expected to be of type Text.Type or Binary.Type.
All I want to do is get all the pages of the query. The pages are available in the response at reviews.page.total.
I'm also trying to be as efficient as possible, as AppFollow uses a credit-based "payment" system for transacting with the API. Can someone help figure out where I've gone wrong?
My Current Code
(ext_id as text, from as text, to as text) =>
let
BaseURL = "https://api.appfollow.io/api/v2/reviews?",
token = "[redacted]",
Query = "ext_id=" & ext_id & "&from=" & from & "&to=" & to,
GetJson = (Url) =>
let
Options = [Headers=[Accept="application/json", #"X-AppFollow-API-Token"= token ]],
RawData = Web.Contents(Url, Options),
Json = Json.Document(RawData)
in Json,
GetPageCount = () =>
let Url = BaseURL & Query,
response = GetJson(Url),
toJson = Json.Document(response),
total = toJson[reviews]{0}[page][total]
in total,
GetPage = (Index) =>
let
Page = "&page=" & (Index),
Url = BaseURL & Query & Page,
Json = GetJson(Url),
Value = Json[reviews]
in Value,
PageCount = GetPageCount(),
PageIndicies = {0..PageCount -1},
Pages = List.Transform(PageIndicies, each GetPage(_)),
Results = List.Union(Pages),
#"Converted to Table" = Table.FromRecords(Results)
in
#"Converted to Table"
Sample Response
{
"query": "/api/reviews?cid=[cid-here]&ext_id=[ext-id-here&from=2023-01-01&to=2023-01-31&host=global4.appfollow.io&method=GET&real_ip=xxx.xxx.xxx.xx",
"reviews": {
"list": [
{
"data": "[removed data]"
}
],
"total": 286,
"page": {
"current": 1,
"total": 3,
"next": 2,
"prev": null
},
"ext_id": "ext-id-here",
"store": "as"
}
}
Error Message
Expression.Error: The parameter is expected to be of type Text.Type or Binary.Type.
Details:
query=/api/reviews?ext_id=[ext-id-here]&to=2023-01-31&from=2023-01-01&dev103=1&cid=[cid-here]&host=global4.appfollow.io&method=GET&real_ip=xxx.xx.xxx.xxx
reviews=[Record]

Try
Page = "&page=" & Text.From((Index)),

Related

Max item count in Cosmos DB trigger

I'm creating a pre-trigger for a Cosmos DB container. The pre-trigger is supposed to fetch all data related to the triggering document id. The incoming_document.items is always returning 100 when there are more than 100 documents expected (which seems to be limited by the query). I tried to set the pageSize property to -1 in the FeedOptions parameters and to use continuation, but it is still giving me 100. How can I fix this to give the total count?
Here is a simplified version of the code (without the continuation, I used a similar code to here):
function trgAddStats() {
var context = getContext();
var request = context.getRequest();
var incoming_document = request.getBody();
var container = context.getCollection();
var incoming_document.items = 1;
var filterQuery = {
"query": `SELECT t.customer, t.amount FROM Transactions_ds t WHERE t.customer = #customer`,
"parameters": [{
"name": "#customer",
"value": incoming_document.customer
}
]
};
var isAccepted = container.queryDocuments(container.getSelfLink(), filterQuery, {},
function (err, items, responseOptions) {
if (err) throw new Error("Error" + err.message);
incoming_document.items += items.length;
request.setBody(incoming_document);
}
);
if (!isAccepted) throw "Unable to update transaction, abort";
}
For getting more than 100 documents in Cosmos DB we can make use of x-ms-max-item-count.
The maximum number of values that can be returned by the query execution is done by the x-ms-max-item-count header.
The default value of the query results is 100 and it can be configured from 1–1000 using this header.
For more details regarding Pagination of query results in Microsoft Documentation.
You can Customize the number for Items per page in Query Explorer too like here.

Flutter : can't get all response body from get request

I have get request in Flutter app, when I test the request in postman I get all data, something like this :
{
"result":{
"name" : "somename",
"images":[
"test.jpg",
"test2.jpg"
],
"sizes":[
{
"id": 1,
"value" : 5
},
{
"id": 2,
"value" : 15
}
]
}
}
I call data and print them like this without using models:
var data = json.decode(response.body);
print(data['result']['name']);
print(data['result']['images']);
print(data['result']['sizes']);
it is print all things expect last one.
where must be the mistake?
Solved, by adding "?sizesView = true" to the link
final response = await http.get(path +'?sizesView = true'):
you should get the index of the last one because it is in a dictionary not a list do this:
print(data['result']['sizes'][0]['id']) // it will get the first index of the sizes list and then get the id key
or you can creat a model of list to get the indexes of your list

Passing values from an API through another API discord.js

So what trying to do is get some values I get from an API, pass onto an array to THEN pass it through another API and then add up the data it gets.
I already made this fetching it from 1 api, but I don't know how to fetch all the values from one api, pass it into an array, and fetch each value for each item.
let req1 = `https://inventory.roblox.com/v1/users/${imageURL}/assets/collectibles?sortOrder=Asc&limit=100`
let req2 = `https://users.roblox.com/v1/users/${imageURL}`
function getItems() {
return axios.get(req1)
}
function getUser() {
return axios.get(req2)
}
await Promise.all([getItems(), getUser(),getValue()])
.then(function(response){
let rap = response[0].data.data
let items = response[0].data.data.assetId
let itemarray = 0
let value = response[2].data.items[items array goes here][4]
let sum = 0
for(let i = 0; i < rap.length; i++) {sum += response[0].data.data[i].recentAveragePrice}
this is what I have so far. Any help will be appreciated. Thanks.
Edit:
Heres what req1 spits out:
{
"previousPageCursor": null,
"nextPageCursor": "49034821991_1_a887f8ff3a6b076aafd71c91a5a4a4fb",
"data": [
{
"userAssetId": 23726188,
"serialNumber": null,
"assetId": 7636350,
"name": "Supa Fly Cap",
"recentAveragePrice": 23535,
"originalPrice": null,
"assetStock": null,
"buildersClubMembershipType": 0
},
{
"userAssetId": 1329942875,
"serialNumber": 13717,
"assetId": 113325603,
"name": "Recycled Cardboard Shades",
"recentAveragePrice": 5703,
"originalPrice": 25,
"assetStock": 15000,
"buildersClubMembershipType": 0
},
```
req2 doesnt apply for this part of the code :p

Multiple values in query

I am trying to get stats for categories, where I want to specify multiple categories. I have query params like this
$query_params = json_decode('{
"aggregated_by": "day",
"limit": 500,
"categories": "category1 category2",
"start_date": "2018-08-12",
"end_date": "2018-08-13"}');
Obviously the way that I am defining multiple categories is wrong, but what is the correct way ? I tried array, comma/space separated values but with no luck.
You need to just name each category in a distinct argument. In your example, It'd probably look like:
$query_params = json_decode('{
"aggregated_by": "day",
"limit": 500,
"categories": "category1",
"categories": "category2",
"start_date": "2018-08-12",
"end_date": "2018-08-13"}');
So I solved this by passing the parameters as array:
$query = array('categories' => ['cat1','cat2']);
And then I modified sendgrid client buildUrl method like this:
private function buildUrl($queryParams = null)
{
$path = '/' . implode('/', $this->path);
if (isset($queryParams)) {
$queryParams = \http_build_query($queryParams);
$path .= '?' . preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryParams);
}
return sprintf('%s%s%s', $this->host, $this->version ?: '', $path);
}
I added the preg_replace part so the url is correctly built without including array key from nested array.

How to create a river using NEST client for ElasticSearch

I'm beginning to work with Elastic Search on our MVC5 project.
We have continuous integration build in place, and would like to configure Elastic Search via NEST just like Entity Framework Code-First.
I'm struggling to find how I can invoke this request through NEST.
PUT _river/mytype/_meta
{
"type":"jdbc",
"jdbc": {
"driver":"com.microsoft.sqlserver.jdbc.SQLServerDriver",
"url" : "jdbc:sqlserver://127.0.0.1:1433;databaseName=MyDatabase;",
"user" : "user",
"password" : "password123",
"sql":"select * from RiverView",
"poll":"30s",
"index":"myindex",
"type": "mytype",
"strategy": "simple"
}
}
Does anyone have any idea how to do this?
Thank you in advance.
I was able to make this work with using ElasticClient.Raw
var client = CreateClient();
var river = new
{
type = "jdbc",
jdbc = new
{
driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver",
url = String.Format("jdbc:sqlserver://{0}:1433;databaseName={1};", "127.0.0.1", "myDatabase"),
user = "user",
password = "password",
sql = "select * from mySqlView",
poll = "30s",
index = "index",
type = "type",
strategy = "simple"
}
};
string body = client.Serializer.Serialize(river, Formatting.Indented);
//HACK: Second parameter is a hack, appended _meta to type because NEST doesn't implement MetaPut()
var response = client.Raw.IndexPut("_river", "mytype/_meta", body);
Might not be the most elegant but worked for my requirement.