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

some RediSearch commands

This commit is contained in:
Leibale
2023-07-31 17:34:45 -04:00
parent 689c6a576c
commit cf38f512b8
34 changed files with 456 additions and 372 deletions

View File

@@ -182,6 +182,7 @@ Some command arguments/replies have changed to align more closely to data types
- `JSON.DEL`: `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.FORGET`: `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.[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>>`
[^enum-to-constants]: TODO [^enum-to-constants]: TODO

View File

@@ -1,11 +1,24 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { transformArguments } from './ALIASADD'; import testUtils, { GLOBAL } from '../test-utils';
import ALIASADD from './ALIASADD';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('ALIASADD', () => { describe('FT.ALIASADD', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('alias', 'index'), ALIASADD.transformArguments('alias', 'index'),
['FT.ALIASADD', 'alias', 'index'] ['FT.ALIASADD', 'alias', 'index']
); );
}); });
testUtils.testWithClient('client.ft.aliasAdd', async client => {
const [, reply] = await Promise.all([
client.ft.create('index', {
field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.aliasAdd('alias', 'index')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,5 +1,10 @@
export function transformArguments(name: string, index: string): Array<string> { import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
return ['FT.ALIASADD', name, index];
}
export declare function transformReply(): 'OK'; export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument, index: RedisArgument) {
return ['FT.ALIASADD', alias, index];
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,25 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { transformArguments } from './ALIASDEL'; import testUtils, { GLOBAL } from '../test-utils';
import ALIASDEL from './ALIASDEL';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('ALIASDEL', () => { describe('FT.ALIASDEL', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('alias', 'index'), ALIASDEL.transformArguments('alias'),
['FT.ALIASDEL', 'alias', 'index'] ['FT.ALIASDEL', 'alias']
); );
}); });
testUtils.testWithClient('client.ft.aliasAdd', async client => {
const [, , reply] = await Promise.all([
client.ft.create('index', {
field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.aliasAdd('alias', 'index'),
client.ft.aliasDel('alias')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,5 +1,10 @@
export function transformArguments(name: string, index: string): Array<string> { import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
return ['FT.ALIASDEL', name, index];
}
export declare function transformReply(): 'OK'; export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument) {
return ['FT.ALIASDEL', alias];
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -1,11 +1,24 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { transformArguments } from './ALIASUPDATE'; import testUtils, { GLOBAL } from '../test-utils';
import ALIASUPDATE from './ALIASUPDATE';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('ALIASUPDATE', () => { describe('FT.ALIASUPDATE', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('alias', 'index'), ALIASUPDATE.transformArguments('alias', 'index'),
['FT.ALIASUPDATE', 'alias', 'index'] ['FT.ALIASUPDATE', 'alias', 'index']
); );
}); });
testUtils.testWithClient('client.ft.aliasUpdate', async client => {
const [, reply] = await Promise.all([
client.ft.create('index', {
field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.aliasUpdate('alias', 'index')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,5 +1,10 @@
export function transformArguments(name: string, index: string): Array<string> { import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
return ['FT.ALIASUPDATE', name, index];
}
export declare function transformReply(): 'OK'; export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(alias: RedisArgument, index: RedisArgument) {
return ['FT.ALIASUPDATE', alias, index];
},
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
} as const satisfies Command;

View File

@@ -257,8 +257,8 @@ export interface CreateOptions {
} }
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) { transformArguments(index: RedisArgument, schema: RediSearchSchema, options?: CreateOptions) {
const args = ['FT.CREATE', index]; const args = ['FT.CREATE', index];

View File

@@ -1,33 +1,32 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { SchemaFieldTypes } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './CURSOR_DEL'; import CURSOR_DEL from './CURSOR_DEL';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('CURSOR DEL', () => { describe('FT.CURSOR DEL', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('index', 0), CURSOR_DEL.transformArguments('index', '0'),
['FT.CURSOR', 'DEL', 'index', '0'] ['FT.CURSOR', 'DEL', 'index', '0']
); );
}); });
testUtils.testWithClient('client.ft.cursorDel', async client => { testUtils.testWithClient('client.ft.cursorDel', async client => {
const [ ,, { cursor } ] = await Promise.all([ const [, , { cursor }] = await Promise.all([
client.ft.create('idx', { client.ft.create('idx', {
field: { field: {
type: SchemaFieldTypes.TEXT type: SCHEMA_FIELD_TYPE.TEXT
} }
}), }),
client.hSet('key', 'field', 'value'), client.hSet('key', 'field', 'value'),
client.ft.aggregateWithCursor('idx', '*', { client.ft.aggregateWithCursor('idx', '*', {
COUNT: 1 COUNT: 1
}) })
]); ]);
assert.equal(
assert.equal( await client.ft.cursorDel('idx', cursor),
await client.ft.cursorDel('idx', cursor), 'OK'
'OK' );
); }, GLOBAL.SERVERS.OPEN);
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,14 +1,10 @@
import { RedisCommandArgument } from '@redis/client/dist/lib/commands'; import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
export const FIRST_KEY_INDEX = 1; export default {
FIRST_KEY_INDEX: undefined,
export function transformArguments(index: RedisCommandArgument, cursorId: number) { IS_READ_ONLY: true,
return [ transformArguments(index: RedisArgument, cursorId: RedisArgument) {
'FT.CURSOR', return ['FT.CURSOR', 'DEL', index, cursorId];
'DEL', },
index, transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
cursorId.toString() } as const satisfies Command;
];
}
export declare function transformReply(): 'OK';

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DICTADD from './DICTADD'; import DICTADD from './DICTADD';
describe('DICTADD', () => { describe('FT.DICTADD', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('string', () => { it('string', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) {
return pushVariadicArguments(['FT.DICTADD', dictionary], term); return pushVariadicArguments(['FT.DICTADD', dictionary], term);
}, },

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DICTDEL from './DICTDEL'; import DICTDEL from './DICTDEL';
describe('DICTDEL', () => { describe('FT.DICTDEL', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('string', () => { it('string', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -3,7 +3,7 @@ import { pushVariadicArguments, RedisVariadicArgument } from '@redis/client/dist
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) { transformArguments(dictionary: RedisArgument, term: RedisVariadicArgument) {
return pushVariadicArguments(['FT.DICTDEL', dictionary], term); return pushVariadicArguments(['FT.DICTDEL', dictionary], term);
}, },

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DICTDUMP from './DICTDUMP'; import DICTDUMP from './DICTDUMP';
describe('DICTDUMP', () => { describe('FT.DICTDUMP', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
DICTDUMP.transformArguments('dictionary'), DICTDUMP.transformArguments('dictionary'),
@@ -11,11 +11,11 @@ describe('DICTDUMP', () => {
}); });
testUtils.testWithClient('client.ft.dictDump', async client => { testUtils.testWithClient('client.ft.dictDump', async client => {
await client.ft.dictAdd('dictionary', 'string') const [, reply] = await Promise.all([
client.ft.dictAdd('dictionary', 'string'),
client.ft.dictDump('dictionary')
]);
assert.deepEqual( assert.deepEqual(reply, ['string']);
await client.ft.dictDump('dictionary'),
['string']
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,9 +1,9 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { SchemaFieldTypes } from '.';
import DROPINDEX from './DROPINDEX'; import DROPINDEX from './DROPINDEX';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('DROPINDEX', () => { describe('FT.DROPINDEX', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
@@ -21,13 +21,13 @@ describe('DROPINDEX', () => {
}); });
testUtils.testWithClient('client.ft.dropIndex', async client => { testUtils.testWithClient('client.ft.dropIndex', async client => {
await client.ft.create('index', { const [, reply] = await Promise.all([
field: SchemaFieldTypes.TEXT client.ft.create('index', {
}); field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.dropIndex('index')
]);
assert.equal( assert.equal(reply, 'OK');
await client.ft.dropIndex('index'),
'OK'
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -6,7 +6,7 @@ export interface FtDropIndexOptions {
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(index: RedisArgument, options?: FtDropIndexOptions) { transformArguments(index: RedisArgument, options?: FtDropIndexOptions) {
const args = ['FT.DROPINDEX', index]; const args = ['FT.DROPINDEX', index];

View File

@@ -1,80 +1,80 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { SchemaFieldTypes } from '.'; import { SchemaFieldTypes } from '.';
import { transformArguments } from './SPELLCHECK'; import SPELLCHECK from './SPELLCHECK';
describe('SPELLCHECK', () => { describe('FT.SPELLCHECK', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('index', 'query'), SPELLCHECK.transformArguments('index', 'query'),
['FT.SPELLCHECK', 'index', 'query'] ['FT.SPELLCHECK', 'index', 'query']
); );
});
it('with DISTANCE', () => {
assert.deepEqual(
transformArguments('index', 'query', { DISTANCE: 2 }),
['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2']
);
});
describe('with TERMS', () => {
it('single', () => {
assert.deepEqual(
transformArguments('index', 'query', {
TERMS: {
mode: 'INCLUDE',
dictionary: 'dictionary'
}
}),
['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary']
);
});
it('multiple', () => {
assert.deepEqual(
transformArguments('index', 'query', {
TERMS: [{
mode: 'INCLUDE',
dictionary: 'include'
}, {
mode: 'EXCLUDE',
dictionary: 'exclude'
}]
}),
['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude']
);
});
});
it('with DIALECT', () => {
assert.deepEqual(
transformArguments('index', 'query', {
DIALECT: 1
}),
['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1']
);
});
}); });
testUtils.testWithClient('client.ft.spellCheck', async client => { it('with DISTANCE', () => {
await Promise.all([ assert.deepEqual(
client.ft.create('index', { SPELLCHECK.transformArguments('index', 'query', {
field: SchemaFieldTypes.TEXT DISTANCE: 2
}), }),
client.hSet('key', 'field', 'query') ['FT.SPELLCHECK', 'index', 'query', 'DISTANCE', '2']
]); );
});
describe('with TERMS', () => {
it('single', () => {
assert.deepEqual( assert.deepEqual(
await client.ft.spellCheck('index', 'quer'), SPELLCHECK.transformArguments('index', 'query', {
[{ TERMS: {
term: 'quer', mode: 'INCLUDE',
suggestions: [{ dictionary: 'dictionary'
score: 1, }
suggestion: 'query' }),
}] ['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'dictionary']
}]
); );
}, GLOBAL.SERVERS.OPEN); });
it('multiple', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
TERMS: [{
mode: 'INCLUDE',
dictionary: 'include'
}, {
mode: 'EXCLUDE',
dictionary: 'exclude'
}]
}),
['FT.SPELLCHECK', 'index', 'query', 'TERMS', 'INCLUDE', 'include', 'TERMS', 'EXCLUDE', 'exclude']
);
});
});
it('with DIALECT', () => {
assert.deepEqual(
SPELLCHECK.transformArguments('index', 'query', {
DIALECT: 1
}),
['FT.SPELLCHECK', 'index', 'query', 'DIALECT', '1']
);
});
});
testUtils.testWithClient('client.ft.spellCheck', async client => {
const [,, reply] = await Promise.all([
client.ft.create('index', {
field: SchemaFieldTypes.TEXT
}),
client.hSet('key', 'field', 'query'),
client.ft.spellCheck('index', 'quer')
]);
assert.deepEqual(reply, [{
term: 'quer',
suggestions: [{
score: 1,
suggestion: 'query'
}]
}]);
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,62 +1,69 @@
interface SpellCheckTerms { import { RedisArgument, CommandArguments, Command } from '@redis/client/dist/lib/RESP/types';
mode: 'INCLUDE' | 'EXCLUDE';
dictionary: string; export interface Terms {
mode: 'INCLUDE' | 'EXCLUDE';
dictionary: RedisArgument;
} }
interface SpellCheckOptions { export interface FtSpellCheckOptions {
DISTANCE?: number; DISTANCE?: number;
TERMS?: SpellCheckTerms | Array<SpellCheckTerms>; TERMS?: Terms | Array<Terms>;
DIALECT?: number; DIALECT?: number;
} }
export function transformArguments(index: string, query: string, options?: SpellCheckOptions): Array<string> { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument, query: RedisArgument, options?: FtSpellCheckOptions) {
const args = ['FT.SPELLCHECK', index, query]; const args = ['FT.SPELLCHECK', index, query];
if (options?.DISTANCE) { if (options?.DISTANCE) {
args.push('DISTANCE', options.DISTANCE.toString()); args.push('DISTANCE', options.DISTANCE.toString());
} }
if (options?.TERMS) { if (options?.TERMS) {
if (Array.isArray(options.TERMS)) { if (Array.isArray(options.TERMS)) {
for (const term of options.TERMS) { for (const term of options.TERMS) {
pushTerms(args, term); pushTerms(args, term);
}
} else {
pushTerms(args, options.TERMS);
} }
} else {
pushTerms(args, options.TERMS);
}
} }
if (options?.DIALECT) { if (options?.DIALECT) {
args.push('DIALECT', options.DIALECT.toString()); args.push('DIALECT', options.DIALECT.toString());
} }
return args; return args;
} },
// TODO
function pushTerms(args: Array<string>, { mode, dictionary }: SpellCheckTerms): void { // type SpellCheckRawReply = Array<[
args.push('TERMS', mode, dictionary); // _: string,
} // term: string,
// suggestions: Array<[score: string, suggestion: string]>
type SpellCheckRawReply = Array<[ // ]>;
_: string,
term: string, // type SpellCheckReply = Array<{
suggestions: Array<[score: string, suggestion: string]> // term: string,
]>; // suggestions: Array<{
// score: number,
type SpellCheckReply = Array<{ // suggestion: string
term: string, // }>
suggestions: Array<{ // }>;
score: number,
suggestion: string // export function transformReply(rawReply: SpellCheckRawReply): SpellCheckReply {
}> // return rawReply.map(([, term, suggestions]) => ({
}>; // term,
// suggestions: suggestions.map(([score, suggestion]) => ({
export function transformReply(rawReply: SpellCheckRawReply): SpellCheckReply { // score: Number(score),
return rawReply.map(([, term, suggestions]) => ({ // suggestion
term, // }))
suggestions: suggestions.map(([score, suggestion]) => ({ // }));
score: Number(score), // }
suggestion transformReply: undefined as unknown as () => any
})) } as const satisfies Command;
}));
function pushTerms(args: CommandArguments, { mode, dictionary }: Terms) {
args.push('TERMS', mode, dictionary);
} }

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import SUGADD from './SUGADD'; import SUGADD from './SUGADD';
describe('SUGADD', () => { describe('FT.SUGADD', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -7,7 +7,7 @@ export interface FtSugAddOptions {
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) { transformArguments(key: RedisArgument, string: RedisArgument, score: number, options?: FtSugAddOptions) {
const args = ['FT.SUGADD', key, string, score.toString()]; const args = ['FT.SUGADD', key, string, score.toString()];

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import SUGDEL from './SUGDEL'; import SUGDEL from './SUGDEL';
describe('SUGDEL', () => { describe('FT.SUGDEL', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
SUGDEL.transformArguments('key', 'string'), SUGDEL.transformArguments('key', 'string'),
@@ -13,7 +13,7 @@ describe('SUGDEL', () => {
testUtils.testWithClient('client.ft.sugDel', async client => { testUtils.testWithClient('client.ft.sugDel', async client => {
assert.equal( assert.equal(
await client.ft.sugDel('key', 'string'), await client.ft.sugDel('key', 'string'),
false 0
); );
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -2,7 +2,7 @@ import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, string: RedisArgument) { transformArguments(key: RedisArgument, string: RedisArgument) {
return ['FT.SUGDEL', key, string]; return ['FT.SUGDEL', key, string];
}, },

View File

@@ -1,46 +1,46 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './SUGGET'; import SUGGET from './SUGGET';
describe('SUGGET', () => { describe('FT.SUGGET', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', 'prefix'), SUGGET.transformArguments('key', 'prefix'),
['FT.SUGGET', 'key', 'prefix'] ['FT.SUGGET', 'key', 'prefix']
); );
});
it('with FUZZY', () => {
assert.deepEqual(
transformArguments('key', 'prefix', { FUZZY: true }),
['FT.SUGGET', 'key', 'prefix', 'FUZZY']
);
});
it('with MAX', () => {
assert.deepEqual(
transformArguments('key', 'prefix', { MAX: 10 }),
['FT.SUGGET', 'key', 'prefix', 'MAX', '10']
);
});
}); });
describe('client.ft.sugGet', () => { it('with FUZZY', () => {
testUtils.testWithClient('null', async client => { assert.deepEqual(
assert.equal( SUGGET.transformArguments('key', 'prefix', { FUZZY: true }),
await client.ft.sugGet('key', 'prefix'), ['FT.SUGGET', 'key', 'prefix', 'FUZZY']
null );
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('with suggestions', async client => {
await client.ft.sugAdd('key', 'string', 1);
assert.deepEqual(
await client.ft.sugGet('key', 'string'),
['string']
);
}, GLOBAL.SERVERS.OPEN);
}); });
it('with MAX', () => {
assert.deepEqual(
SUGGET.transformArguments('key', 'prefix', { MAX: 10 }),
['FT.SUGGET', 'key', 'prefix', 'MAX', '10']
);
});
});
describe('client.ft.sugGet', () => {
testUtils.testWithClient('null', async client => {
assert.equal(
await client.ft.sugGet('key', 'prefix'),
null
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('with suggestions', async client => {
const [, reply] = await Promise.all([
client.ft.sugAdd('key', 'string', 1),
client.ft.sugGet('key', 's')
]);
assert.deepEqual(reply, ['string']);
}, GLOBAL.SERVERS.OPEN);
});
}); });

View File

@@ -1,22 +1,25 @@
export const IS_READ_ONLY = true; import { ArrayReply, BlobStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
export interface SugGetOptions { export interface FtSugGetOptions {
FUZZY?: true; FUZZY?: boolean;
MAX?: number; MAX?: number;
} }
export function transformArguments(key: string, prefix: string, options?: SugGetOptions): Array<string> { export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(key: RedisArgument, prefix: RedisArgument, options?: FtSugGetOptions) {
const args = ['FT.SUGGET', key, prefix]; const args = ['FT.SUGGET', key, prefix];
if (options?.FUZZY) { if (options?.FUZZY) {
args.push('FUZZY'); args.push('FUZZY');
} }
if (options?.MAX) { if (options?.MAX !== undefined) {
args.push('MAX', options.MAX.toString()); args.push('MAX', options.MAX.toString());
} }
return args; return args;
} },
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
export declare function transformReply(): null | Array<string>; } as const satisfies Command;

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import SUGLEN from './SUGLEN'; import SUGLEN from './SUGLEN';
describe('SUGLEN', () => { describe('FT.SUGLEN', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
SUGLEN.transformArguments('key'), SUGLEN.transformArguments('key'),

View File

@@ -1,24 +1,24 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './SYNDUMP'; import SYNDUMP from './SYNDUMP';
import { SchemaFieldTypes } from '.'; import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('SYNDUMP', () => { describe('FT.SYNDUMP', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('index'), SYNDUMP.transformArguments('index'),
['FT.SYNDUMP', 'index'] ['FT.SYNDUMP', 'index']
); );
}); });
testUtils.testWithClient('client.ft.synDump', async client => { testUtils.testWithClient('client.ft.synDump', async client => {
await client.ft.create('index', { const [, reply] = await Promise.all([
field: SchemaFieldTypes.TEXT client.ft.create('index', {
}); field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.synDump('index')
]);
assert.deepEqual( assert.deepEqual(reply, []);
await client.ft.synDump('index'), }, GLOBAL.SERVERS.OPEN);
[]
);
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,5 +1,22 @@
export function transformArguments(index: string): Array<string> { import { RedisArgument, MapReply, BlobStringReply, ArrayReply, UnwrapReply, Command } from '@redis/client/dist/lib/RESP/types';
return ['FT.SYNDUMP', index];
}
export declare function transformReply(): Array<string>; export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(index: RedisArgument) {
return ['FT.SYNDUMP', index];
},
transformReply: {
2: (reply: UnwrapReply<ArrayReply<BlobStringReply | ArrayReply<BlobStringReply>>>) => {
const result: Record<string, ArrayReply<BlobStringReply>> = {};
let i = 0;
while (i < reply.length) {
const key = (reply[i++] as unknown as UnwrapReply<BlobStringReply>).toString(),
value = reply[i++] as unknown as ArrayReply<BlobStringReply>;
result[key] = value;
}
return result;
},
3: undefined as unknown as () => MapReply<BlobStringReply, ArrayReply<BlobStringReply>>
}
} as const satisfies Command;

View File

@@ -1,40 +1,42 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './SYNUPDATE'; import SYNUPDATE from './SYNUPDATE';
import { SchemaFieldTypes } from '.'; import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('SYNUPDATE', () => { describe('FT.SYNUPDATE', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('single term', () => { it('single term', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('index', 'groupId', 'term'), SYNUPDATE.transformArguments('index', 'groupId', 'term'),
['FT.SYNUPDATE', 'index', 'groupId', 'term'] ['FT.SYNUPDATE', 'index', 'groupId', 'term']
); );
});
it('multiple terms', () => {
assert.deepEqual(
transformArguments('index', 'groupId', ['1', '2']),
['FT.SYNUPDATE', 'index', 'groupId', '1', '2']
);
});
it('with SKIPINITIALSCAN', () => {
assert.deepEqual(
transformArguments('index', 'groupId', 'term', { SKIPINITIALSCAN: true }),
['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term']
);
});
}); });
testUtils.testWithClient('client.ft.synUpdate', async client => { it('multiple terms', () => {
await client.ft.create('index', { assert.deepEqual(
field: SchemaFieldTypes.TEXT SYNUPDATE.transformArguments('index', 'groupId', ['1', '2']),
}); ['FT.SYNUPDATE', 'index', 'groupId', '1', '2']
);
});
assert.equal( it('with SKIPINITIALSCAN', () => {
await client.ft.synUpdate('index', 'groupId', 'term'), assert.deepEqual(
'OK' SYNUPDATE.transformArguments('index', 'groupId', 'term', {
); SKIPINITIALSCAN: true
}, GLOBAL.SERVERS.OPEN); }),
['FT.SYNUPDATE', 'index', 'groupId', 'SKIPINITIALSCAN', 'term']
);
});
});
testUtils.testWithClient('client.ft.synUpdate', async client => {
const [, reply] = await Promise.all([
client.ft.create('index', {
field: SCHEMA_FIELD_TYPE.TEXT
}),
client.ft.synUpdate('index', 'groupId', 'term')
]);
assert.equal(reply, 'OK');
}, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,23 +1,26 @@
import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers'; import { SimpleStringReply, Command, RedisArgument } from '@redis/client/dist/lib/RESP/types';
import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
interface SynUpdateOptions { export interface FtSynUpdateOptions {
SKIPINITIALSCAN?: true; SKIPINITIALSCAN?: boolean;
} }
export function transformArguments( export default {
index: string, FIRST_KEY_INDEX: undefined,
groupId: string, IS_READ_ONLY: true,
terms: string | Array<string>, transformArguments(
options?: SynUpdateOptions index: RedisArgument,
): RedisCommandArguments { groupId: RedisArgument,
terms: RedisVariadicArgument,
options?: FtSynUpdateOptions
) {
const args = ['FT.SYNUPDATE', index, groupId]; const args = ['FT.SYNUPDATE', index, groupId];
if (options?.SKIPINITIALSCAN) { if (options?.SKIPINITIALSCAN) {
args.push('SKIPINITIALSCAN'); args.push('SKIPINITIALSCAN');
} }
return pushVariadicArguments(args, terms); return pushVariadicArguments(args, terms);
} },
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
export declare function transformReply(): 'OK'; } as const satisfies Command;

View File

@@ -1,9 +1,9 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { SchemaFieldTypes } from '.';
import TAGVALS from './TAGVALS'; import TAGVALS from './TAGVALS';
import { SCHEMA_FIELD_TYPE } from './CREATE';
describe('TAGVALS', () => { describe('FT.TAGVALS', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
TAGVALS.transformArguments('index', '@field'), TAGVALS.transformArguments('index', '@field'),
@@ -12,13 +12,13 @@ describe('TAGVALS', () => {
}); });
testUtils.testWithClient('client.ft.tagVals', async client => { testUtils.testWithClient('client.ft.tagVals', async client => {
await client.ft.create('index', { const [, reply] = await Promise.all([
field: SchemaFieldTypes.TAG client.ft.create('index', {
}); field: SCHEMA_FIELD_TYPE.TAG
}),
client.ft.tagVals('index', 'field')
]);
assert.deepEqual( assert.deepEqual(reply, []);
await client.ft.tagVals('index', 'field'),
[]
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -2,7 +2,7 @@ import { RedisArgument, ArrayReply, SetReply, BlobStringReply, Command } from '@
export default { export default {
FIRST_KEY_INDEX: undefined, FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: false, IS_READ_ONLY: true,
transformArguments(index: RedisArgument, fieldName: RedisArgument) { transformArguments(index: RedisArgument, fieldName: RedisArgument) {
return ['FT.TAGVALS', index, fieldName]; return ['FT.TAGVALS', index, fieldName];
}, },

View File

@@ -2,13 +2,13 @@ import _LIST from './_LIST';
// import ALTER from './ALTER'; // import ALTER from './ALTER';
// import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR'; // import AGGREGATE_WITHCURSOR from './AGGREGATE_WITHCURSOR';
// import AGGREGATE from './AGGREGATE'; // import AGGREGATE from './AGGREGATE';
// import ALIASADD from './ALIASADD'; import ALIASADD from './ALIASADD';
// import ALIASDEL from './ALIASDEL'; import ALIASDEL from './ALIASDEL';
// import ALIASUPDATE from './ALIASUPDATE'; import ALIASUPDATE from './ALIASUPDATE';
// import CONFIG_GET from './CONFIG_GET'; // import CONFIG_GET from './CONFIG_GET';
// import CONFIG_SET from './CONFIG_SET'; // import CONFIG_SET from './CONFIG_SET';
import CREATE from './CREATE'; import CREATE from './CREATE';
// import CURSOR_DEL from './CURSOR_DEL'; import CURSOR_DEL from './CURSOR_DEL';
// import CURSOR_READ from './CURSOR_READ'; // import CURSOR_READ from './CURSOR_READ';
import DICTADD from './DICTADD'; import DICTADD from './DICTADD';
import DICTDEL from './DICTDEL'; import DICTDEL from './DICTDEL';
@@ -20,16 +20,16 @@ import EXPLAINCLI from './EXPLAINCLI';
// import PROFILESEARCH from './PROFILE_SEARCH'; // import PROFILESEARCH from './PROFILE_SEARCH';
// import PROFILEAGGREGATE from './PROFILE_AGGREGATE'; // import PROFILEAGGREGATE from './PROFILE_AGGREGATE';
// import SEARCH from './SEARCH'; // import SEARCH from './SEARCH';
// import SPELLCHECK from './SPELLCHECK'; import SPELLCHECK from './SPELLCHECK';
import SUGADD from './SUGADD'; import SUGADD from './SUGADD';
import SUGDEL from './SUGDEL'; import SUGDEL from './SUGDEL';
// import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS'; // import SUGGET_WITHPAYLOADS from './SUGGET_WITHPAYLOADS';
// import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS'; // import SUGGET_WITHSCORES_WITHPAYLOADS from './SUGGET_WITHSCORES_WITHPAYLOADS';
// import SUGGET_WITHSCORES from './SUGGET_WITHSCORES'; // import SUGGET_WITHSCORES from './SUGGET_WITHSCORES';
// import SUGGET from './SUGGET'; import SUGGET from './SUGGET';
import SUGLEN from './SUGLEN'; import SUGLEN from './SUGLEN';
// import SYNDUMP from './SYNDUMP'; import SYNDUMP from './SYNDUMP';
// import SYNUPDATE from './SYNUPDATE'; import SYNUPDATE from './SYNUPDATE';
import TAGVALS from './TAGVALS'; import TAGVALS from './TAGVALS';
// import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; // import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers'; import { pushOptionalVariadicArgument, pushVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
@@ -45,20 +45,20 @@ export default {
// aggregateWithCursor: AGGREGATE_WITHCURSOR, // aggregateWithCursor: AGGREGATE_WITHCURSOR,
// AGGREGATE, // AGGREGATE,
// aggregate: AGGREGATE, // aggregate: AGGREGATE,
// ALIASADD, ALIASADD,
// aliasAdd: ALIASADD, aliasAdd: ALIASADD,
// ALIASDEL, ALIASDEL,
// aliasDel: ALIASDEL, aliasDel: ALIASDEL,
// ALIASUPDATE, ALIASUPDATE,
// aliasUpdate: ALIASUPDATE, aliasUpdate: ALIASUPDATE,
// CONFIG_GET, // CONFIG_GET,
// configGet: CONFIG_GET, // configGet: CONFIG_GET,
// CONFIG_SET, // CONFIG_SET,
// configSet: CONFIG_SET, // configSet: CONFIG_SET,
CREATE, CREATE,
create: CREATE, create: CREATE,
// CURSOR_DEL, CURSOR_DEL,
// cursorDel: CURSOR_DEL, cursorDel: CURSOR_DEL,
// CURSOR_READ, // CURSOR_READ,
// cursorRead: CURSOR_READ, // cursorRead: CURSOR_READ,
DICTADD, DICTADD,
@@ -81,8 +81,8 @@ export default {
// profileAggregate: PROFILEAGGREGATE, // profileAggregate: PROFILEAGGREGATE,
// SEARCH, // SEARCH,
// search: SEARCH, // search: SEARCH,
// SPELLCHECK, SPELLCHECK,
// spellCheck: SPELLCHECK, spellCheck: SPELLCHECK,
SUGADD, SUGADD,
sugAdd: SUGADD, sugAdd: SUGADD,
SUGDEL, SUGDEL,
@@ -93,14 +93,14 @@ export default {
// sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS, // sugGetWithScoresWithPayloads: SUGGET_WITHSCORES_WITHPAYLOADS,
// SUGGET_WITHSCORES, // SUGGET_WITHSCORES,
// sugGetWithScores: SUGGET_WITHSCORES, // sugGetWithScores: SUGGET_WITHSCORES,
// SUGGET, SUGGET,
// sugGet: SUGGET, sugGet: SUGGET,
SUGLEN, SUGLEN,
sugLen: SUGLEN, sugLen: SUGLEN,
// SYNDUMP, SYNDUMP,
// synDump: SYNDUMP, synDump: SYNDUMP,
// SYNUPDATE, SYNUPDATE,
// synUpdate: SYNUPDATE, synUpdate: SYNUPDATE,
TAGVALS, TAGVALS,
tagVals: TAGVALS tagVals: TAGVALS
}; };

View File

@@ -5,7 +5,8 @@
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
"files": [ "files": [
"dist/" "dist/",
"!dist/tsconfig.tsbuildinfo"
], ],
"scripts": { "scripts": {
"test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'" "test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'"