Skip to content

Commit b1865b9

Browse files
committed
implement vlinks_withscores
1 parent 2e9217b commit b1865b9

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { strict as assert } from 'node:assert';
2+
import testUtils, { GLOBAL } from '../test-utils';
3+
import { parseArgs } from './generic-transformers';
4+
import VLINKS_WITHSCORES from './VLINKS_WITHSCORES';
5+
6+
describe('VLINKS WITHSCORES', () => {
7+
it('transformArguments', () => {
8+
assert.deepEqual(parseArgs(VLINKS_WITHSCORES, 'key', 'element'), [
9+
'VLINKS',
10+
'key',
11+
'element',
12+
'WITHSCORES'
13+
]);
14+
});
15+
16+
testUtils.testAll(
17+
'vLinksWithScores',
18+
async client => {
19+
// Create a vector set with multiple elements to build HNSW graph layers
20+
await client.vAdd('key', [1.0, 2.0, 3.0], 'element1');
21+
await client.vAdd('key', [1.1, 2.1, 3.1], 'element2');
22+
await client.vAdd('key', [1.2, 2.2, 3.2], 'element3');
23+
await client.vAdd('key', [2.0, 3.0, 4.0], 'element4');
24+
25+
const result = await client.vLinksWithScores('key', 'element1');
26+
27+
assert.ok(Array.isArray(result));
28+
29+
for (const layer of result) {
30+
assert.equal(
31+
typeof layer,
32+
'object'
33+
);
34+
}
35+
36+
assert.ok(result.length >= 1, 'Should have at least layer 0');
37+
},
38+
{
39+
client: GLOBAL.SERVERS.OPEN,
40+
cluster: GLOBAL.CLUSTERS.OPEN
41+
}
42+
);
43+
44+
testUtils.testWithClient(
45+
'vLinksWithScores with RESP3',
46+
async client => {
47+
await client.vAdd('resp3-key', [1.0, 2.0, 3.0], 'element1');
48+
await client.vAdd('resp3-key', [1.1, 2.1, 3.1], 'element2');
49+
await client.vAdd('resp3-key', [1.2, 2.2, 3.2], 'element3');
50+
await client.vAdd('resp3-key', [2.0, 3.0, 4.0], 'element4');
51+
52+
const result = await client.vLinksWithScores('resp3-key', 'element1');
53+
54+
assert.ok(Array.isArray(result));
55+
56+
for (const layer of result) {
57+
assert.equal(
58+
typeof layer,
59+
'object'
60+
);
61+
}
62+
63+
assert.ok(result.length >= 1, 'Should have at least layer 0');
64+
},
65+
{
66+
...GLOBAL.SERVERS.OPEN,
67+
clientOptions: {
68+
RESP: 3
69+
}
70+
}
71+
);
72+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { BlobStringReply, Command, DoubleReply, MapReply } from '../RESP/types';
2+
import { transformDoubleReply } from './generic-transformers';
3+
import VLINKS from './VLINKS';
4+
5+
6+
function transformVLinksWithScoresReply(reply: any): Array<Record<string, DoubleReply>> {
7+
const layers: Array<Record<string, DoubleReply>> = [];
8+
9+
for (const layer of reply) {
10+
const obj: Record<string, DoubleReply> = Object.create(null);
11+
12+
// Each layer contains alternating element names and scores
13+
for (let i = 0; i < layer.length; i += 2) {
14+
const element = layer[i];
15+
const score = transformDoubleReply[2](layer[i + 1]);
16+
obj[element.toString()] = score;
17+
}
18+
19+
layers.push(obj);
20+
}
21+
22+
return layers;
23+
}
24+
25+
export default {
26+
IS_READ_ONLY: VLINKS.IS_READ_ONLY,
27+
/**
28+
* Get the connections for each layer of the HNSW graph with similarity scores
29+
* @param args - Same parameters as the VLINKS command
30+
* @see https://redis.io/commands/vlinks/
31+
*/
32+
parseCommand(...args: Parameters<typeof VLINKS.parseCommand>) {
33+
const parser = args[0];
34+
35+
VLINKS.parseCommand(...args);
36+
parser.push('WITHSCORES');
37+
},
38+
transformReply: {
39+
2: transformVLinksWithScoresReply,
40+
3: undefined as unknown as () => Array<MapReply<BlobStringReply, DoubleReply>>
41+
}
42+
} as const satisfies Command;

packages/client/lib/commands/VSIM_WITHSCORES.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {
44
Command,
55
DoubleReply,
66
MapReply,
7-
TuplesReply,
87
UnwrapReply
98
} from '../RESP/types';
109
import { transformDoubleReply } from './generic-transformers';

packages/client/lib/commands/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ import VEMB from './VEMB';
351351
import VGETATTR from './VGETATTR';
352352
import VINFO from './VINFO';
353353
import VLINKS from './VLINKS';
354+
import VLINKS_WITHSCORES from './VLINKS_WITHSCORES';
354355
import VRANDMEMBER from './VRANDMEMBER';
355356
import VREM from './VREM';
356357
import VSETATTR from './VSETATTR';
@@ -1064,6 +1065,8 @@ export default {
10641065
vInfo: VINFO,
10651066
VLINKS,
10661067
vLinks: VLINKS,
1068+
VLINKS_WITHSCORES,
1069+
vLinksWithScores: VLINKS_WITHSCORES,
10671070
VRANDMEMBER,
10681071
vRandMember: VRANDMEMBER,
10691072
VREM,

0 commit comments

Comments
 (0)