Skip to content

Commit 65bc592

Browse files
authored
feat: get similar documents (#1677)
1 parent 1716ac8 commit 65bc592

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/indexes.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import {
5353
ProximityPrecision,
5454
Embedders,
5555
SearchCutoffMs,
56+
SearchSimilarDocumentsParams,
5657
} from './types';
5758
import { removeUndefinedFromObject } from './utils';
5859
import { HttpRequests } from './http-requests';
@@ -177,6 +178,25 @@ class Index<T extends Record<string, any> = Record<string, any>> {
177178
);
178179
}
179180

181+
/**
182+
* Search for similar documents
183+
*
184+
* @param params - Parameters used to search for similar documents
185+
* @returns Promise containing the search response
186+
*/
187+
async searchSimilarDocuments<
188+
D extends Record<string, any> = T,
189+
S extends SearchParams = SearchParams,
190+
>(params: SearchSimilarDocumentsParams): Promise<SearchResponse<D, S>> {
191+
const url = `indexes/${this.uid}/similar`;
192+
193+
return await this.httpRequest.post(
194+
url,
195+
removeUndefinedFromObject(params),
196+
undefined,
197+
);
198+
}
199+
180200
///
181201
/// INDEX
182202
///

src/types/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,18 @@ export type FieldDistribution = {
267267
[field: string]: number;
268268
};
269269

270+
export type SearchSimilarDocumentsParams = {
271+
id: string | number;
272+
offset?: number;
273+
limit?: number;
274+
filter?: Filter;
275+
embedder?: string;
276+
attributesToRetrieve?: string[];
277+
showRankingScore?: boolean;
278+
showRankingScoreDetails?: boolean;
279+
rankingScoreThreshold?: number;
280+
};
281+
270282
/*
271283
** Documents
272284
*/

tests/embedders.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,39 @@ const index = {
1414
uid: 'movies_test',
1515
};
1616

17+
const datasetSimilarSearch = [
18+
{
19+
title: 'Shazam!',
20+
release_year: 2019,
21+
id: '287947',
22+
_vectors: { manual: [0.8, 0.4, -0.5] },
23+
},
24+
{
25+
title: 'Captain Marvel',
26+
release_year: 2019,
27+
id: '299537',
28+
_vectors: { manual: [0.6, 0.8, -0.2] },
29+
},
30+
{
31+
title: 'Escape Room',
32+
release_year: 2019,
33+
id: '522681',
34+
_vectors: { manual: [0.1, 0.6, 0.8] },
35+
},
36+
{
37+
title: 'How to Train Your Dragon: The Hidden World',
38+
release_year: 2019,
39+
id: '166428',
40+
_vectors: { manual: [0.7, 0.7, -0.4] },
41+
},
42+
{
43+
title: 'All Quiet on the Western Front',
44+
release_year: 1930,
45+
id: '143',
46+
_vectors: { manual: [-0.5, 0.3, 0.85] },
47+
},
48+
];
49+
1750
jest.setTimeout(100 * 1000);
1851

1952
afterAll(() => {
@@ -223,6 +256,38 @@ describe.each([{ permission: 'Master' }, { permission: 'Admin' }])(
223256

224257
expect(response).toEqual(null);
225258
});
259+
260+
test(`${permission} key: search for similar documents`, async () => {
261+
const client = await getClient(permission);
262+
263+
const newEmbedder: Embedders = {
264+
manual: {
265+
source: 'userProvided',
266+
dimensions: 3,
267+
},
268+
};
269+
const { taskUid: updateEmbeddersTask }: EnqueuedTask = await client
270+
.index(index.uid)
271+
.updateEmbedders(newEmbedder);
272+
273+
await client.waitForTask(updateEmbeddersTask);
274+
275+
const { taskUid: documentAdditionTask } = await client
276+
.index(index.uid)
277+
.addDocuments(datasetSimilarSearch);
278+
279+
await client.waitForTask(documentAdditionTask);
280+
281+
const response = await client.index(index.uid).searchSimilarDocuments({
282+
id: '143',
283+
});
284+
285+
expect(response).toHaveProperty('hits');
286+
expect(response.hits.length).toEqual(4);
287+
expect(response).toHaveProperty('offset', 0);
288+
expect(response).toHaveProperty('limit', 20);
289+
expect(response).toHaveProperty('estimatedTotalHits', 4);
290+
});
226291
},
227292
);
228293

0 commit comments

Comments
 (0)