<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>ebendutoit.com</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://ebendutoit.com/"/>
  <updated>2021-02-16T08:43:25.679Z</updated>
  <id>http://ebendutoit.com/</id>
  
  <author>
    <name>Eben du Toit</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Convert BigQuery response to MYSQL in python 3</title>
    <link href="http://ebendutoit.com/2020/10/02/python_convert_bq_results/"/>
    <id>http://ebendutoit.com/2020/10/02/python_convert_bq_results/</id>
    <published>2020-10-02T10:55:56.000Z</published>
    <updated>2021-02-16T08:43:25.679Z</updated>
    
    <content type="html"><![CDATA[<p>More than a year ago I wrote a post with a Javascript (node JS) function inside it that shows how we can recursively parse BigQuery rows results from their API into a flattened “mysql”-like JSON file. Recently I needed the python version of this function, so I provide it here. Enjoy!</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">convert_bq_rows_to_json</span><span class="params">(self, schema, rows)</span>:</span></span><br><span class="line"></span><br><span class="line">        result_rows = []</span><br><span class="line">        result = &#123;&#125;</span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">recurse</span> <span class="params">(schema_cur, rows_cur, col_name)</span>:</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> isinstance(schema_cur, list):</span><br><span class="line">                <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">0</span>, len(schema_cur)):</span><br><span class="line">                    print(schema_cur[i])</span><br><span class="line">                    <span class="keyword">if</span> (col_name == <span class="string">""</span>):</span><br><span class="line">                        recurse(schema_cur[i], rows_cur[<span class="string">'f'</span>][i], col_name + schema_cur[i][<span class="string">'name'</span>])</span><br><span class="line">                    <span class="keyword">else</span>:</span><br><span class="line">                        recurse(schema_cur[i], rows_cur[<span class="string">'f'</span>][i], col_name + <span class="string">"."</span> + schema_cur[i][<span class="string">'name'</span>])</span><br><span class="line">                </span><br><span class="line">            <span class="keyword">if</span> <span class="string">'type'</span> <span class="keyword">in</span> schema_cur <span class="keyword">and</span> schema_cur[<span class="string">'type'</span>] == <span class="string">"RECORD"</span>:</span><br><span class="line">                <span class="keyword">if</span> <span class="string">'mode'</span> <span class="keyword">in</span> schema_cur <span class="keyword">and</span> schema_cur[<span class="string">'mode'</span>] != <span class="string">"REPEATED"</span>:</span><br><span class="line">                    val_index = <span class="number">0</span></span><br><span class="line">                    <span class="keyword">for</span> p <span class="keyword">in</span> schema_cur[<span class="string">'fields'</span>]:</span><br><span class="line">                        <span class="keyword">if</span> rows_cur[<span class="string">'v'</span>] == <span class="literal">None</span>:</span><br><span class="line">                            recurse(schema_cur[<span class="string">'fields'</span>][p], rows_cur, col_name + <span class="string">"."</span> + schema_cur[<span class="string">'fields'</span>][p][<span class="string">'name'</span>])</span><br><span class="line">                        <span class="keyword">else</span>:</span><br><span class="line">                            recurse(schema_cur[<span class="string">'fields'</span>][p], rowsCur.v.f[valIndex], colName + <span class="string">"."</span> + schemaCur.fields[p].name)</span><br><span class="line">                    </span><br><span class="line">                        val_index+=<span class="number">1</span></span><br><span class="line">                    </span><br><span class="line">                <span class="keyword">if</span> (schema_cur[<span class="string">'mode'</span>] == <span class="string">"REPEATED"</span>):  </span><br><span class="line">                    result[colName] = [] </span><br><span class="line">                    <span class="keyword">for</span> x <span class="keyword">in</span> rows_cur[<span class="string">'v'</span>]: </span><br><span class="line">                        recurse(schema_cur[<span class="string">'fields'</span>], rows_cur[<span class="string">'v'</span>][x], col_name)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="keyword">if</span> <span class="string">'mode'</span> <span class="keyword">in</span> schema_cur <span class="keyword">and</span> schema_cur[<span class="string">'mode'</span>] == <span class="string">"REPEATED"</span>:</span><br><span class="line">                    <span class="keyword">if</span> rows_cur[<span class="string">'v'</span>] != <span class="literal">None</span>:</span><br><span class="line">                        result[col_name] = map(<span class="keyword">lambda</span> x : x[<span class="string">'v'</span>], rows_cur[<span class="string">'v'</span>])</span><br><span class="line">                    <span class="keyword">else</span>:</span><br><span class="line">                        result[col_name] = [ <span class="literal">None</span> ]</span><br><span class="line">                    </span><br><span class="line">                <span class="keyword">elif</span> col_name <span class="keyword">in</span> result <span class="keyword">and</span> type(result[col_name]) <span class="keyword">is</span> list:</span><br><span class="line">                    next_row = &#123;&#125; </span><br><span class="line">                    <span class="keyword">for</span> j <span class="keyword">in</span> schema_cur:</span><br><span class="line">                        next_row[col_name + <span class="string">"."</span> + schema_cur[j].name] = map(<span class="keyword">lambda</span> x: x[<span class="string">'v'</span>], rows_cur[<span class="string">'v'</span>][<span class="string">'f'</span>][j][<span class="string">'v'</span>]) <span class="keyword">if</span> type(rows_cur[<span class="string">'v'</span>][<span class="string">'f'</span>][j][<span class="string">'v'</span>]) <span class="keyword">is</span> list <span class="keyword">else</span> rows_cur[<span class="string">'v'</span>][<span class="string">'f'</span>][j][<span class="string">'v'</span>]</span><br><span class="line">                    </span><br><span class="line">                    result[col_name].append(next_row)</span><br><span class="line">                <span class="keyword">else</span>:</span><br><span class="line">                    <span class="keyword">if</span> col_name != <span class="string">""</span>:</span><br><span class="line">                        result[col_name] = rows_cur[<span class="string">'v'</span>]</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> r <span class="keyword">in</span> range(<span class="number">0</span>, len(rows)):</span><br><span class="line">            recurse(schema[<span class="string">'fields'</span>], rows[r], <span class="string">""</span>)</span><br><span class="line">            result_rows.append(result)</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">return</span> result_rows</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;More than a year ago I wrote a post with a Javascript (node JS) function inside it that shows how we can recursively parse BigQuery rows 
      
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>Converting JSON query results from Google BigQuery to MySQL</title>
    <link href="http://ebendutoit.com/2019/03/24/convert_bq_results/"/>
    <id>http://ebendutoit.com/2019/03/24/convert_bq_results/</id>
    <published>2019-03-24T16:50:37.000Z</published>
    <updated>2019-03-27T14:22:07.030Z</updated>
    
    <content type="html"><![CDATA[<p>Have you ever wanted to convert the schema and results passed from the query API of BigQuery into something more acceptable?<br>There is an endless array of <code>{ f: { v: } }</code> nests to contend with sometimes. Well now you can transform it into something simpler!</p><a id="more"></a><p>We are transforming something that looks like this:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"schema"</span>: &#123;</span><br><span class="line">        <span class="attr">"fields"</span>: [</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">"name"</span>: <span class="string">"Name"</span>,</span><br><span class="line">            <span class="attr">"type"</span>: <span class="string">"STRING"</span>,</span><br><span class="line">            <span class="attr">"mode"</span>: <span class="string">"NULLABLE"</span></span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">"name"</span>: <span class="string">"Address"</span>,</span><br><span class="line">            <span class="attr">"type"</span>: <span class="string">"RECORD"</span>,</span><br><span class="line">            <span class="attr">"mode"</span>: <span class="string">"REPEATED"</span>,</span><br><span class="line">            <span class="attr">"fields"</span>: [</span><br><span class="line">              &#123;</span><br><span class="line">                <span class="attr">"name"</span>: <span class="string">"street"</span>,</span><br><span class="line">                <span class="attr">"type"</span>: <span class="string">"STRING"</span>,</span><br><span class="line">                <span class="attr">"mode"</span>: <span class="string">"NULLABLE"</span></span><br><span class="line">              &#125;,</span><br><span class="line">              &#123;</span><br><span class="line">                <span class="attr">"name"</span>: <span class="string">"city"</span>,</span><br><span class="line">                <span class="attr">"type"</span>: <span class="string">"STRING"</span>,</span><br><span class="line">                <span class="attr">"mode"</span>: <span class="string">"NULLABLE"</span></span><br><span class="line">              &#125;</span><br><span class="line">            ]</span><br><span class="line">          &#125;</span><br><span class="line">        ]</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">"rows"</span>: [</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">"f"</span>: [</span><br><span class="line">            &#123;</span><br><span class="line">              <span class="attr">"v"</span>: <span class="string">"Amos"</span></span><br><span class="line">            &#125;,</span><br><span class="line">            &#123;</span><br><span class="line">              <span class="attr">"v"</span>: [</span><br><span class="line">                &#123;</span><br><span class="line">                  <span class="attr">"v"</span>: &#123;</span><br><span class="line">                    <span class="attr">"f"</span>: [</span><br><span class="line">                      &#123;</span><br><span class="line">                        <span class="attr">"v"</span>: <span class="string">"street1"</span></span><br><span class="line">                      &#125;,</span><br><span class="line">                      &#123;</span><br><span class="line">                        <span class="attr">"v"</span>: <span class="string">"city1"</span></span><br><span class="line">                      &#125;</span><br><span class="line">                    ]</span><br><span class="line">                  &#125;</span><br><span class="line">                &#125;,</span><br><span class="line">                &#123;</span><br><span class="line">                  <span class="attr">"v"</span>: &#123;</span><br><span class="line">                    <span class="attr">"f"</span>: [</span><br><span class="line">                      &#123;</span><br><span class="line">                        <span class="attr">"v"</span>: <span class="string">"street2"</span></span><br><span class="line">                      &#125;,</span><br><span class="line">                      &#123;</span><br><span class="line">                        <span class="attr">"v"</span>: <span class="string">"city2"</span></span><br><span class="line">                      &#125;</span><br><span class="line">                    ]</span><br><span class="line">                  &#125;</span><br><span class="line">                &#125;</span><br><span class="line">              ]</span><br><span class="line">            &#125;</span><br><span class="line">          ]</span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>into this?</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[ &#123; <span class="attr">"Name"</span>: <span class="string">"Amos"</span>,</span><br><span class="line">    <span class="attr">"Address"</span>: </span><br><span class="line">     [ &#123; <span class="attr">"Address.street"</span>: <span class="string">"street1"</span>, <span class="attr">"Address.city"</span>: <span class="string">"city1"</span> &#125;,</span><br><span class="line">       &#123; "Address.street": "street2", "Address.city': "city2" &#125; ] &#125; ]</span><br></pre></td></tr></table></figure><p>Now you can, and for some <a href="https://cloud.google.com/bigquery/docs/nested-repeated" target="_blank" rel="noopener">very complicated nested results</a> as well!</p><p>See the <em>node.js</em> function below and enjoy! </p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">convertBQToMySQLResults</span>(<span class="params">schema, rows</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">var</span> resultRows = []</span><br><span class="line">    </span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">recurse</span> (<span class="params">schemaCur, rowsCur, colName</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(schemaCur) &amp;&amp; !<span class="built_in">Array</span>.isArray(result[colName])) &#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>, l=schemaCur.length; i&lt;l; i++) &#123;</span><br><span class="line">                <span class="keyword">if</span> (colName === <span class="string">""</span>)</span><br><span class="line">                    recurse(schemaCur[i], rowsCur.f[i], colName + schemaCur[i].name)</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    recurse(schemaCur[i], rowsCur.f[i], colName + <span class="string">"."</span> + schemaCur[i].name)</span><br><span class="line">            &#125;    </span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (schemaCur.type &amp;&amp; schemaCur.type === <span class="string">"RECORD"</span>) &#123;</span><br><span class="line">            <span class="keyword">if</span> (schemaCur.mode !== <span class="string">"REPEATED"</span>) &#123;</span><br><span class="line">                <span class="keyword">var</span> valIndex = <span class="number">0</span></span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">var</span> p <span class="keyword">in</span> schemaCur.fields) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (rowsCur.v === <span class="literal">null</span>) &#123;</span><br><span class="line">                        recurse(schemaCur.fields[p], rowsCur, colName + <span class="string">"."</span> + schemaCur.fields[p].name)</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        recurse(schemaCur.fields[p], rowsCur.v.f[valIndex], colName + <span class="string">"."</span> + schemaCur.fields[p].name)</span><br><span class="line">                    &#125;</span><br><span class="line">                    </span><br><span class="line">                    valIndex++</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; </span><br><span class="line">            </span><br><span class="line">            <span class="keyword">if</span> (schemaCur.mode === <span class="string">"REPEATED"</span>) &#123;   </span><br><span class="line">                result[colName] = [] </span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">in</span> rowsCur.v) &#123;</span><br><span class="line">                    recurse(schemaCur.fields, rowsCur.v[x], colName)</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">if</span> (schemaCur.mode === <span class="string">"REPEATED"</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (rowsCur.v !== <span class="literal">null</span>) &#123;</span><br><span class="line">                    result[colName] = rowsCur.v.map( <span class="function">(<span class="params">value, index</span>) =&gt;</span> &#123; <span class="keyword">return</span> value.v &#125;)</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    result[colName] = [ <span class="literal">null</span> ]</span><br><span class="line">                &#125;</span><br><span class="line">                </span><br><span class="line">            &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(result[colName])) &#123;</span><br><span class="line">                <span class="keyword">let</span> nextRow = &#123;&#125; </span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">var</span> j <span class="keyword">in</span> schemaCur) &#123;</span><br><span class="line">                    nextRow[colName + <span class="string">"."</span> + schemaCur[j].name] = <span class="built_in">Array</span>.isArray(rowsCur.v.f[j].v) ? rowsCur.v.f[j].v.map( <span class="function">(<span class="params">value, index</span>) =&gt;</span> &#123; <span class="keyword">return</span> value.v &#125;) : rowsCur.v.f[j].v</span><br><span class="line">                &#125;</span><br><span class="line">                result[colName].push(nextRow)</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="keyword">if</span> (colName !== <span class="string">""</span>)</span><br><span class="line">                    result[colName] = rowsCur.v</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">var</span> r=<span class="number">0</span>, rowsCount=rows.length; r&lt;rowsCount; r++) &#123;</span><br><span class="line">        <span class="keyword">var</span> result = &#123;&#125;;</span><br><span class="line">        recurse(schema, rows[r], <span class="string">""</span>)</span><br><span class="line">        resultRows.push(result)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> resultRows</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Have you ever wanted to convert the schema and results passed from the query API of BigQuery into something more acceptable?&lt;br&gt;There is an endless array of &lt;code&gt;{ f: { v: } }&lt;/code&gt; nests to contend with sometimes. Well now you can transform it into something simpler!&lt;/p&gt;
    
    </summary>
    
    
  </entry>
  
</feed>
