1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-04 15:02:09 +03:00

some json and search commands

This commit is contained in:
Leibale
2023-08-01 14:29:34 -04:00
parent 2136418f1a
commit fd016ee1b2
21 changed files with 199 additions and 147 deletions

View File

@@ -178,9 +178,8 @@ Some command arguments/replies have changed to align more closely to data types
- `TOPK.QUERY`: `Array<number>` -> `Array<boolean>`
- `GRAPH.SLOWLOG`: `timestamp` has been changed from `Date` to `number`
- `JSON.ARRINDEX`: `start` and `end` arguments moved to `{ range: { start: number; end: number; }; }` [^future-proofing]
- `JSON.ARRLEN`: `path` argument moved to `{ path: string; }` [^future-proofing]
- `JSON.DEL`: `path` argument moved to `{ path: string; }` [^future-proofing]
- `JSON.FORGET`: `path` argument moved to `{ path: string; }` [^future-proofing]
- `JSON.ARRLEN`, `JSON.CLEAR`, `JSON.DEBUG MEMORY`, `JSON.DEL`, `JSON.FORGET`, `JSON.OBJKEYS`, `JSON.OBJLEN`, `JSON.STRLEN`, `JSON.TYPE`: `path` argument moved to `{ path: string; }` [^future-proofing]
- : `path` argument moved to `{ path: string; }` [^future-proofing]
- `TS.[M][REV]RANGE`: `enum TimeSeriesBucketTimestamp` -> `const TIME_SERIES_BUCKET_TIMESTAMP` [^enum-to-constants], `enum TimeSeriesReducers` -> `const TIME_SERIES_REDUCERS` [^enum-to-constants], the `ALIGN` argument has been moved into `AGGREGRATION`
- `TS.SYNUPDATE`: `Array<string | Array<string>>` -> `Record<string, Array<string>>`

View File

