【问题标题】:BigQuery UDF using BYTES datatype使用 BYTES 数据类型的 BigQuery UDF
【发布时间】:2017-12-15 18:23:11
【问题描述】:

我目前正在尝试使用 Javascript 中的用户定义函数计算 BigQuery 中两个二进制字符串之间的汉明距离,我的架构非常简单:

row_id        STRING    
descriptors   BYTES REPEATED    
phash         BYTES

我发现有点令人困惑的是,您显然将 BigQuery 中的 BYTES 作为 Base64 字符串处理,我导入了 atob()btoa() 这两个函数,因此我可以使用二进制形式的字节字符串而不是 Base64 表示:

我的查询目前如下所示:

CREATE TEMP FUNCTION f_PHASH_distance(ph1 BYTES, ph2 BYTES)
    RETURNS INT64
   LANGUAGE js AS
   """
        return HammingDistance(ph1, ph2);
   """
    OPTIONS (
        library=["gs://test.appspot.com/HammingDistance.js",
                 "gs://test.appspot.com/btoa_atob.js"]
    );

SELECT f_PHASH_distance(phash, CAST("9Slp3g9OgVI=" AS BYTES)) 
  FROM ims.images WHERE row_id = "2333USX"

id = "2333USX" phash 的行在 base64 中等于 "9Slp3g9OgVI=",这意味着汉明距离为 0。但我目前得到的不是 0,而是 BigQuery 上的 35。

HammingDistance.js 有以下内容:

function HammingDistance(a, b){
    var count = 0;
    for(var i = 0; i < a.length; i++){
        // calculate XOR between the two chars
        var xor = a.charCodeAt(i) ^ b.charCodeAt(i);
        // count number of 1's on the result
        for(var j = 0; j < 16; j++){
            //add if LSB is 1
            count += xor % 2;
            //right shift the variable
            xor = xor >> 1;
        }
    }
    return count;
}

/**
 *  Calculates the distance between two Perceptual hashes of two images encoded
 *  in base 64
 */
function PHASHDistance(a, b){
    return HammingDistance(atob(a), atob(b));
} 

在浏览器的 JS 控制台中对其进行测试,我确实得到了预期的结果。所以我假设我在转换方面做错了,但是关于带有 BYTE 参数的 UDF 的文档非常稀缺。

任何帮助将不胜感激。

【问题讨论】:

    标签: google-bigquery user-defined-functions


    【解决方案1】:

    如果有人在比较常规字符串(不是二进制字符串作为这个问题)的情况下寻找解决方案,look at my answer here

    【讨论】:

      【解决方案2】:

      看起来问题在于您将"9Slp3g9OgVI=" 转换为字节,而不是将其从base64 转换为字节。我想你想要这个:

      SELECT f_PHASH_distance(phash, FROM_BASE64("9Slp3g9OgVI=")) 
      FROM ims.images WHERE row_id = "2333USX"
      

      不过,使用 SQL 函数而不是 JavaScript 函数可能会更好,因为 JavaScript 通常没有那么快。这是 SQL 中的汉明距离实现,假设字节长度相等:

      #standardSQL
      CREATE TEMP FUNCTION HammingDistance(b1 BYTES, b2 BYTES) AS (
        BIT_COUNT(b1 ^ b2)
      );
      
      WITH Input AS (
        SELECT b'defdef' AS bytes UNION ALL
        SELECT b'123de4' UNION ALL
        SELECT b'abc123'
      )
      SELECT HammingDistance(b'abcdef', bytes)
      FROM Input;
      

      它对两个字节值进行按位异或,然后检查有多少位不相同。

      【讨论】:

      • Elliot,SQL HammingDistance 似乎有一个小问题,它在以下示例中失败:CREATE TEMP FUNCTION HammingDistance(b1 BYTES, b2 BYTES) AS ( (SELECT COUNTIF(c != 0) FROM UNNEST(TO_CODE_POINTS(b1 ^ b2)) AS c) ); SELECT HammingDistance(FROM_BASE64("MA=="), FROM_BASE64("Mw=="))“MA==”是 0b110000 和“Mw==”的基数 64 表示" 0b110011 的 base 64 表示。看起来这种行为来自 TO_CODE_POINTS 返回一个字符数组而不是位数组这一事实。
      • 使用BIT_COUNT(b1 ^ b2) 似乎可以解决问题。
      • 对不起,我认为目的是获取每对字节是否匹配的信号。我更新了我的答案,改为使用 BIT_COUNT 和 xor。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2017-01-10
      • 2021-08-07
      • 2017-02-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多