exp_hll.js

// *****************************************************************************
// Copyright 2022-2023 Aerospike, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// *****************************************************************************
const as = require('bindings')('aerospike.node')
const exp = as.exp
const hlls = as.hll

const _valueExp = (op, valName) => (value) => [{ op, [valName]: value }]
const _int = _valueExp(exp.ops.VAL_INT, 'intVal')
const _rtype = _valueExp(exp.ops.VAL_RTYPE, 'intVal')
/*********************************************************************************
 * HLL MODIFY EXPRESSIONS
 *********************************************************************************/

const _hllModify = () => [
  { op: exp.ops.CALL, count: 5 },
  ..._rtype(exp.type.HLL),
  ..._int(exp.sys.CALL_HLL | exp.sys.FLAG_MODIFY_LOCAL)
]

const _hllModifyStart = (op, param) => [
  ..._hllModify(),
  { op: exp.ops.CALL_VOP_START, count: 1 + param },
  ..._int(op)
]

const _hllRead = (returnType) => [
  { op: exp.ops.CALL, count: 5 },
  ..._rtype(returnType),
  ..._int(exp.sys.CALL_HLL)
]

const _hllReadStart = (returnType, op, param) => [
  ..._hllRead(returnType),
  { op: exp.ops.CALL_VOP_START, count: 1 + param },
  ..._int(op)
]
/**
 * @module aerospike/exp/hll
 *
 * @description The {@link module:aerospike/exp/hll|aerospike/exp/hll} module defines functions
 * for expressions on the HyperLogLog datatype.
 */
module.exports = {
  /**
 * Create expression that creates a new HLL or resets an existing HLL with minhash bits.
 *
 * @param {Object} policy hll policy value.
 * @param {number} indexBitCount Number of index bits. Must be between 4 and 16 inclusive.
 * @param {number} mhBitCount Number of min hash bits. Must be between 4 and 51 inclusive.
 * @param {AerospikeExp} bin  A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin Returns the resulting hll bin.
 */
  initMH: (bin, mhBitCount, indexBitCount, policy = null) => [
    ..._hllModifyStart(hlls.opcodes.INIT, 3),
    ..._int(indexBitCount),
    ..._int(mhBitCount),
    ..._int((policy ? policy.flags : 0)),
    ...bin
  ],

  /**
 * Create expression that creates a new HLL or resets an existing HLL.
 *
 * @param {Object} policy hll policy value.
 * @param {number} indexBitCount Number of index bits. Must be between 4 and 16 inclusive.
 * @param {AerospikeExp} bin  A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin Returns the resulting hll bin.
 */
  init: (bin, indexBitCount, policy = null) => [
    ..._hllModifyStart(hlls.opcodes.INIT, 2),
    ..._int(indexBitCount),
    ..._int((policy ? policy.flags : 0)),
    ...bin
  ],

  /**
 * Create an expression that performs operations hll addMh.
 *
 * @param {Object} policy hll policy value.
 * @param {AerospikeExp} list A list expression of elements to add to the HLL.
 * @param {number} indexBitCount Number of index bits. Must be between 4 and 16 inclusive.
 * @param {number} mhBitCount Number of min hash bits. Must be between 4 and 51 inclusive.
 * @param {AerospikeExp} bin  A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin Returns the resulting hll bin after adding elements from list.
 */
  addMH: (bin, mhBitCount, indexBitCount, list, policy = null) => [
    ..._hllModifyStart(hlls.opcodes.ADD, 4),
    ...list,
    ..._int(indexBitCount),
    ..._int(mhBitCount),
    ..._int((policy ? policy.flags : 0)),
    ...bin
  ],

  /**
 * Create an expression that performs operations hll add.
 *
 * @param {Object} policy hll policy value.
 * @param {AerospikeExp} list A list expression of elements to add to the HLL.
 * @param {number} indexBitCount Number of index bits. Must be between 4 and 16 inclusive.
 * @param {AerospikeExp} bin  A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin Returns the resulting hll bin after adding elements from list.
 */
  add: (bin, indexBitCount, list, policy = null) => [
    ..._hllModifyStart(hlls.opcodes.ADD, 4),
    ...list,
    ..._int(indexBitCount),
    ..._int(-1),
    ..._int((policy ? policy.flags : 0)),
    ...bin
  ],

  /**
 * Create an expression that performs operations hll update.
 *
 * @param {Object} policy hll policy value.
 * @param {AerospikeExp} list A list expression of elements to add to the HLL.
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin Returns the resulting hll bin after adding elements from list.
 */
  update: (bin, list, policy = null) => [
    ..._hllModifyStart(hlls.opcodes.ADD, 4),
    ...list,
    ..._int(-1),
    ..._int(-1),
    ..._int((policy ? policy.flags : 0)),
    ...bin
  ],

  /*********************************************************************************
 * HLL READ EXPRESSIONS
 *********************************************************************************/

  /**
 * Create an expression that performs operations hll get count.
 *
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} integer bin The estimated number of unique elements in an HLL.
 */
  getCount: (bin) => [
    ..._hllReadStart(exp.type.INT, hlls.opcodes.COUNT, 0),
    ...bin
  ],

  /**
 * Create an expression that performs operations hll get union.
 *
 * @param {AerospikeExp} list A list expression of HLLs to union with.
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} hll bin HLL bin representing the set union.
 */
  getUnion: (bin, list) => [
    ..._hllReadStart(exp.type.HLL, hlls.opcodes.GET_UNION, 1),
    ...list,
    ...bin
  ],

  /**
 * Create an expression that performs operations hll get union count.
 *
 * @param {AerospikeExp} list A list expression of HLLs to union with.
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} integer bin Estimated number of elements in the set union.
 */
  getUnionCount: (bin, list) => [
    ..._hllReadStart(exp.type.INT, hlls.opcodes.UNION_COUNT, 1),
    ...list,
    ...bin
  ],

  /**
 * Create an expression that performs operations hll get inersect count.
 *
 * @param {AerospikeExp} list A list expression of HLLs to intersect with.
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} integer bin Estimated number of elements in the set intersection.
 */
  getIntersectCount: (bin, list) => [
    ..._hllReadStart(exp.type.INT, hlls.opcodes.INTERSECT_COUNT, 1),
    ...list,
    ...bin
  ],

  /**
 * Create an expression that performs operations hll get similarity.
 *
 * @param {AerospikeExp} list A list expression of HLLs to calculate similarity with..
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return (float bin) Estimated similarity between 0.0 and 1.0.
 */
  getSimilarity: (bin, list) => [
    ..._hllReadStart(exp.type.FLOAT, hlls.opcodes.SIMILARITY, 1),
    ...list,
    ...bin
  ],

  /**
 * Create an expression that performs operations hll describe.
 *
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} list bin A list containing the index_bit_count and minhash bit count.
 */
  describe: (bin) => [
    ..._hllReadStart(exp.type.LIST, hlls.opcodes.DESCRIBE, 0),
    ...bin
  ],

  /**
 * Create an expression that checks if the HLL bin contains all keys in
 *  list..
 *
 * @param {AerospikeExp} list A list expression of keys to check if the HLL may contain them.
 * @param {AerospikeExp} bin A bin expression to apply this function to.
 * @return {AerospikeExp} integer bin 1 bin contains all of list, 0 otherwise.
 */
  mayContain: (bin, list) => [
    ..._hllReadStart(exp.type.INT, hlls.opcodes.MAY_CONTAIN, 1),
    ...list,
    ...bin
  ]
}