@@ -30,11 +30,11 @@ export interface SetOptions {
condition?: 'NX' | 'XX';
/**
* @deprecated Use `condition` 'NX' instead
* @deprecated Use `{ condition: 'NX' }` instead.
*/
NX?: boolean;
/**
* @deprecated Use `condition` 'XX' instead
* @deprecated Use `{ condition: 'XX' }` instead.
*/
XX?: boolean;

View File

@@ -4,7 +4,7 @@ import DEBUG_MEMORY from './DEBUG_MEMORY';
describe('JSON.DEBUG MEMORY', () => {
describe('transformArguments', () => {
it('without path', () => {
it('simple', () => {
assert.deepEqual(
DEBUG_MEMORY.transformArguments('key'),
['JSON.DEBUG', 'MEMORY', 'key']
@@ -13,7 +13,9 @@ describe('JSON.DEBUG MEMORY', () => {
it('with path', () => {
assert.deepEqual(
DEBUG_MEMORY.transformArguments('key', '$'),
DEBUG_MEMORY.transformArguments('key', {
path: '$'
}),
['JSON.DEBUG', 'MEMORY', 'key', '$']
);
});
@@ -21,7 +23,7 @@ describe('JSON.DEBUG MEMORY', () => {
testUtils.testWithClient('client.json.debugMemory', async client => {
assert.deepEqual(
await client.json.debugMemory('key', '$'),
await client.json.debugMemory('key'),
0
);
}, GLOBAL.SERVERS.OPEN);

View File

@@ -1,13 +1,17 @@
import { RedisArgument, NumberReply, ArrayReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface JsonDebugMemoryOptions {
path?: RedisArgument;
}
export default {
FIRST_KEY_INDEX: 2,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, path?: RedisArgument) {
transformArguments(key: RedisArgument, options?: JsonDebugMemoryOptions) {
const args = ['JSON.DEBUG', 'MEMORY', key];
if (path) {
args.push(path);
if (options?.path) {
args.push(options.path);
}
return args;

View File

@@ -4,7 +4,7 @@ import OBJKEYS from './OBJKEYS';
describe('JSON.OBJKEYS', () => {
describe('transformArguments', () => {
it('without path', () => {
it('simple', () => {
assert.deepEqual(
OBJKEYS.transformArguments('key'),
['JSON.OBJKEYS', 'key']
@@ -13,7 +13,9 @@ describe('JSON.OBJKEYS', () => {
it('with path', () => {
assert.deepEqual(
OBJKEYS.transformArguments('key', '$'),
OBJKEYS.transformArguments('key', {
path: '$'
}),
['JSON.OBJKEYS', 'key', '$']
);
});
@@ -21,7 +23,7 @@ describe('JSON.OBJKEYS', () => {
testUtils.testWithClient('client.json.objKeys', async client => {
assert.deepEqual(
await client.json.objKeys('key', '$'),
await client.json.objKeys('key'),
[null]
);
}, GLOBAL.SERVERS.OPEN);

View File

@@ -1,13 +1,17 @@
import { RedisArgument, ArrayReply, BlobStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface JsonObjKeysOptions {
path?: RedisArgument;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, path?: RedisArgument) {
transformArguments(key: RedisArgument, options?: JsonObjKeysOptions) {
const args = ['JSON.OBJKEYS', key];
if (path) {
args.push(path);
if (options?.path) {
args.push(options.path);
}
return args;

View File

@@ -4,7 +4,7 @@ import OBJLEN from './OBJLEN';
describe('JSON.OBJLEN', () => {
describe('transformArguments', () => {
it('without path', () => {
it('simple', () => {
assert.deepEqual(
OBJLEN.transformArguments('key'),
['JSON.OBJLEN', 'key']
@@ -13,7 +13,9 @@ describe('JSON.OBJLEN', () => {
it('with path', () => {
assert.deepEqual(
OBJLEN.transformArguments('key', '$'),
OBJLEN.transformArguments('key', {
path: '$'
}),
['JSON.OBJLEN', 'key', '$']
);
});
@@ -21,8 +23,8 @@ describe('JSON.OBJLEN', () => {
testUtils.testWithClient('client.json.objLen', async client => {
assert.equal(
await client.json.objLen('key', '$'),
[null]
await client.json.objLen('key'),
null
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,13 +1,17 @@
import { RedisArgument, NumberReply, ArrayReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface JsonObjLenOptions {
path?: RedisArgument;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, path?: RedisArgument) {
transformArguments(key: RedisArgument, options?: JsonObjLenOptions) {
const args = ['JSON.OBJLEN', key];
if (path) {
args.push(path);
if (options?.path) {
args.push(options.path);
}
return args;

View File

@@ -1,23 +1,34 @@
import { RedisArgument, SimpleStringReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RedisJSON, transformRedisJsonArgument } from '.';
export interface NX {
NX: true;
}
export interface XX {
XX: true;
export interface JsonSetOptions {
condition?: 'NX' | 'XX';
/**
* @deprecated Use `{ condition: 'NX' }` instead.
*/
NX?: boolean;
/**
* @deprecated Use `{ condition: 'XX' }` instead.
*/
XX?: boolean;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, path: RedisArgument, json: RedisJSON, options?: NX | XX) {
transformArguments(
key: RedisArgument,
path: RedisArgument,
json: RedisJSON,
options?: JsonSetOptions
) {
const args = ['JSON.SET', key, path, transformRedisJsonArgument(json)];
if ((<NX>options)?.NX) {
if (options?.condition) {
args.push(options?.condition);
} else if (options?.NX) {
args.push('NX');
} else if ((<XX>options)?.XX) {
} else if (options?.XX) {
args.push('XX');
}

View File

@@ -4,7 +4,7 @@ import STRLEN from './STRLEN';
describe('JSON.STRLEN', () => {
describe('transformArguments', () => {
it('without path', () => {
it('simple', () => {
assert.deepEqual(
STRLEN.transformArguments('key'),
['JSON.STRLEN', 'key']
@@ -13,7 +13,9 @@ describe('JSON.STRLEN', () => {
it('with path', () => {
assert.deepEqual(
STRLEN.transformArguments('key', '$'),
STRLEN.transformArguments('key', {
path: '$'
}),
['JSON.STRLEN', 'key', '$']
);
});
@@ -22,9 +24,9 @@ describe('JSON.STRLEN', () => {
testUtils.testWithClient('client.json.strLen', async client => {
const [, reply] = await Promise.all([
client.json.set('key', '$', ''),
client.json.strLen('key', '$')
client.json.strLen('key')
]);
assert.deepEqual(reply, [0]);
assert.deepEqual(reply, 0);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,13 +1,17 @@
import { RedisArgument, ArrayReply, NumberReply, NullReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface JsonStrLenOptions {
path?: RedisArgument;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, path?: RedisArgument) {
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, options?: JsonStrLenOptions) {
const args = ['JSON.STRLEN', key];
if (path) {
args.push(path);
if (options?.path) {
args.push(options.path);
}
return args;

View File

@@ -3,21 +3,12 @@ import testUtils, { GLOBAL } from '../test-utils';
import TOGGLE from './TOGGLE';
describe('JSON.TOGGLE', () => {
describe('transformArguments', () => {
it('without path', () => {
assert.deepEqual(
TOGGLE.transformArguments('key'),
['JSON.TOGGLE', 'key']
);
});
it('with path', () => {
it('transformArguments', () => {
assert.deepEqual(
TOGGLE.transformArguments('key', '$'),
['JSON.TOGGLE', 'key', '$']
);
});
});
testUtils.testWithClient('client.json.toggle', async client => {
const [, reply] = await Promise.all([

View File

@@ -3,14 +3,8 @@ import { RedisArgument, ArrayReply, NumberReply, NullReply, Command, } from '@re
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false,
transformArguments(key: RedisArgument, path?: RedisArgument) {
const args = ['JSON.TOGGLE', key]
if (path) {
args.push(path);
}
return args;
transformArguments(key: RedisArgument, path: RedisArgument) {
return ['JSON.TOGGLE', key, path];
},
transformReply: undefined as unknown as () => NumberReply | NullReply | ArrayReply<NumberReply | NullReply>
} as const satisfies Command;

View File

@@ -1,10 +1,10 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './TYPE';
import TYPE from './TYPE';
describe('TYPE', () => {
describe('transformArguments', () => {
it('without path', () => {
it('simple', () => {
assert.deepEqual(
transformArguments('key'),
['JSON.TYPE', 'key']
@@ -13,16 +13,20 @@ describe('TYPE', () => {
it('with path', () => {
assert.deepEqual(
transformArguments('key', '$'),
transformArguments('key', {
path: '$'
}),
['JSON.TYPE', 'key', '$']
);
});
});
// testUtils.testWithClient('client.json.type', async client => {
// assert.deepEqual(
// await client.json.type('key', '$'),
// [null]
// );
// }, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('client.json.type', async client => {
assert.deepEqual(
await client.json.type('key', {
path: '$'
}),
[null]
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,13 +1,25 @@
export const FIRST_KEY_INDEX = 1;
import { NullReply, BlobStringReply, ArrayReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
export function transformArguments(key: string, path?: string): Array<string> {
export interface JsonTypeOptions {
path?: RedisArgument;
}
export default {
FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, options?: JsonTypeOptions) {
const args = ['JSON.TYPE', key];
if (path) {
args.push(path);
if (options?.path) {
args.push(options.path);
}
return args;
}
},
transformReply: {
2: undefined as unknown as () => NullReply | BlobStringReply | ArrayReply<BlobStringReply>,
// TODO: ?!??!
3: undefined as unknown as () => any
}
} as const satisfies Command;
export declare function transformReply(): string | null | Array<string | null>;

View File

@@ -19,7 +19,7 @@ import SET from './SET';
import STRAPPEND from './STRAPPEND';
import STRLEN from './STRLEN';
import TOGGLE from './TOGGLE';
// import TYPE from './TYPE';
import TYPE from './TYPE';
export default {
ARRAPPEND,
@@ -64,8 +64,8 @@ export default {
strLen: STRLEN,
TOGGLE,
toggle: TOGGLE,
// TYPE,
// type: TYPE
TYPE,
type: TYPE
};
// https://github.com/Microsoft/TypeScript/issues/3496#issuecomment-128553540

View File

@@ -1,15 +1,15 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './ALTER';
import { SchemaFieldTypes } from '.';
import ALTER from './ALTER';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('ALTER', () => {
describe('FT.ALTER', () => {
describe('transformArguments', () => {
it('with NOINDEX', () => {
assert.deepEqual(
transformArguments('index', {
ALTER.transformArguments('index', {
field: {
type: SchemaFieldTypes.TEXT,
type: SCHEMA_FIELD_TYPE.TEXT,
NOINDEX: true,
SORTABLE: 'UNF',
AS: 'text'
@@ -21,17 +21,15 @@ describe('ALTER', () => {
});
testUtils.testWithClient('client.ft.create', async client => {
await Promise.all([
const [, reply] = await Promise.all([
client.ft.create('index', {
title: SchemaFieldTypes.TEXT
title: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.alter('index', {
body: SCHEMA_FIELD_TYPE.TEXT
})
]);
assert.equal(
await client.ft.alter('index', {
body: SchemaFieldTypes.TEXT
}),
'OK'
);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,10 +1,13 @@
import { RediSearchSchema, pushSchema } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { RediSearchSchema, pushSchema } from './CREATE';
export function transformArguments(index: string, schema: RediSearchSchema): Array<string> {
export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, schema: RediSearchSchema) {
const args = ['FT.ALTER', index, 'SCHEMA', 'ADD'];
pushSchema(args, schema);
return args;
}
export declare function transformReply(): 'OK';
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,12 +1,19 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './CONFIG_SET';
import CONFIG_SET from './CONFIG_SET';
describe('CONFIG SET', () => {
describe('FT.CONFIG SET', () => {
it('transformArguments', () => {
assert.deepEqual(
transformArguments('TIMEOUT', '500'),
CONFIG_SET.transformArguments('TIMEOUT', '500'),
['FT.CONFIG', 'SET', 'TIMEOUT', '500']
);
});
testUtils.testWithClient('client.ft.configSet', async client => {
assert.deepEqual(
await client.ft.configSet('TIMEOUT', '500'),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});

View File

@@ -1,5 +1,14 @@
export function transformArguments(option: string, value: string): Array<string> {
return ['FT.CONFIG', 'SET', option, value];
}
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export declare function transformReply(): 'OK';
// using `string & {}` to avoid TS widening the type to `string`
// TODO
type FtConfigProperties = 'a' | 'b' | (string & {}) | Buffer;
export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(property: FtConfigProperties, value: RedisArgument) {
return ['FT.CONFIG', 'SET', property, value];
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,12 +1,12 @@
import _LIST from './_LIST';
// import ALTER from './ALTER';
import ALTER from './ALTER';
// import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR';
// import AGGREGATE from './AGGREGATE';
import ALIASADD from './ALIASADD';
import ALIASDEL from './ALIASDEL';
import ALIASUPDATE from './ALIASUPDATE';
// import CONFIG_GET from './CONFIG_GET';
// import CONFIG_SET from './CONFIG_SET';
import CONFIG_SET from './CONFIG_SET';
import CREATE from './CREATE';
import CURSOR_DEL from './CURSOR_DEL';
// import CURSOR_READ from './CURSOR_READ';
@@ -39,8 +39,8 @@ import { CommandArguments } from '@redis/client/dist/lib/RESP/types';
export default {
_LIST,
_list: _LIST,
// ALTER,
// alter: ALTER,
ALTER,
alter: ALTER,
// AGGREGATE_WITHCURSOR,
// aggregateWithCursor: AGGREGATE_WITHCURSOR,
// AGGREGATE,
@@ -53,8 +53,8 @@ export default {
aliasUpdate: ALIASUPDATE,
// CONFIG_GET,
// configGet: CONFIG_GET,
// CONFIG_SET,
// configSet: CONFIG_SET,
CONFIG_SET,
configSet: CONFIG_SET,
CREATE,
create: CREATE,
CURSOR_DEL,