学习笔记1:Power BI访问SASURI获取数据

浏览: 1321

本文的学习资源来自网络。(需要科学上网)

https://medium.com/@martijnlentink/azure-table-storage-in-power-bi-with-a-shared-access-signature-token-dde6524b01c

文章标题为
Azure Table Storage in Power BI with a Shared Access Signature Token

学习笔记系列,只写我看完文章的理解和应用。

什么是SASURI数据源?

SAS的全称是Shared Access Signature token(SAS)。

SASURI包括SASURL和SAStoken两部分。SASURL就是https到?之间的信息,SAStoken是token的具体信息。

对于访问Azure(微软云)中存储的数据的两种方式,Account Key和Shared Access Signature token(SAS) 。Access Keys有点像管理员Admin,会给你全部的权限( full access to the Storage account)。

SAS可以提供有过期时限的(expiry date)token。token过期,连接就会失效,不能访问数据。也可以分配控制数据读写删除更新的权限。

直接通过Power BI获取SASURI数据源?

虽然Power BI和Azure都是微软的产品,但是目前不支持Power BI直接连接SAS的数据源。

打开Power BI Desktop,在Get Data中虽然有Azure Tables Storage的选项。但是输入SASURI的链接,会报URL过长的错误。

输入SASURI的URL,超出字符长度错误。


如何获取SASURI数据?

解:M Query里面的Web.Contents 函数和API。

目前,因为数据安全的原因,对于访问SASURI,并不能一次全部获得大量数据(>1000条)。当调用REST API访问SASURI,每次只能获取1000条数据,并得到下次访问需要的continuation token. 通过continuation token,我们可以继续访问下一个1000条数据,当continuation token返回为空的时候,所有的数据就全部取到了。

Power BI取SASURI就是模拟这个过程。其中如何得到不同的continuation token,作者通过观察找到了规律。

不懂也没有关系,其实也不影响后面的实现,只是这个规律有助于理解作者在M query中的function的定义。

实现步骤:

  1.  创建空白的Query

    打开Power BI, 点击Transform data,转到Power Query Editor页面。在Queries里面,右键新建一个Blank Query。

  2. 点击Advanced Editor,把以下代码直接贴上去。什么都不需要修改。

    有兴趣的可以读读,这里就是建立一个function来获取数据,并存到一个record list里面。

let    Base64Encode = (str as text) => Binary.ToText(Text.ToBinary(str, BinaryEncoding.Base64)),    CreateContinuationTokens = (partitionkey as text, rowkey as text) =>     let        tokenPrefix = "1",        combineToken = "!",        encodedPartition = Base64Encode(partitionkey),        encodedRow = Base64Encode(rowkey),        nextPartKey = Text.Combine({tokenPrefix, Text.From(Text.Length(encodedPartition)), encodedPartition}, combineToken),        nextRowKey = Text.Combine({tokenPrefix, Text.From(Text.Length(encodedRow)), encodedRow}, combineToken),        result = [ NextPartitionKey = nextPartKey, NextRowKey = nextRowKey]    in        result,    Func = (url as text, query as record, optional continuationTokens as record) =>    let        queryCombine = if continuationTokens = null then query else Record.Combine({query, continuationTokens}),        result = Json.Document(Web.Contents(url, [ Headers=[Accept="application/json;odata=nometadata"], Query = queryCombine ])),        resultAsList = result[value],        lastInList = List.Last(resultAsList),        tokens = CreateContinuationTokens(lastInList[PartitionKey], lastInList[RowKey]),        resultList = if List.Count(resultAsList) > 1 then List.Combine({resultAsList, RecursiveTableStorage(url, query, tokens)}) else resultAsList    in        resultListin    Func

3. 修改function函数的名字为RecursiveTableStorage

4. 新建一个blank query用RecursiveTableStorage函数获取数据。

以下代码是文章作者给的例子。URL部分,需要替换到你的SASURL的内容。也就是http到?之前的内容。st,se,sig是在token中用decode获取的。案例代码如下:

let  URL = "https://storagename.table.core.windows.net/tablename",    queryParameters = [ st = "2019-08-20T10:00:00Z",        se = "2030-08-25T10:00:00Z",        sp = "r",        sv = "2018-05-30",        tn = "tablename",        sig = "abcdefghijklmnopqrstuvwxyz"    ],    tabledata = Table.FromRecords(RecursiveTableStorage(URL, queryParameters)),    distinctRows = Table.Distinct(tabledata, {"PartitionKey", "RowKey"}),in    distinctRows

Decode转换网站https://www.urldecoder.org/

举个例子。上面空里贴的是SAStoken部分的一个内容。下面decode会生成正常的时间内容。然后把decode之后的内容替换掉上面代码相应位置。

如果Azure中存储的数据字段全部都有数据,这个代码没有问题。但是如果某一列某一行有一个空数据,则直接用table.fromrecords就会整行报错。

具体怎么处理参考Tips-6:如何从List of Record生成一个数据表

先调用函数RecursiveTableStorage(URL, queryParameters)来获得list of record,然后再生成表。最后不要忘记Dictinct table。因为每次调用API访问数据的时候,每次会用到最后一行数据来重构continuation token,所以每次最后一行数据都会重复出现。所以要用到distinct.

通过Tip6得到了table之后,用以下代码替换掉 in #"Expanded Column1" 部分

  distinctRows = Table.Distinct(#"Expanded Column1" , {"PartitionKey""RowKey"})in    distinctRows

就这样了。不太懂也没有关系。会用就可以了。

谢谢关注,分享。

感谢Sandy同学的review以及Azure数据方向的技术答疑!!谢谢!!


推荐 0
本文由 懒胖子 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册