I have an issue when Calling a REST endpoint. The resulting data set is too large for the endpoint to return (I get an HTTP 500 error).
I can split the Query up in pieces, e.g. by month. How do I perform multiple calls to the endpoint - one for each month I want to return, and then combine them into one table?
Unfortunately, the REST endpoind doesn't support ODATA queries, so I cannot page through the result set.
let
Source1 = Json.Document(Web.Contents("https://someurl?theapi" & "&q=Date>='2019-01-01' AND Date<='2019-01-31'")),
Source2 = Json.Document(Web.Contents("https://someurl?theapi" & "&q=Date>='2019-02-01' AND Date<='2019-02-28'")),
Table1= Table.FromList(Source1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
Table2= Table.FromList(Source2, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
CompositeTable= Table.NestedJoin(Table2, {"Datum"}, Table1, {"Datum"}, "CompositeTable", JoinKind.LeftOuter)
in
CompositeTable
I want to have the result sets from both queries merged into "CompositeTable"
There's a great blog post by Mark Tiedemann that suggests a solution. I've applied this method a dozen times and it works flawlessly for any paginated API I encountered.
Mark's elegant solution is to query the first page, extract the number of total results from it and then call the GetPage function for all remaining pages and combine all pages using the List.Union function.
For your use case, I would use a start and end date instead of items/page and total items. For each month in between start and end date, call the function that queries this month only, and combine the results. To give you an idea, something like this:
let
BaseUrl = "https://someurl?theapi&",
StartDate = #date(2019,01,01),
EndDate = #date(2019,05,31),
GetJson = (Url) =>
let Json = Json.Document(Web.Contents(Url))
in Json,
GetPage = (Index) =>
let Start = "Date>=" & Text.From(Date.StartOfMonth(Index)),
End = "Date<=" & Text.From(Date.EndOfMonth(Index)),
Url = BaseUrl & "&q=" & Start " AND " & End,
Json = GetJson(Url),
Value = Json[#"value"]
in Value,
PageIndices = { LIST OF ALL MONTHS },
Pages = List.Transform(PageIndices, each GetPage(_)),
Entities = List.Union(Pages),
Table = Table.FromList(Entities, Splitter.SplitByNothing(), null, null, ExtraValues.Error)
in
Table
Related
I am trying to pull data from Dynamics CRM.
I am not able to use oData as this brings in the whole DB.
= OData.Feed("https://crm/xxxxxx/api/data/v8.0/contacts")
Json allows the columns to be restricted but has a number of limits.
5000k limit
No page number listed
Offset function does not work
Limit function does not work
No total record count function
The below Json link returns two columns of information:
Values column - A list of the first 5000 records
oData.nextLink column - a link to the next 5000 records.
=Json.Document(Web.Contents("https://crm/xxxxxx/api/data/v8.0/contacts"))
I need to write function starting with the URL that returns the lists into a table. The first link is just a URL, the second is the oData link which makes coding harder. The loop ends on error.
I have tried too many methods to list, none give me the answer.
oData.nextLink is a large string
https://crm/xxxxxx/api/data/v8.0/contacts?$skiptoken=%3Ccookie%20pagenumber=%221%22%20pagingcookie=%22%253ccookie%2520page%253d%25221%2522%253e%253ccontactid%2520last%253d%2522%257bD0E5305F-0085-E211-9FD1-000C29854771%257d%2522%2520first%253d%2522%257b609AF16C-120C-4E2C-9498-00015D9B0068%257d%2522%2520%252f%253e%253c%252fcookie%253e%22%20istracking=%22False%22%20/%3E
let
Source = {1..7},
BaseURL = "https://crm/xxxxxx/api/data/v8.0/contacts",
NextURL = Json.Document(Web.Contents("https://crm/xxxxxx/api/data/v8.0/contacts")) [#"#odata.nextLink"],
NextList = Json.Document(Web.Contents("https://crm/xxxxxx/api/data/v8.0/contacts")) [#"value"],
ToTable = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
Renamed = Table.RenameColumns(ToTable,{{"Column1", "Page"}}),
AddedBase = Table.AddColumn(Renamed, "Base" as text, each BaseURL),
AddedLink = Table.AddColumn(AddedBase, "Next" as text, each NextURL),
AddedList = Table.AddColumn(AddedLink, "List" as text, each NextList)
in AddedList
I have a table (named Proto) in power-bi desktop as shown below (with 4 columns & around 30k rows).
I created a measure with the following DAX code. Here, ProtoVal is a table of single column containing unique values of protocol (like SSL, DNS etc). Based on the user selected protocol, i am filtering the above table to contain rows only for the selected protocol.
ProtoTotBytes =
VAR SelectedProto = SELECTEDVALUE(ProtoVal[Protocol])
VAR temp1 = FILTER(Proto, Proto[Protocol] == SelectedProto)
RETURN CALCULATE(SUM(Proto[total_bytes]), temp1)
The above DAX code works fine. Now in addition to SelectedProto, i wanted to add one more config variable numIP (TopN-IP's being a table of single column containing numerical values 5,10,15,20 etcTopN-IP's = GENERATESERIES(5, 30, 5)) where i want to take only the top 'numIP' rows from table temp1. Wrote the code below for that. This works whenever i change the value of SelectedProto but doesn't change when i change numIP ? Can anyone please let me know whey its sensitive to one config variable while it is ignoring another ?
ProtoTotBytes =
VAR numIP = SELECTEDVALUE('TopN-IP''s'[TopN-IP's])
VAR SelectedProto = SELECTEDVALUE(ProtoVal[Protocol])
VAR temp1 = FILTER(Proto, Proto[Protocol] == SelectedProto)
VAR temp2 = TOPN(numIP, temp1, [total_bytes], DESC)
RETURN CALCULATE(SUM(Proto[total_bytes]), temp2)
It does exactly what you told it to do, look at your code:
VAR temp1 = FILTER(Proto, Proto[Protocol] == SelectedProto)
VAR temp2 = TOPN(numIP, temp1, [total_bytes], DESC)
in the first line you use FILTER, this is correct, you are filtering
in the second line you are using TOPN, this is only sorting. I believe your intent was, was a filter based on your selection so also here you need to use FILTER.
VAR temp2 = FILTER(temp1, numIP = VALUE(RIGHT(Proto[networkIpAddress],1)))
In this filter I compare the last digit of the networkIp with the numIP(s) selected by the user
How can I use current datetime as parameters in a power bi query statement for REST API? I specified two parameters "DateStart" and "DateEnd" which I want to include in my Data source's SQL statement,i want to add DateEnd as current system datetime & DateStart as 15 min past datetime.
my query is
let
body = Text.ToBinary("{
""Type"": ""Feedbacks"",
""FromDate"": ""01-01-2015 23:00:00.000"",
""ToDate"": ""20-09-2017 23:00:00.000"",
""SearchField"": ""test"",
""SearchFieldValue"": ""*""
}"),
actualUrl = "http:/xx.xx.xx.xx:xx/service/GetSomething",
options = [
Headers =[#"Content-type"="application/json"],
Content=body
],
result = Web.Contents(actualUrl, options),
#"Imported JSON" = Json.Document(result,65001)
in
#"Imported JSON"
Here i want to add end date as current datetime & start date as current-15 min
Thanks in advance.
I am using Power BI Desktop to create a web query to the stack overflow API. I want to obtain the number of questions asked on stack overflow for each user which is extracted from a prepopulated table of users in Power BI.
So I want something that will look like this:
Pre-populated Users:
6231494
User2
User3
StackOverflow Questions:
6231494: 5
User2: 12
User3: 10
Here is my current code for my web query in the advanced editor:
let
Source = Json.Document(Web.Contents("http://api.stackexchange.com/2.2/users/6231494/answers?order=desc&sort=activity&site=stackoverflow")),
items = Source[items],
#"Converted to Table" = Table.FromList(items, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"owner", "is_accepted", "score", "last_activity_date", "creation_date", "answer_id", "question_id"}, {"Column1.owner", "Column1.is_accepted", "Column1.score", "Column1.last_activity_date", "Column1.creation_date", "Column1.answer_id", "Column1.question_id"}),
#"Expanded Column1.owner" = Table.ExpandRecordColumn(#"Expanded Column1", "Column1.owner", {"reputation", "user_id", "user_type", "profile_image", "display_name", "link"}, {"Column1.owner.reputation", "Column1.owner.user_id", "Column1.owner.user_type", "Column1.owner.profile_image", "Column1.owner.display_name", "Column1.owner.link"})
in
#"Expanded Column1.owner"
I basically need a way to set the current hardcoded ID (6231494) equal to the list of IDs from my predefined user table
Assume that you have a Users table with column ID as number:
You can make a few changes to your Questions query to turn it into a custom function in Power BI:
(id as number) =>
let
Source = Json.Document(Web.Contents("http://api.stackexchange.com/2.2/users/" & Text.From(id) & "/answers?order=desc&sort=activity&site=stackoverflow")),
items = Source[items]
...
(id as number) => is added to turn the query into a function;
and the user ID is replaced with Text.From(id).
Here I renamed it to GetQuestions to keep it clear that it's a function:
You can then add a custom column to invoke the function:
Expand it and you shall find the columns from the original query:
And you can work with the data to get the results you want (e.g. number of questions).
I am calling an API with PowerQuery in PowerBI desktop with the intention of pushing the data into the online service for scheduled refreshing.
The query itself works as intended but will throw an error if the API service is unavailable. This proves a problem as the whole scheduled refresh will fail if one of one query doesn't work.
I've thrown a try...otherwise around the call but I don't know how to tell it to skip the current query if it returns an error.
let
url = "https://example-api.com",
.
. <code omitted for brevity>
.
AddColumns = try Table.AddColumn(CreateTable,
"Data",
each Json.Document(Web.Contents(url,
[
Headers =[#"Accept"="application/json"],
Timeout=#duration(0, 0, 10, 0),
RelativePath="/api/index.php/api-method.json",
Query=
[
#"filter" = "openedDate $gte 2016-03-01T00:00:00",
#"key" = "<api-key>",
#"select" = "customerId,type,status,name,userId,total,openedDate",
]
]
))),
in
AddColumns
The best outcome here would be if it catches an error to cancel the current query and keep the data from the last successful data refresh.
I'd move try keyword after each. This will leave row, when your variant would fail the whole table.
AddColumns = Table.AddColumn(CreateTable,
"Data",
each try Json.Document(skipped d/l code) otherwise null
),
DataTable = if Table.IsEmpty(Table.SelectRows(AddColumns, each [Data] <> null)) then OldTableWithData else AddColumns,
NextStep = DoSomething(DataTable),
etc etc
Also this article might prove useful for you:
http://blog.gbrueckl.at/2013/12/error-handling-in-power-query/