Neo4j密码查询中的按位运算替代方案

时间:2016-02-05 14:06:31

标签: neo4j cypher bitwise-operators bitwise-and

我需要在cypher查询中做一个“和”。似乎cypher不支持按位操作。对替代品的任何建议? 这就是我想要发现的...... 例如268是(2 ^ 8 + 2 ^ 3 + 2 ^ 2),你可以看到2 ^ 3 = 8是我原始数字的一部分。因此,如果我使用按位AND,它将是(100001100)& (1000)= 1000所以这样我可以检测8是否是268的一部分。 如果没有按位支持,我怎么能这样做呢?有什么建议?我需要在密码中这样做。

5 个答案:

答案 0 :(得分:2)

使用cypher执行此类测试的另一种方法是将十进制值转换为表示设置位的小数的集合。

// convert the binary number to a collection of decimal parts
// create an index the size of the number to convert
// create a collection of decimals that correspond to the bit locations
with '100001100' as number
, [1,2,4,8,16,32,64,128,256,512,1024,2048,4096] as decimals
with number
, range(length(number)-1,0,-1) as index
, decimals[0..length(number)] as decimals

// map the bits to decimal equivalents
unwind index as i
with number, i, (split(number,''))[i] as binary_placeholder, decimals[-i-1] as decimal_placeholder

// multiply the decimal value by the bits that are set
with collect(decimal_placeholder * toInt(binary_placeholder)) as decimal_placeholders

// filter out the zero values from the collection
with filter(d in decimal_placeholders where d > 0) as decimal_placeholders
return decimal_placeholders

以下是此返回的示例。

enter image description here

然后,当您想测试数字是否为十进制数时,您可以只测试集合中存在的实际小数。

with [4, 8, 256] as decimal_placeholders
, 8 as decimal_to_test
return 
  case 
    when decimal_to_test in decimal_placeholders then
      toString(decimal_to_test) + ' value bit is set'
    else
      toString(decimal_to_test) + ' value bit is NOT set'
    end as bit_set_test

答案 1 :(得分:1)

如果你绝对必须在cypher中进行操作,可能更好的解决方案是使用cypher实现类似@ evan的SO解决方案Alternative to bitwise operation

您可以先使用看起来像这样的cypher转换数据......

// convert binary to a product of prime numbers
// start with the number to conver an a collection of primes
with '100001100' as number
, [2,3,5,7,13,17,19,23,29,31,37] as primes

// create an index based on the size of the binary number to convert
// take a slice of the prime array that is the size of the number to convert
with number
, range(length(number)-1,0,-1) as index
, primes[0..length(number)] as primes, decimals[0..length(number)] as decimals

// iterate over the index and match the prime number to the bits in the number to convert
unwind index as i
with (split(number,''))[i] as binary_place_holder, primes[-i-1] as prime_place_holder, decimals[-i-1] as decimal_place_holder

// collect the primes that are set by multiplying by the set bits
with collect(toInt(binary_place_holder) * prime_place_holder) as prime_placeholders

// filter out the zero bits
with filter(p in prime_placeholders where p > 0) as prime_placeholders

// return a product of primes of the set bits
return prime_placeholders, reduce(pp = 1, p in prime_placeholders | pp * p) as prime_product

以上查询的输出示例。可以调整查询以使用主要产品更新属性。

enter image description here

以下是转换失败的屏幕截图

enter image description here

然后,当您想要使用它时,您可以在要测试的位的位置使用素数的模数。

// test if the fourth bit is set in the decimal 268
// 268 is the equivalent of a prime product of 1015
// a modulus 7 == 0 will indicate the bit is set
with 1015 as prime_product
, [2,3,5,7,13,17,19,23,29,31,37] as primes
, 4 as bit_to_test
with bit_to_test
, prime_product
, primes[bit_to_test-1] as prime
, prime_product % primes[bit_to_test-1] as mod_remains
with 
  case when mod_remains = 0 then
    'bit ' + toString(bit_to_test) + ' set'
  else
    'bit ' + toString(bit_to_test) + ' NOT set'
  end as bit_set
return bit_set

答案 2 :(得分:1)

或者,如果有APOC可用,他们可以使用apoc.bitwise.op,这是java按位操作的包装。

RETURN apoc.bitwise.op(268, "&",8 ) AS `268_AND_8`

产生以下结果

enter image description here

答案 3 :(得分:0)

这几乎肯定会破坏选择按位操作的目的,但如果你绝对需要 AND cypher中的两个二进制数,你可以用集合做这样的事情。

with split('100001100', '') as bin_term_1
, split('000001000', '') as bin_term_2
, toString(1) as one
with bin_term_1, bin_term_2, one, range(0,size(bin_term_1)-1,1) as index
unwind index as i
with i, bin_term_1, bin_term_2, one,
case 
  when (bin_term_1[i] = one) and (bin_term_2[i] = one) then
    1
  else
    0
  end as r
return collect(r) as AND

答案 4 :(得分:0)

谢谢戴夫。我尝试了你的解决方案,他们都工作了。这对我来说是一个很好的暗示,可以找到另一种方法。这就是我解决它的方式。我使用了String比较。

 with '100001100' as number , '100000000' as sub_number
 with number,sub_number,range(length (number)-1,length (number)-length(sub_number),-1) as tail,length (number)-length(sub_number) as difference
 unwind tail as i
 with i,sub_number,number, i - length (number) + length (sub_number) as sub_number_position
 with sub_number_position, (split(number,''))[i-1] as bit_mask , (split(sub_number,''))[sub_number_position] as sub_bit 
 with collect(toInt(bit_mask) * toInt(sub_bit)) as result

return result

显然,number和sub_number可以有不同的值。