Google bigquery 使用字节数据类型的BigQueryUDF

Google bigquery 使用字节数据类型的BigQueryUDF,google-bigquery,user-defined-functions,Google Bigquery,User Defined Functions,我目前正在使用Javascript中的用户定义函数计算BigQuery中两个二进制字符串之间的汉明距离,我的模式非常简单: row_id STRING descriptors BYTES REPEATED phash BYTES 我发现有点困惑的是,您显然将BigQuery中的字节作为Base64字符串处理,我导入了函数atob和btoa,因此我可以使用字节字符串的二进制形式,而不是Base64表示: 我的查询当前如下所示: CREATE TE

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

row_id        STRING    
descriptors   BYTES REPEATED    
phash         BYTES
我发现有点困惑的是,您显然将BigQuery中的字节作为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=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控制台中进行测试,我确实得到了预期的结果。因此,我假设我对强制转换做了一些错误的事情,但是关于带有字节参数的UDF的文档非常少


任何帮助都将不胜感激。

问题似乎在于您正在将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似乎有一个小问题,以下示例失败:创建临时函数HammingDistanceb1字节,b2字节为SELECT COUNTIFc!=0从UNNESTTO_代码_点B1^b2作为c;选择HammingDistanceFROM_BASE64MA==,FROM_BASE64Mw==MA==作为0b110000的基64表示形式,Mw==0b110011的基64表示形式。这种行为似乎源于这样一个事实:TO_CODE_POINTS返回一个字符数组,而不是一个位数组。使用BIT_COUNTb1^b2似乎可以解决这个问题。对不起,我以为这样做的目的是获取一个信号,表明每对字节是否匹配。我更新了我的答案,改为使用带xor的位计数。