aerospike
Version:
Aerospike Client Library
947 lines (814 loc) • 42.3 kB
text/typescript
// *****************************************************************************
// 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.
// *****************************************************************************
'use strict'
/* eslint-env mocha */
/* global expect */
import { exp as expModule, operations, lists as listsModule, Client as Cli, Key, RemovePolicyOptions, AerospikeExp, AerospikeRecord, cdt, AerospikeBins, AerospikeError} from '../lib/aerospike.js';
import * as Aerospike from '../lib/aerospike.js';
import { expect } from 'chai';
import * as helper from './test_helper.ts';
const exp: typeof expModule = Aerospike.exp
const op: typeof operations = Aerospike.operations
const lists: typeof listsModule = Aerospike.lists
const Context: typeof cdt.Context = Aerospike.cdt.Context
const keygen: any = helper.keygen
const tempBin: string = 'ExpVar'
const FILTERED_OUT: number = Aerospike.status.FILTERED_OUT
describe('Aerospike.exp_operations', function () {
helper.skipUnlessVersion('>= 5.0.0', this)
const client: Cli = helper.client
const key: Key = keygen.string(helper.namespace, helper.set, { prefix: 'test/exp' })()
async function createRecord (bins: any, meta = null) {
await client.put(key, bins, meta)
return key
}
async function testNoMatch (key: any, filterExpression: any) {
const rejectPolicy: RemovePolicyOptions = { filterExpression }
let operationSuccessful: boolean = false
try {
await client.remove(key, rejectPolicy)
operationSuccessful = true
} catch (error: any) {
expect(error.code).to.eq(FILTERED_OUT, `Received unexpected error code with message "${error.message}"`)
}
if (operationSuccessful) {
expect.fail('Test no-match: Operation should have not have been executed due to failed expression match')
}
}
async function testMatch (key: any, filterExpression: any) {
const passPolicy: RemovePolicyOptions = { filterExpression }
await client.remove(key, passPolicy)
}
it('builds up a filter expression value', function () {
const filter: AerospikeExp = exp.eq(exp.binInt('intVal'), exp.int(42))
expect(filter).to.be.an('array')
})
describe('list expressions', function () {
describe('list size', function () {
it('matches the size of a list value', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
await testNoMatch(key, exp.eq(exp.lists.size(exp.binList('tags')), exp.int(5)))
await testMatch(key, exp.eq(exp.lists.size(exp.binList('tags')), exp.int(3)))
})
})
describe('list size with context', function () {
it('matches the size of a list value within a nested context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
await testNoMatch(key, exp.eq(exp.lists.size(exp.binList('tags'), context), exp.int(5)))
await testMatch(key, exp.eq(exp.lists.size(exp.binList('tags'), context), exp.int(4)))
})
})
describe('inList', function () {
helper.skipUnlessVersion('>= 8.1.2', this)
beforeEach(async () => {
await createRecord({ color: 'blue', qty: 5, rgb: [1, 5, 255] })
})
afterEach(async () => {
// When running the inList tests in CI/CD, sometimes the after hook will trigger a record not found error
// This is a workaround to prevent the test from failing
try {
await client.remove(key)
}
catch (error) {
const ignore_error = error instanceof AerospikeError && error.code == Aerospike.status.ERR_RECORD_NOT_FOUND
if (ignore_error == false) {
throw error;
}
}
})
it('is true when bin string is contained in a literal list (exp.inList case 1)', async function () {
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.inList(exp.binStr('color'), exp.list(['red', 'blue', 'green'])),
0)
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins![tempBin]).to.equal(true)
})
it('is false when a string literal is not in the list (exp.inList case 2)', async function () {
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.inList(exp.str('yellow'), exp.list(['red', 'blue', 'green'])),
0)
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins![tempBin]).to.equal(false)
})
it('is true when bin int is contained in a literal list (exp.inList case 3)', async function () {
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.inList(exp.binInt('qty'), exp.list([1, 5, 10])),
0)
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins![tempBin]).to.equal(true)
})
it('is true when bin int is contained in a integer bin list (exp.inList case 4)', async function () {
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.inList(exp.binInt('qty'), exp.binList('rgb')),
0)
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins![tempBin]).to.equal(true)
})
})
describe('clear', function () {
it('removes all items in a map', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.clear(
exp.binList('tags')),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: [] })
})
it('selects item identified by index inside nested map', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.clear(
exp.binList('tags'),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', []] })
})
})
describe('removeByValue', function () {
it('removes list item by value', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValue(
exp.binList('tags'),
exp.str('green')),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'yellow'] })
})
it('removes list item by value in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValue(
exp.binList('tags'),
exp.str('white'),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['orange', 'pink', 'black']] })
})
})
describe('removeByValueList', function () {
it('removes list item by value list', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValueList(
exp.binList('tags'),
exp.list(['green', 'yellow'])),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue'] })
})
it('removes list item by value list in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValueList(
exp.binList('tags'),
exp.list(['orange', 'white']),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['pink', 'black']] })
})
})
describe('removeByValueRange', function () {
it('removes list item by value range', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValueRange(
exp.binList('tags'),
exp.str('green'),
exp.str('blue')),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['green', 'yellow'] })
})
it('removes list item by value range in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByValueRange(
exp.binList('tags'),
exp.str('pink'),
exp.str('black'),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['pink', 'white']] })
})
})
describe('removeByRelRankRangeToEnd', function () {
it('removes list item by value relative rank range to end', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRelRankRangeToEnd(
exp.binList('tags'),
exp.int(1),
exp.str('blue')),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue'] })
})
it('removes list item by value relative rank range to end in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRelRankRangeToEnd(
exp.binList('tags'),
exp.int(1),
exp.str('orange'),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['orange', 'black']] })
})
})
describe('removeByRelRankRange', function () {
it('removes list item by value relative rank range', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRelRankRange(
exp.binList('tags'),
exp.int(1),
exp.int(-1),
exp.str('green')),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['green', 'yellow'] })
})
it('removes list item by value relative rank range in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRelRankRange(
exp.binList('tags'),
exp.int(1),
exp.int(-1),
exp.str('pink'),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['pink', 'white', 'black']] })
})
})
describe('removeByIndex', function () {
it('removes a list item by index', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndex(
exp.binList('tags'),
exp.int(1)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'yellow'] })
})
it('removes a list item by index in a cdt context in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndex(
exp.binList('tags'),
exp.int(1),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['orange', 'white', 'black']] })
})
})
describe('removeByIndexRangeToEnd', function () {
it('removes a list item by index range to end', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndexRangeToEnd(
exp.binList('tags'),
exp.int(1)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue'] })
})
it('removes a list item by index range to end in a cdt context in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndexRangeToEnd(
exp.binList('tags'),
exp.int(1),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['orange']] })
})
})
describe('removeByIndexRange', function () {
it('removes a list item by index range', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndexRange(
exp.binList('tags'),
exp.int(2),
exp.int(0)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['yellow'] })
})
it('removes a list item by index range in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByIndexRange(
exp.binList('tags'),
exp.int(2),
exp.int(0),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['white', 'black']] })
})
})
describe('removeByRank', function () {
it('removes a list item by rank', async function () {
const key: Key = await createRecord({ tags: ['yellow', 'green', 'blue'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRank(
exp.binList('tags'),
exp.int(2)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['green', 'blue'] })
})
it('removes a list item by rank in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRank(
exp.binList('tags'),
exp.int(2),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['orange', 'white', 'black']] })
})
})
describe('removeByRankRangeToEnd', function () {
it('removes a list item by rank range to end', async function () {
const key: Key = await createRecord({ tags: ['yellow', 'green', 'blue'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRankRangeToEnd(
exp.binList('tags'),
exp.int(1)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue'] })
})
it('removes a list item by rank range to end in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRankRangeToEnd(
exp.binList('tags'),
exp.int(1),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['black']] })
})
})
describe('removeByRankRange', function () {
it('removes a list item by rank range', async function () {
const key: Key = await createRecord({ tags: ['yellow', 'green', 'blue'] })
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRankRange(
exp.binList('tags'),
exp.int(2),
exp.int(0)),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['yellow'] })
})
it('removes a list item by rank range in a cdt context', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', ['orange', 'pink', 'white', 'black']] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.write('tags',
exp.lists.removeByRankRange(
exp.binList('tags'),
exp.int(2),
exp.int(0),
context),
0),
op.read('tags')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
expect(result.bins).to.eql({ tags: ['blue', 'green', ['pink', 'white']] })
})
})
describe('getByValue', function () {
it('matches the count of the matched list values', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow', 'green'] })
await testNoMatch(key, exp.eq(exp.lists.getByValue(exp.binList('tags'), exp.str('green'), lists.returnType.COUNT), exp.int(1)))
await testMatch(key, exp.eq(exp.lists.getByValue(exp.binList('tags'), exp.str('green'), lists.returnType.COUNT), exp.int(2)))
})
})
describe('getByValue with context', function () {
it('matches the count of the matched list values', async function () {
const key: Key = await createRecord({ tags: ['blue', 'green', 'yellow', 'green', ['orange', 'pink', 'white', 'black', 'pink']] })
const context: cdt.Context = new Context().addListIndex(4)
await testNoMatch(key, exp.eq(exp.lists.getByValue(exp.binList('tags'), exp.str('pink'), lists.returnType.COUNT, context), exp.int(1)))
await testMatch(key, exp.eq(exp.lists.getByValue(exp.binList('tags'), exp.str('pink'), lists.returnType.COUNT, context), exp.int(2)))
})
})
describe('getByValueRange', function () {
it('matches the count of the matched range of list values', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 48] })
await testNoMatch(key, exp.eq(exp.lists.getByValueRange(exp.binList('values'), exp.int(25), exp.int(50), lists.returnType.COUNT), exp.int(1)))
await testMatch(key, exp.eq(exp.lists.getByValueRange(exp.binList('values'), exp.int(25), exp.int(50), lists.returnType.COUNT), exp.int(3)))
})
})
describe('getByValueRange with context', function () {
it('matches the count of the matched range of list values', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 48, [1, 92, 94, 96]] })
const context: cdt.Context = new Context().addListIndex(7)
await testNoMatch(key, exp.eq(exp.lists.getByValueRange(exp.binList('values'), exp.int(90), exp.int(99), lists.returnType.COUNT, context), exp.int(1)))
await testMatch(key, exp.eq(exp.lists.getByValueRange(exp.binList('values'), exp.int(90), exp.int(99), lists.returnType.COUNT, context), exp.int(3)))
})
})
describe('getByValueList', function () {
it('matches the count of the matched values', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 88, 48, 16] })
await testNoMatch(key, exp.eq(exp.lists.getByValueList(exp.binList('values'), exp.list([88, 94]), lists.returnType.COUNT), exp.int(2)))
await testMatch(key, exp.eq(exp.lists.getByValueList(exp.binList('values'), exp.list([88, 94]), lists.returnType.COUNT), exp.int(3)))
})
})
describe('getByValueList with context', function () {
it('matches the count of the matched values', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 88, 48, 16, [0, 1, 2, 73, 74, 73, 74]] })
const context: cdt.Context = new Context().addListIndex(9)
await testNoMatch(key, exp.eq(exp.lists.getByValueList(exp.binList('values'), exp.list([73, 74]), lists.returnType.COUNT, context), exp.int(2)))
await testMatch(key, exp.eq(exp.lists.getByValueList(exp.binList('values'), exp.list([73, 74]), lists.returnType.COUNT, context), exp.int(4)))
})
})
describe('getByRelRankRangeToEnd', function () {
it('selects list items nearest to value and greater by relative rank', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 88, 48, 16] })
await testNoMatch(key, exp.eq(exp.lists.getByRelRankRangeToEnd(exp.binList('values'), exp.int(38), exp.int(1), lists.returnType.VALUE), exp.list([38, 48, 53, 88, 88, 94])))
await testMatch(key, exp.eq(exp.lists.getByRelRankRangeToEnd(exp.binList('values'), exp.int(38), exp.int(1), lists.returnType.VALUE), exp.list([48, 53, 88, 88, 94])))
})
})
describe('getByRelRankRangeToEnd with context', function () {
it('selects list items nearest to value and greater by relative rank', async function () {
const key: Key = await createRecord({ values: [53, 16, [2, 12, 14, 17]] })
const context: cdt.Context = new Context().addListIndex(2)
await testNoMatch(key, exp.eq(exp.lists.getByRelRankRangeToEnd(exp.binList('values'), exp.int(12), exp.int(1), lists.returnType.VALUE, context), exp.list([16, 53])))
await testMatch(key, exp.eq(exp.lists.getByRelRankRangeToEnd(exp.binList('values'), exp.int(12), exp.int(1), lists.returnType.VALUE, context), exp.list([14, 17])))
})
})
describe('getByRelRankRange', function () {
it('selects list items nearest to value and greater by relative rank with a count limit', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, 38, 25, 88, 88, 48, 16] })
await testNoMatch(key, exp.eq(exp.lists.getByRelRankRange(exp.binList('values'), exp.int(38), exp.int(1), exp.int(3), lists.returnType.VALUE), exp.list([38, 48, 53])))
await testMatch(key, exp.eq(exp.lists.getByRelRankRange(exp.binList('values'), exp.int(38), exp.int(1), exp.int(3), lists.returnType.VALUE), exp.list([48, 53, 88])))
})
})
describe('getByRelRankRange with context', function () {
it('selects list items nearest to value and greater by relative rank with a count limit', async function () {
const key: Key = await createRecord({ values: [53, 16, 94, [30, 40, 45, 20]] })
const context: cdt.Context = new Context().addListIndex(3)
await testNoMatch(key, exp.eq(exp.lists.getByRelRankRange(exp.binList('values'), exp.int(30), exp.int(1), exp.int(3), lists.returnType.VALUE, context), exp.list([94])))
await testMatch(key, exp.eq(exp.lists.getByRelRankRange(exp.binList('values'), exp.int(30), exp.int(1), exp.int(3), lists.returnType.VALUE, context), exp.list([40, 45])))
})
})
describe('getByIndex', function () {
it('selects item identified by index', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo'] })
await testNoMatch(key, exp.eq(exp.lists.getByIndex(exp.binList('values'), exp.int(2), exp.type.STR, lists.returnType.VALUE), exp.str('Hamburg')))
await testMatch(key, exp.eq(exp.lists.getByIndex(exp.binList('values'), exp.int(2), exp.type.STR, lists.returnType.VALUE), exp.str('San Francisco')))
})
})
describe('getByIndex with context', function () {
it('selects item identified by index within nested context', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo', ['Firth', 'Hickman', 'Palmyra']] })
const context: cdt.Context = new Context().addListIndex(4)
await testNoMatch(key, exp.eq(exp.lists.getByIndex(exp.binList('values'), exp.int(2), exp.type.STR, lists.returnType.VALUE, context), exp.str('San Francisco')))
await testMatch(key, exp.eq(exp.lists.getByIndex(exp.binList('values'), exp.int(2), exp.type.STR, lists.returnType.VALUE, context), exp.str('Palmyra')))
})
})
describe('getByIndexRangeToEnd', function () {
it('selects list items starting at specified index to the end of the list', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo'] })
await testNoMatch(key, exp.eq(exp.lists.getByIndexRangeToEnd(exp.binList('values'), exp.int(2), lists.returnType.VALUE), exp.list(['Hamburg', 'San Francisco'])))
await testMatch(key, exp.eq(exp.lists.getByIndexRangeToEnd(exp.binList('values'), exp.int(2), lists.returnType.VALUE), exp.list(['San Francisco', 'Tokyo'])))
})
})
describe('getByIndexRangeToEnd with context', function () {
it('selects list items starting at specified index to the end of the list', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo', ['Firth', 'Hickman', 'Palmyra']] })
const context: cdt.Context = new Context().addListIndex(4)
await testNoMatch(key, exp.eq(exp.lists.getByIndexRangeToEnd(exp.binList('values'), exp.int(1), lists.returnType.VALUE, context), exp.list(['Hamburg', 'San Francisco', 'Tokyo'])))
await testMatch(key, exp.eq(exp.lists.getByIndexRangeToEnd(exp.binList('values'), exp.int(1), lists.returnType.VALUE, context), exp.list(['Hickman', 'Palmyra'])))
})
})
describe('getByIndexRange', function () {
it('selects "count" list items starting at specified index', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo'] })
await testNoMatch(key, exp.eq(exp.lists.getByIndexRange(exp.binList('values'), exp.int(2), exp.int(1), lists.returnType.VALUE), exp.list(['Hamburg'])))
await testMatch(key, exp.eq(exp.lists.getByIndexRange(exp.binList('values'), exp.int(2), exp.int(1), lists.returnType.VALUE), exp.list(['San Francisco'])))
})
})
describe('getByIndexRange with context', function () {
it('selects "count" list items starting at specified index', async function () {
const key: Key = await createRecord({ values: ['Singapore', 'Hamburg', 'San Francisco', 'Tokyo', ['Firth', 'Hickman', 'Palmyra']] })
const context: cdt.Context = new Context().addListIndex(4)
await testNoMatch(key, exp.eq(exp.lists.getByIndexRange(exp.binList('values'), exp.int(0), exp.int(2), lists.returnType.VALUE, context), exp.list(['Singapore', 'Hamburg'])))
await testMatch(key, exp.eq(exp.lists.getByIndexRange(exp.binList('values'), exp.int(0), exp.int(2), lists.returnType.VALUE, context), exp.list(['Firth', 'Hickman'])))
})
})
describe('getByRank', function () {
it('selects list item identified by rank', async function () {
const key: Key = await createRecord({ values: [83, 39, 49, 20, 42, 41, 98] })
await testNoMatch(key, exp.eq(exp.lists.getByRank(exp.binList('values'), exp.int(2), exp.type.INT, lists.returnType.VALUE), exp.int(42)))
await testMatch(key, exp.eq(exp.lists.getByRank(exp.binList('values'), exp.int(2), exp.type.INT, lists.returnType.VALUE), exp.int(41)))
})
})
describe('getByRank with context', function () {
it('selects list item identified by rank', async function () {
const key: Key = await createRecord({ values: [83, [0, 4, 2, 8], 40] })
const context: cdt.Context = new Context().addListIndex(1)
await testNoMatch(key, exp.eq(exp.lists.getByRank(exp.binList('values'), exp.int(2), exp.type.INT, lists.returnType.VALUE, context), exp.int(40)))
await testMatch(key, exp.eq(exp.lists.getByRank(exp.binList('values'), exp.int(2), exp.type.INT, lists.returnType.VALUE, context), exp.int(4)))
})
})
describe('getByRankRangeToEnd', function () {
it('selects list items starting at specified rank to the last ranked item', async function () {
const key: Key = await createRecord({ values: [83, 39, 49, 20, 42, 41, 98] })
await testNoMatch(key, exp.eq(exp.lists.getByRankRangeToEnd(exp.binList('values'), exp.int(2), lists.returnType.VALUE), exp.list([39, 41, 42, 49, 83, 98])))
await testMatch(key, exp.eq(exp.lists.getByRankRangeToEnd(exp.binList('values'), exp.int(2), lists.returnType.VALUE), exp.list([41, 42, 49, 83, 98])))
})
})
describe('getByRankRangeToEnd with context', function () {
it('selects list items starting at specified rank to the last ranked item', async function () {
const key: Key = await createRecord({ values: [83, [0, 4, 2, 8]] })
const context: cdt.Context = new Context().addListIndex(1)
await testNoMatch(key, exp.eq(exp.lists.getByRankRangeToEnd(exp.binList('values'), exp.int(1), lists.returnType.VALUE, context), exp.list([0, 2, 4, 8])))
await testMatch(key, exp.eq(exp.lists.getByRankRangeToEnd(exp.binList('values'), exp.int(1), lists.returnType.VALUE, context), exp.list([2, 4, 8])))
})
})
describe('getByRankRange', function () {
it('selects "count" list items starting at specified rank', async function () {
const key: Key = await createRecord({ values: [83, 39, 49, 20, 42, 41, 98] })
await testNoMatch(key, exp.eq(exp.lists.getByRankRange(exp.binList('values'), exp.int(2), exp.int(2), lists.returnType.VALUE), exp.list([39, 41, 42])))
await testMatch(key, exp.eq(exp.lists.getByRankRange(exp.binList('values'), exp.int(2), exp.int(2), lists.returnType.VALUE), exp.list([42, 41])))
})
})
describe('getByRankRange with context', function () {
it('selects "count" list items starting at specified rank', async function () {
const key: Key = await createRecord({ values: [83, [0, 4, 2, 8]] })
const context: cdt.Context = new Context().addListIndex(1)
await testNoMatch(key, exp.eq(exp.lists.getByRankRange(exp.binList('values'), exp.int(1), exp.int(4), lists.returnType.VALUE, context), exp.list([83, [0, 4, 2, 8]])))
await testMatch(key, exp.eq(exp.lists.getByRankRange(exp.binList('values'), exp.int(1), exp.int(4), lists.returnType.VALUE, context), exp.list([2, 4, 8])))
})
})
describe('list bin append expression', function () {
it('appends integer value to list', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5], intVal: 6 })
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.append(exp.binList('list'), exp.binInt('intVal')),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5])
expect(bins.ExpVar).to.eql([2, 3, 4, 5, 6])
})
it('appends integer value to a list within a nested context', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5, [4]], intVal: 6 })
const context: cdt.Context = new Context().addListIndex(4)
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.append(exp.binList('list'), exp.binInt('intVal'), null, context),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5, [4]])
expect(bins.ExpVar).to.eql([2, 3, 4, 5, [4, 6]])
})
})
describe('list bin appendItems expression', function () {
it('appends list to itself', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5] })
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.appendItems(exp.binList('list'), exp.binList('list')),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5])
expect(bins.ExpVar).to.eql([2, 3, 4, 5, 2, 3, 4, 5])
})
it('appends list to a list within a nested context', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5, [80, 90, 100]] })
const context: cdt.Context = new Context().addListIndex(4)
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.appendItems(exp.binList('list'), exp.binList('list'), null, context),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5, [80, 90, 100]])
expect(bins.ExpVar).to.eql([2, 3, 4, 5, [80, 90, 100, 2, 3, 4, 5, [80, 90, 100]]])
})
})
})
describe('list bin insert expression', function () {
it('inserts value at specified index', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5], intVal: 6 })
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.insert(exp.binList('list'), exp.binInt('intVal'), exp.int(2)),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5])
expect(bins.ExpVar).to.eql([2, 3, 6, 4, 5])
})
it('inserts value at specified index within a nested context', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5, [4, 1, 9]], intVal: 7 })
const context: cdt.Context = new Context().addListIndex(4)
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.insert(exp.binList('list'), exp.binInt('intVal'), exp.int(2), null, context),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5, [4, 1, 9]])
expect(bins.ExpVar).to.eql([2, 3, 4, 5, [4, 1, 7, 9]])
})
})
describe('list bin insertItems expression', function () {
it('inserts values at specified index', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5] })
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.insertItems(exp.binList('list'), exp.binList('list'), exp.int(1)),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, 4, 5])
expect(bins.ExpVar).to.eql([2, 2, 3, 4, 5, 3, 4, 5])
})
it('inserts values at specified index within a nested context', async function () {
const key: Key = await createRecord({ list: [2, 3, [9, 9]] })
const context: cdt.Context = new Context().addListIndex(2)
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.insertItems(exp.binList('list'), exp.binList('list'), exp.int(1), null, context),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.list).to.eql([2, 3, [9, 9]])
expect(bins.ExpVar).to.eql([2, 3, [9, 2, 3, [9, 9], 9]])
})
})
describe('list bin sort expression', function () {
it('sorts specified list', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5] })
const ops: operations.Operation[] = [
exp.operations.write('list',
exp.lists.insertItems(exp.binList('list'), exp.binList('list'), exp.int(1)),
0),
exp.operations.read(tempBin,
exp.lists.sort(exp.binList('list'), 1),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.ExpVar).to.eql([5, 5, 4, 4, 3, 3, 2, 2])
expect(bins.list).to.eql([2, 2, 3, 4, 5, 3, 4, 5])
})
it('sorts specified nested list', async function () {
const key: Key = await createRecord({ list: [2, 3, 4, 5, [9, 100]] })
const context: cdt.Context = new Context().addListIndex(4)
const ops: operations.Operation[] = [
exp.operations.read(tempBin,
exp.lists.sort(exp.binList('list'), 1, context),
0),
op.read('list')
]
const result: AerospikeRecord = await client.operate(key, ops, {})
const bins: AerospikeBins = result.bins
expect(bins.ExpVar).to.eql([2, 3, 4, 5, [100, 9]])
expect(bins.list).to.eql([2, 3, 4, 5, [9, 100]])
})
})
})