// *****************************************************************************
// Copyright 2013-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.
// *****************************************************************************
'use strict'
const as = require('bindings')('aerospike.node')
const opcodes = as.mapOperations
const Context = require('./cdt_context')
const Operation = require('./operations').Operation
/**
* @module aerospike/maps
*
* @description This module defines operations on the Sorted Map data type that
* can be used with the {@link Client#operate} command. Operations on Sorted
* Maps require Aerospike Server
* <a href="http://www.aerospike.com/download/server/notes.html#3.8.4">⇑version 3.8.4</a>
* or later.
*
* For more information, please refer to the
* <a href="http://www.aerospike.com/docs/guide/cdt-map.html">⇑Maps</a>
* documentation in the Aerospike Feature Guide.
*
* #### Sorted Maps
*
* The Map data type supports both unordered and ordered maps. Maps can be
* ordered by key, or by key and value. By default, maps are unordered. The map
* order is controlled through the map policy and can be set either when the
* map is created through the {@link module:aerospike/maps.put|put} or {@link
* module:aerospike/maps.putItems|putItems} operations or later on through the
* {@link module:aerospike/maps.setPolicy|setPolicy} operation.
*
* All maps maintain an index and a rank. The index is the item offset from the
* start of the map, for both unordered and ordered maps. The rank is the
* sorted index of the value component. Map supports negative indexing for
* index and rank.
*
* Index examples:
*
* - Index 0: First item in map.
* - Index 4: Fifth item in map.
* - Index -1: Last item in map.
* - Index -3: Third to last item in map.
* - Index 1 Count 2: Second and third items in map.
* - Index -3 Count 3: Last three items in map.
* - Index -5 Count 4: Range between fifth to last item to second to last item inclusive.
*
* Rank examples:
*
* - Rank 0: Item with lowest value rank in map.
* - Rank 4: Fifth lowest ranked item in map.
* - Rank -1: Item with highest ranked value in map.
* - Rank -3: Item with third highest ranked value in map.
* - Rank 1 Count 2: Second and third lowest ranked items in map.
* - Rank -3 Count 3: Top three ranked items in map.
*
* #### CDT Context - Operating on Nested Maps
*
* To operate on nested maps, use the {@link
* module:aerospike/maps~MapOperation#withContext MapOperation#withContext}
* function to set the context for a map operation.
*
* @see {@link Client#operate}
*
* @example <caption>Manipulating a map bin using map operations</caption>
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}),
* remove : new Aerospike.RemovePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
*
* Aerospike.connect(config).then(async client => {
* let ops = [
* maps.put('map', 'e', 5, {
* order: maps.order.KEY_ORDERED
* }), // => { e: 5 }
* maps.putItems('map', { d: 4, b: 2, c: 3 }), // => { b: 2, c: 3, d: 4, e: 5 }
* maps.putItems('map', { c: 99, a: 1 }, {
* writeFlags: maps.writeFlags.CREATE_ONLY
* | maps.writeFlags.NO_FAIL
* | maps.writeFlags.PARTIAL
* }), // => { a: 1, b: 2, c: 3, d: 4, e: 5 }
* maps.removeByValue('map', 3), // => { a: 1, b: 2, d: 4, e: 5 }
* maps.removeByIndexRange('map', -2)
* .andReturn(maps.returnType.KEY) // => { a: 1, b: 2 }
* ]
* let result = await client.operate(key, ops)
* console.log(result.bins.map) // => ['d', 'e']
* let record = await client.get(key)
* console.log(record.bins.map) // => { a: 1, b: 2 }
* await client.remove(key)
* client.close()
* })
*/
/**
* @class module:aerospike/maps~MapOperation
*
* @classdesc Use the methods in the {@link module:aerospike/maps|maps}
* module to create map operations for use with the {@link Client#operate}
* command.
*/
class MapOperation extends Operation {
}
/**
* @summary Set the return type for certain map operations.
*
* @description The return type only affects <code>getBy\*</code> and
* <code>removeBy\*</code> map operations.
*
* @param {number} returnType - The {@link
* module:aerospike/maps.returnType|return type} indicating what data of the
* selected items to return.
*
* @example <caption>Remove map keys in a given range and return the values</caption>
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config).then(async client => {
* await client.put(key, { map: { a: 1, b: 2, c: 3, d: 4, e: 5 } })
* const ops = [
* maps.removeByKeyRange('map', 'b', 'd')
* .andReturn(maps.returnType.VALUE)
* ]
* const result = await client.operate(key, ops)
* console.info('Result:', result.bins.map) // => Result: [ 2, 3 ]
* client.close()
* })
*/
MapOperation.prototype.andReturn = function (returnType) {
this.returnType = returnType
return this
}
/**
* @summary By setting the context, the map operation will be executed on a
* nested map, instead of the bin value itself.
*
* @param { CdtContext | function } context - Either a CdtContext object, or a
* function which accepts a CdtContext object.
* @returns { MapOperation } The map operation itself.
*
* @since v3.12.0
*
* @example <caption>Fetch the value with the key 'b' from the 2nd nested map</caption>
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapsTest')
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config).then(async (client) => {
* await client.put(key, { maps: [{ a: 1, b: 2 }, { b: 3, c: 4 }] })
* const ops = [
* maps.getByKey('maps', 'b')
* .withContext((ctx) => ctx.addListIndex(1))
* .andReturn(maps.returnType.VALUE)
* ]
* const result = await client.operate(key, ops)
* console.info('Result:', result.bins.maps) // => Result: 3
* client.close()
* })
*
* @example <caption>Fetch the value with the key 'b' from the nested map under the key 'alpha'</caption>
*
* const Aerospike = require('./')
* const maps = Aerospike.maps
* const Context = Aerospike.cdt.Context
* const key = new Aerospike.Key('test', 'demo', 'listsTest')
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config).then(async (client) => {
* await client.put(key, { maps: { alpha: { a: 1, b: 2 }, beta: { b: 3, c: 4 } } })
* const context = new Context().addMapKey('alpha')
* const ops = [
* maps.getByKey('maps', 'b')
* .withContext(context)
* .andReturn(maps.returnType.VALUE)
* ]
* const result = await client.operate(key, ops)
* console.info('Result:', result.bins.maps) // => Result: 2
* client.close()
* })
*/
MapOperation.prototype.withContext = function (contextOrFunction) {
if (typeof contextOrFunction === 'object') {
this.context = contextOrFunction
} else if (typeof contextOrFunction === 'function') {
this.context = new Context()
contextOrFunction(this.context)
}
return this
}
/**
* @summary Map order.
*
* @description The order determines what kind of index the Aerospike server
* maintains for the map.
*
* @type Object
* @property {number} UNORDERED - Map is not ordered. This is the default.
* @property {number} KEY_ORDERED - Order map by key.
* @property {number} KEY_VALUE_ORDERED - Order map by key, then value.
*/
exports.order = as.maps.order
/**
* @summary Map write mode.
*
* @description Write mode is used to determine the criteria for a successful operation.
*
* Map write mode should only be used for server versions prior to v4.3. For
* server versions v4.3 or later, the use of {@link
* module:aerospike/maps.writeFlags|writeFlags} is recommended.
*
* @type Object
* @property {number} UPDATE - If the key already exists, the item will be
* overwritten. If the key does not exist, a new item will be created. This is
* the default write mode.
* @property {number} UPDATE_ONLY - If the key already exists, the item will be
* overwritten. If the key does not exist, the write will fail.
* @property {number} CREATE_ONLY - If the key already exists, the write will
* fail. If the key does not exist, a new item will be created.
*
* @deprecated since v3.5.0
*/
exports.writeMode = as.maps.writeMode
/**
* @summary Map write flags.
*
* @description Write flags are used to determine the criteria for a successful operation.
*
* Map write flags require server version v4.3 or later. For earier server
* versions, set the {@link module:aerospike/maps.writeMode|writeMode} instead.
*
* @type Object
* @property {number} DEFAULT - Allow create or update. Default.
* @property {number} CREATE_ONLY - If the key already exists, the item will be
* denied. If the key does not exist, a new item will be created.
* @property {number} UPDATE_ONLY - If the key already exists, the item will be
* overwritten. If the key does not exist, the item will be denied.
* @property {number} NO_FAIL - Do not raise error, if map item is denied due
* to write flag constraints.
* @property {number} PARTIAL - Allow other valid map items to be committed, if
* a map item is denied due to write flag constraints.
*
* @since v3.5.0
*/
exports.writeFlags = as.maps.writeFlags
/**
* @summary Map return type.
*
* @description The return type determines what data of the selected items the
* get and remove operations return in the result of the {@link Client#operate}
* command. It is optional to specify the return type for remove operations;
* default is <code>NONE</code>. For get operations the return type parameter
* is required.
*
* @type Object
* @property {number} NONE - Do not return a result; this is the default.
* @property {number} INDEX - Return key index order. (0 = first key, 1 =
* second key, ...)
* @property {number} REVERSE_INDEX - Return reverse key order. (0 = last key,
* -1 = second last key, ...)
* @property {number} RANK - Return value order. (0 = smallest value, 1 =
* second smallest value, ...)
* @property {number} REVERSE_RANK - Return reverse value order. (0 = largest
* value, -1 = second largest value, ...)
* @property {number} COUNT - Return count of items selected.
* @property {number} KEY - Return key for single key read and key list for
* range read.
* @property {number} VALUE - Return value for single key read and value list
* for range read.
* @property {number} KEY_VALUE - Return map items keys and values as an Array.
* i.e. [key1, value1, key2, value2, ...].
* @property {number} EXISTS - Return true if count > 0.
* @property {number} UNORDERED_MAP - Return an unordered map.
* @property {number} ORDERED_MAP - Return an ordered map.
*/
exports.returnType = as.maps.returnType
/**
* @summary Sets map policy attributes.
*
* @description This operation does not return any result.
*
* @param {string} bin - The name of the bin. The bin must contain a Map value.
* @param {MapPolicy} policy - The map policy.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.setPolicy = function (bin, policy) {
const op = new MapOperation(opcodes.MAP_SET_POLICY, bin)
op.policy = policy
return op
}
/**
* @summary Writes a key/value item to the map.
*
* @description Depending on the map policy and whether an entry with the same
* key already exists in the map, a new key will be added to the map or the
* existing entry with the same key will be updated. If the bin does not yet
* contain a map value, a new map may be created.
*
* This operation returns the new size of the map.
*
* @param {string} bin - The name of the bin. If the bin exists, it must
* contain a Map value; if it does not yet exist, a new Map may be created
* depending on the map policy's write mode.
* @param {any} key - Map key to write.
* @param {any} value - Map value to write.
* @param {MapPolicy} [policy] - The map policy.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.put = function (bin, key, value, policy) {
const op = new MapOperation(opcodes.MAP_PUT, bin)
op.key = key
op.value = value
op.policy = policy
return op
}
/**
* @summary Writes each entry of the given map to the map bin on the server.
*
* @description For each item, depending on the map policy and whether an entry with the same
* key already exists in the map, a new entry will be added to the map or the
* existing entry with the same key will be updated. If the bin does not yet
* contain a map value, a new map may be created.
*
* This operation returns the new size of the map.
*
* @param {string} bin - The name of the bin. If the bin exists, it must
* contain a Map value; if it does not yet exist, a new Map may be created
* depending on the map policy's write mode.
* @param {object} items - One or more key value pairs to write to the map.
* @param {MapPolicy} [policy] - The map policy.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.putItems = function (bin, items, policy) {
const op = new MapOperation(opcodes.MAP_PUT_ITEMS, bin)
op.items = items
op.policy = policy
return op
}
/**
* @summary Increments the map entry identified by the given key by the value
* <code>incr</code>. Valid only for numeric values.
*
* @description If a map entry with the given key does not exist, the map
* policy's write mode determines whether a new entry will be created same as
* for the {@link module:aerospike/maps.put|put} command. This operation may
* create a new map if the map bin is currently empty.
*
* This operation returns the new value of the map entry.
*
* @param {string} bin - The name of the bin. If the bin exists, it must
* contain a Map value; if it does not yet exist, a new Map may be created
* depending on the map policy's write mode.
* @param {any} key - The map key.
* @param {number} incr - The value to increment the map entry by. Use negative
* value to decrement map entry.
* @param {MapPolicy} [policy] - The map policy.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.increment = function (bin, key, incr, policy) {
const op = new MapOperation(opcodes.MAP_INCREMENT, bin)
op.key = key
op.incr = incr
op.policy = policy
return op
}
/**
* @summary Decrements the map entry identified by the given key by the value
* <code>decr</code>. Valid only for numeric values.
*
* @description If a map entry with the given key does not exist, the map
* policy's write mode determines whether a new entry will be created same as
* for the {@link module:aerospike/maps.put|put} command. This operation may
* create a new map if the map bin is currently empty.
*
* This operation returns the new value of the map entry.
*
* @param {string} bin - The name of the bin. If the bin exists, it must
* contain a Map value; if it does not yet exist, a new Map may be created
* depending on the map policy's write mode.
* @param {any} key - The map key.
* @param {number} decr - The value to decrement the map entry by.
* @param {MapPolicy} [policy] - The map policy.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @deprecated since v4.0.0 - use increment function with negative value instead.
*/
exports.decrement = function (bin, key, decr, policy) {
const op = new MapOperation(opcodes.MAP_DECREMENT, bin)
op.key = key
op.decr = decr
op.policy = policy
return op
}
/**
* @summary Removes all items in the map.
*
* @description This operation does not return any result.
*
* @param {string} bin - The name of the bin. If the bin exists, it must
* contain a Map value; if it does not yet exist, a new Map may be created
* depending on the map policy's write mode.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.clear = function (bin) {
return new MapOperation(opcodes.MAP_CLEAR, bin)
}
/**
* @summary Removes a single item identified by key from the map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} key - The map key.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByKey = function (bin, key, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_KEY, bin)
op.key = key
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items identified by key from the map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {Array<any>} keys - An array of map keys.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByKeyList = function (bin, keys, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_KEY_LIST, bin)
op.keys = keys
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items identified by a range of keys from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {?any} begin - Start key in the range (inclusive). If set to
* <code>null</code>, the range includes all keys less than the
* <code>end</code> key.
* @param {?any} end - End key in the range (exclusive). If set to
* <code>null</code>, the range includes all keys greater than or equal to the
* <code>begin</code> key.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByKeyRange = function (bin, begin, end, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_KEY_RANGE, bin)
op.begin = begin
op.end = end
op.returnType = returnType
return op
}
/**
* @summary Removes map items nearest to key and greater, by index, from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* Examples for map { a: 17, e: 2, f: 15, j: 10 }:
*
* * (value, index, count) = [removed items]
* * ('f', 0, 1) = { f: 15 }
* * ('f', 1, 2) = { j: 10 }
* * ('f', -1, 1) = { e: 2 }
* * ('b', 2, 1) = { j: 10 }
* * ('b', -2, 2) = { a: 17 }
*
* Without count:
*
* * (value, index) = [removed items]
* * ('f', 0) = { f: 15, j: 10 }
* * ('f', 1) = { j: 10 }
* * ('f', -1) = { e: 2, f: 15, j: 10 }
* * ('b', 2) = { j: 10 }
* * ('b', -2) = { a: 17, e: 2, f: 15, j: 10 }
*
* Requires Aerospike Server v4.3.0 or later.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} key - Find map items nearest to this key and greater.
* @param {number} index - Index of items to be removed relative to the given key.
* @param {number} [count] - Number of items to remove. If undefined, the range
* includes all items nearest to key and greater, until the end.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*
* @since v3.5.0
*
* @example
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* read : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* write : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config)
* .then(async client => {
* await client.put(key, { map: { a: 17, e: 2, f: 15, j: 10 } })
* let result = await client.operate(key, [
* maps.removeByKeyRelIndexRange('map', 'f', -1, 1)
* .andReturn(maps.returnType.KEY_VALUE)])
* console.info(result.bins.map) // => [ 'e', 2 ]
* let record = await client.get(key)
* console.info(record.bins.map) // => { a: 17, f: 15, j: 10 }
* client.close()
* })
*/
exports.removeByKeyRelIndexRange = function (bin, key, index, count, returnType) {
return new MapOperation(opcodes.MAP_REMOVE_BY_KEY_REL_INDEX_RANGE, bin, {
key,
index,
count,
returnType
})
}
/**
* @summary Removes one or more items identified by a single value from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} value - The map value.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByValue = function (bin, value, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_VALUE, bin)
op.value = value
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items identified by a list of values from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {Array<any>} values - An array of map values.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByValueList = function (bin, values, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_VALUE_LIST, bin)
op.values = values
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items identified by a range of values from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {?any} begin - Start values in the range (inclusive). If set to
* <code>null</code>, the range includes all values less than the
* <code>end</code> value.
* @param {?any} end - End value in the range (exclusive). If set to
* <code>null</code>, the range includes all values greater than or equal to the
* <code>begin</code> value.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByValueRange = function (bin, begin, end, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_VALUE_RANGE, bin)
op.begin = begin
op.end = end
op.returnType = returnType
return op
}
/**
* @summary Removes map items nearest to value and greater, by relative rank.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* Examples for map { e: 2, j: 10, f: 15, a: 17 }:
*
* * (value, rank, count) = [removed items]
* * (11, 1, 1) = { a: 17 }
* * (11, -1, 1) = { j: 10 }
*
* Without count:
*
* * (value, rank) = [removed items]
* * (11, 1) = { a: 17 }
* * (11, -1) = { j: 10, f: 15, a: 17 }
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} value - Find map items nearest to this value and greater.
* @param {number} rank - Rank of items to be removed relative to the given value.
* @param {number} [count] - Number of items to remove. If undefined, the range
* includes all items nearest to value and greater, until the end.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*
* @since v3.5.0
*
* @example
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* read : new Aerospike.ReadPolicy({socketTimeout : 0, totalTimeout : 0}),
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config)
* .then(async client => {
* await client.put(key, { map: { e: 2, j: 10, f: 15, a: 17 } })
* let result = await client.operate(key, [
* maps.removeByValueRelRankRange('map', 11, -1)
* .andReturn(maps.returnType.KEY_VALUE)])
* console.info(result.bins.map) // => [ 'j', 10, 'f', 15, 'a', 17 ]
* let record = await client.get(key)
* console.info(record.bins.map) // => { e: 2 }
* client.close()
* })
*/
exports.removeByValueRelRankRange = function (bin, value, rank, count, returnType) {
return new MapOperation(opcodes.MAP_REMOVE_BY_VALUE_REL_RANK_RANGE, bin, {
value,
rank,
count,
returnType
})
}
/**
* @summary Removes a single item identified by its index value from the map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Index of the entry to remove.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByIndex = function (bin, index, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_INDEX, bin)
op.index = index
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items in the specified index range from the
* map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Starting index.
* @param {number} [count] - Number of items to delete. If undefined, the range
* includes all items starting from <code>index</code>.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByIndexRange = function (bin, index, count, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_INDEX_RANGE, bin)
op.index = index
op.count = count
op.returnType = returnType
return op
}
/**
* @summary Removes a single item identified by its rank value from the map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} rank - Rank of the item to remove.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByRank = function (bin, rank, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_RANK, bin)
op.rank = rank
op.returnType = returnType
return op
}
/**
* @summary Removes one or more items in the specified rank range from the map.
*
* @description This operation returns the removed data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Starting rank.
* @param {number} [count] - Number of items to delete. If undefined, the range
* includes all items starting from <code>rank</code>.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the affected item(s) to return (if any).
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.removeByRankRange = function (bin, rank, count, returnType) {
const op = new MapOperation(opcodes.MAP_REMOVE_BY_RANK_RANGE, bin)
op.rank = rank
op.count = count
op.returnType = returnType
return op
}
/**
* @summary Returns the size of the map.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*/
exports.size = function (bin) {
return new MapOperation(opcodes.MAP_SIZE, bin)
}
/**
* @summary Retrieves a single item identified by key from the map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} key - The map key.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByKey = function (bin, key, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_KEY, bin)
op.key = key
op.returnType = returnType
return op
}
/**
* @summary Retrieves map items identified by keys list.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} keys - The map keys.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByKeyList = function (bin, keys, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_KEY_LIST, bin)
op.keys = keys
op.returnType = returnType
return op
}
/**
* @summary Retrieves one or more items identified by a range of keys from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {?any} begin - Start key in the range (inclusive). If set to
* <code>null</code>, the range includes all keys less than the
* <code>end</code> key.
* @param {?any} end - End key in the range (exclusive). If set to
* <code>null</code>, the range includes all keys greater than or equal to the
* <code>begin</code> key.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByKeyRange = function (bin, begin, end, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_KEY_RANGE, bin)
op.begin = begin
op.end = end
op.returnType = returnType
return op
}
/**
* @summary Retrieves map items nearest to key and greater, by index, from the
* map.
*
* @description This operation returns the selected data specified by
* <code>returnType</code>.
*
* Examples for map { a: 17, e: 2, f: 15, j: 10 }:
*
* * (value, index, count) = [selected items]
* * ('f', 0, 1) = { f: 15 }
* * ('f', 1, 2) = { j: 10 }
* * ('f', -1, 1) = { e: 2 }
* * ('b', 2, 1) = { j: 10 }
* * ('b', -2, 2) = { a: 17 }
*
* Without count:
*
* * (value, index) = [selected items]
* * ('f', 0) = { f: 15, j: 10 }
* * ('f', 1) = { j: 10 }
* * ('f', -1) = { e: 2, f: 15, j: 10 }
* * ('b', 2) = { j: 10 }
* * ('b', -2) = { a: 17, e: 2, f: 15, j: 10 }
*
* Requires Aerospike Server v4.3.0 or later.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} key - Find map items nearest to this key and greater.
* @param {number} index - Index of items to be retrieved relative to the given key.
* @param {number} [count] - Number of items to retrieve. If undefined, the
* range includes all items nearest to key and greater, until the end.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*
* @since v3.5.0
*
* @example
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
* Aerospike.connect(config)
* .then(async client => {
* await client.put(key, { map: { a: 17, e: 2, f: 15, j: 10 } })
* let result = await client.operate(key, [
* maps.getByKeyRelIndexRange('map', 'b', 2, 1)
* .andReturn(maps.returnType.KEY_VALUE)])
* console.info(result.bins.map) // => [ 'j', 10 ]
* client.close()
* })
*/
exports.getByKeyRelIndexRange = function (bin, key, index, count, returnType) {
return new MapOperation(opcodes.MAP_GET_BY_KEY_REL_INDEX_RANGE, bin, {
key,
index,
count,
returnType
})
}
/**
* @summary Retrieves one or more items identified by a single value from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} value - The map value.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByValue = function (bin, value, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_VALUE, bin)
op.value = value
op.returnType = returnType
return op
}
/**
* @summary Retrieves map items identified by values from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} values - The map values.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByValueList = function (bin, values, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_VALUE_LIST, bin)
op.values = values
op.returnType = returnType
return op
}
/**
* @summary Retrieves one or more items identified by a range of values from
* the map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {?any} begin - Start values in the range (inclusive). If set to
* <code>null</code>, the range includes all values less than the
* <code>end</code> value.
* @param {?any} end - End value in the range (exclusive). If set to
* <code>null</code>, the range includes all values greater than or equal to the
* <code>begin</code> value.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByValueRange = function (bin, begin, end, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_VALUE_RANGE, bin)
op.begin = begin
op.end = end
op.returnType = returnType
return op
}
/**
* @summary Retrieves map items nearest to value and greater, by relative rank.
*
* @description This operation returns the selected data specified by
* <code>returnType</code>.
*
* Examples for map { e: 2, j: 10, f: 15, a: 17 }:
*
* * (value, rank, count) = [selected items]
* * (11, 1, 1) = { a: 17 }
* * (11, -1, 1) = { j: 10 }
*
* Without count:
*
* * (value, rank) = [selected items]
* * (11, 1) = { a: 17 }
* * (11, -1) = { j: 10, f: 15, a: 17 }
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {any} value - Find map items nearest to this value and greater.
* @param {number} rank - Rank of items to be retrieved relative to the given value.
* @param {number} [count] - Number of items to retrieve. If undefined, the
* range includes all items nearest to value and greater, until the end.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*
* @since v3.5.0
*
* @example
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* write : new Aerospike.WritePolicy({socketTimeout : 0, totalTimeout : 0}),
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
*
* }
* }
* Aerospike.connect(config)
* .then(async client => {
* await client.put(key, { map: { e: 2, j: 10, f: 15, a: 17 } })
* let result = await client.operate(key, [
* maps.getByValueRelRankRange('map', 11, 1, 1)
* .andReturn(maps.returnType.KEY_VALUE)])
* console.info(result.bins.map) // => [ 'a', 17 ]
* client.close()
* })
*/
exports.getByValueRelRankRange = function (bin, value, rank, count, returnType) {
return new MapOperation(opcodes.MAP_GET_BY_VALUE_REL_RANK_RANGE, bin, {
value,
rank,
count,
returnType
})
}
/**
* @summary Retrieves a single item identified by it's index value from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Index of the entry to remove.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByIndex = function (bin, index, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_INDEX, bin)
op.index = index
op.returnType = returnType
return op
}
/**
* @summary Retrieves one or more items in the specified index range from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Starting index.
* @param {number} [count] - Number of items to delete. If undefined, the range
* includes all items starting from <code>index</code>.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByIndexRange = function (bin, index, count, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_INDEX_RANGE, bin)
op.index = index
op.count = count
op.returnType = returnType
return op
}
/**
* @summary Retrieves a single item identified by it's rank value from the map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} rank - Rank of the entry to remove.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByRank = function (bin, rank, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_RANK, bin)
op.rank = rank
op.returnType = returnType
return op
}
/**
* @summary Retrieves one or more items in the specified rank range from the
* map.
*
* @description This operation returns the data specified by
* <code>returnType</code>.
*
* @param {string} bin - The name of the bin, which must contain a Map value.
* @param {number} index - Starting rank.
* @param {number} count - Number of items to delete; if not specified, the
* range includes all items starting from <code>rank</code>.
* @param {number} [returnType] - The {@link module:aerospike/maps.returnType|return type}
* indicating what data of the selected item(s) to return.
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @see Instead of passing <code>returnType</code>, you can also use
* {@link module:aerospike/maps~MapOperation#andReturn|MapOperation#andReturn} to
* select what data to return.
*/
exports.getByRankRange = function (bin, rank, count, returnType) {
const op = new MapOperation(opcodes.MAP_GET_BY_RANK_RANGE, bin)
op.rank = rank
op.count = count
op.returnType = returnType
return op
}
/**
* @summary Creates map create operation.
*
*
* @param {string} bin - bin name.
* @param {number} order - map order.
* @param {persistIndex} count - if true, persist map index. A map index improves lookup performance, but requires more storage.
* A map index can be created for a top-level ordered map only. Nested and unordered map indexes are not supported.
* @param {number} ctx - optional path to nested map. If not defined, the top-level map is used.
*
* @returns {Object} Operation that can be passed to the {@link Client#operate} command.
*
* @example
*
* const Aerospike = require('aerospike')
* const maps = Aerospike.maps
* const key = new Aerospike.Key('test', 'demo', 'mapKey')
*
* // INSERT HOSTNAME AND PORT NUMBER OF AEROSPIKE SERVER NODE HERE!
* var config = {
* hosts: '192.168.33.10:3000',
* // Timeouts disabled, latency dependent on server location. Configure as needed.
* policies: {
* operate : new Aerospike.OperatePolicy({socketTimeout : 0, totalTimeout : 0})
* }
* }
*
* Aerospike.connect(config).then(async client => {
* let ops = [
* maps.create('map', maps.order.KEY_ORDERED, true)
* ]
* let result = await client.operate(key, ops)
* console.log(result.bins) // => { map: null }
* let record = await client.get(key)
* console.log(record.bins) // => { map: {} }
*
* await client.remove(key)
* client.close()
* })
*/
exports.create = function (bin, order, persistIndex = false, ctx) {
const op = new MapOperation(opcodes.MAP_CREATE, bin)
op.order = order
op.persistIndex = persistIndex
if (ctx === undefined) {
return op
}
return op.withContext(ctx)
}