Skip to content

Commit

Permalink
Merge branch 'main' into improve-errors
Browse files Browse the repository at this point in the history
  • Loading branch information
brunoocasali authored Jul 24, 2024
2 parents d3f490f + 01f51b4 commit 4b3dc78
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 10 deletions.
19 changes: 19 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -754,3 +754,22 @@ negative_search_1: |-
client.index('movies').search('-escape')
negative_search_2: |-
client.index('movies').search('-"escape"')
search_parameter_reference_ranking_score_threshold_1: |-
client.index('INDEX_NAME').search('badman', { rankingScoreThreshold: 0.2 })
search_parameter_reference_retrieve_vectors_1: |-
client.index('INDEX_NAME').search('kitchen utensils', {
retrieveVectors: true,
hybrid: { embedder: 'default'}
})
get_similar_post_1: |-
client.index('INDEX_NAME').searchSimilarDocuments({ id: 'TARGET_DOCUMENT_ID'})
search_parameter_guide_matching_strategy_3: |-
client.index('movies').search('white shirt', {
matchingStrategy: 'frequency'
})
search_parameter_reference_distinct_1: |-
client.index('INDEX_NAME').search('QUERY TERMS', { distinct: 'ATTRIBUTE_A' })
distinct_attribute_guide_filterable_1: |-
client.index('products').updateFilterableAttributes(['product_id', 'sku', 'url'])
distinct_attribute_guide_distinct_parameter_1: |-
client.index('products').search('white shirt', { distinct: 'sku' })
2 changes: 1 addition & 1 deletion .github/scripts/check-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ if [ "$current_tag" != "$package_json_version" ]; then
exit 1
fi

package_version_ts=$(grep "PACKAGE_VERSION =" src/package-version.ts | cut -d "=" -f 2- | tr -d " " | tr -d "'")
package_version_ts=$(grep "PACKAGE_VERSION =" src/package-version.ts | cut -d "=" -f 2- | tr -d ';' | tr -d " " | tr -d "'")
if [ "$current_tag" != "$package_version_ts" ]; then
echo "Error: the current tag does not match the version in src/package-version.ts."
echo "$current_tag vs $package_version_ts"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "meilisearch",
"version": "0.40.0",
"version": "0.41.0",
"description": "The Meilisearch JS client for Node.js and the browser.",
"keywords": [
"meilisearch",
Expand Down
12 changes: 6 additions & 6 deletions playgrounds/javascript/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5311,16 +5311,16 @@ wrappy@1:
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=

ws@^5.1.1:
version "5.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d"
integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==
version "5.2.4"
resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.4.tgz#c7bea9f1cfb5f410de50e70e82662e562113f9a7"
integrity sha512-fFCejsuC8f9kOSu9FYaOw8CdO68O3h5v0lg4p74o8JqWpwTf9tniOD+nOB78aWoVSS6WptVUmDrp/KPsMVBWFQ==
dependencies:
async-limiter "~1.0.0"

ws@^6.1.2:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
version "6.2.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.3.tgz#ccc96e4add5fd6fedbc491903075c85c5a11d9ee"
integrity sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==
dependencies:
async-limiter "~1.0.0"

Expand Down
20 changes: 20 additions & 0 deletions src/indexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {
ProximityPrecision,
Embedders,
SearchCutoffMs,
SearchSimilarDocumentsParams,
} from './types';
import { removeUndefinedFromObject } from './utils';
import { HttpRequests } from './http-requests';
Expand Down Expand Up @@ -177,6 +178,25 @@ class Index<T extends Record<string, any> = Record<string, any>> {
);
}

/**
* Search for similar documents
*
* @param params - Parameters used to search for similar documents
* @returns Promise containing the search response
*/
async searchSimilarDocuments<
D extends Record<string, any> = T,
S extends SearchParams = SearchParams,
>(params: SearchSimilarDocumentsParams): Promise<SearchResponse<D, S>> {
const url = `indexes/${this.uid}/similar`;

return await this.httpRequest.post(
url,
removeUndefinedFromObject(params),
undefined,
);
}

///
/// INDEX
///
Expand Down
2 changes: 1 addition & 1 deletion src/package-version.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const PACKAGE_VERSION = '0.40.0';
export const PACKAGE_VERSION = '0.41.0';
28 changes: 28 additions & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export type IndexesResults<T> = ResourceResults<T> & {};
export const MatchingStrategies = {
ALL: 'all',
LAST: 'last',
FREQUENCY: 'frequency',
} as const;

export type MatchingStrategies =
Expand Down Expand Up @@ -124,8 +125,11 @@ export type SearchParams = Query &
vector?: number[] | null;
showRankingScore?: boolean;
showRankingScoreDetails?: boolean;
rankingScoreThreshold?: number;
attributesToSearchOn?: string[] | null;
hybrid?: HybridSearch;
distinct?: string;
retrieveVectors?: boolean;
};

// Search parameters for searches made with the GET method
Expand All @@ -145,6 +149,9 @@ export type SearchRequestGET = Pagination &
attributesToSearchOn?: string | null;
hybridEmbedder?: string;
hybridSemanticRatio?: number;
rankingScoreThreshold?: number;
distinct?: string;
retrieveVectors?: boolean;
};

export type MultiSearchQuery = SearchParams & { indexUid: string };
Expand Down Expand Up @@ -262,6 +269,18 @@ export type FieldDistribution = {
[field: string]: number;
};

export type SearchSimilarDocumentsParams = {
id: string | number;
offset?: number;
limit?: number;
filter?: Filter;
embedder?: string;
attributesToRetrieve?: string[];
showRankingScore?: boolean;
showRankingScoreDetails?: boolean;
rankingScoreThreshold?: number;
};

/*
** Documents
*/
Expand Down Expand Up @@ -294,6 +313,7 @@ export type DocumentsQuery<T = Record<string, any>> = ResourceQuery & {
filter?: Filter;
limit?: number;
offset?: number;
retrieveVectors?: boolean;
};

export type DocumentQuery<T = Record<string, any>> = {
Expand Down Expand Up @@ -1013,6 +1033,14 @@ export const ErrorStatusCode = {

/** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_facet_search_facet_query */
INVALID_FACET_SEARCH_FACET_QUERY: 'invalid_facet_search_facet_query',

/** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_search_ranking_score_threshold */
INVALID_SEARCH_RANKING_SCORE_THRESHOLD:
'invalid_search_ranking_score_threshold',

/** @see https://www.meilisearch.com/docs/reference/errors/error_codes#invalid_similar_ranking_score_threshold */
INVALID_SIMILAR_RANKING_SCORE_THRESHOLD:
'invalid_similar_ranking_score_threshold',
};

export type ErrorStatusCode =
Expand Down
86 changes: 86 additions & 0 deletions tests/documents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,92 @@ Hint: It might not be working because maybe you're not up to date with the Meili
expect(documents.results.length).toEqual(dataset.length);
});

test(`${permission} key: Get documents with retrieveVectors to true`, async () => {
const client = await getClient(permission);
const adminKey = await getKey('Admin');

await fetch(`${HOST}/experimental-features`, {
body: JSON.stringify({ vectorStore: true }),
headers: {
Authorization: `Bearer ${adminKey}`,
'Content-Type': 'application/json',
},
method: 'PATCH',
});

const { taskUid } = await client
.index(indexPk.uid)
.addDocuments(dataset);
await client.index(indexPk.uid).waitForTask(taskUid);

// Get documents with POST
const documentsPost = await client
.index(indexPk.uid)
.getDocuments<Book>({ retrieveVectors: true });

expect(documentsPost.results.length).toEqual(dataset.length);
expect(documentsPost.results[0]).toHaveProperty('_vectors');

// Get documents with GET
const res = await fetch(
`${HOST}/indexes/${indexPk.uid}/documents?retrieveVectors=true`,
{
headers: {
Authorization: `Bearer ${adminKey}`,
'Content-Type': 'application/json',
},
method: 'GET',
},
);
const documentsGet = await res.json();

expect(documentsGet.results.length).toEqual(dataset.length);
expect(documentsGet.results[0]).toHaveProperty('_vectors');
});

test(`${permission} key: Get documents without retrieveVectors`, async () => {
const client = await getClient(permission);
const adminKey = await getKey('Admin');

await fetch(`${HOST}/experimental-features`, {
body: JSON.stringify({ vectorStore: true }),
headers: {
Authorization: `Bearer ${adminKey}`,
'Content-Type': 'application/json',
},
method: 'PATCH',
});

const { taskUid } = await client
.index(indexPk.uid)
.addDocuments(dataset);
await client.index(indexPk.uid).waitForTask(taskUid);

// Get documents with POST
const documentsPost = await client
.index(indexPk.uid)
.getDocuments<Book>();

expect(documentsPost.results.length).toEqual(dataset.length);
expect(documentsPost.results[0]).not.toHaveProperty('_vectors');

// Get documents with GET
const res = await fetch(
`${HOST}/indexes/${indexPk.uid}/documents?retrieveVectors=false`,
{
headers: {
Authorization: `Bearer ${adminKey}`,
'Content-Type': 'application/json',
},
method: 'GET',
},
);
const documentsGet = await res.json();

expect(documentsGet.results.length).toEqual(dataset.length);
expect(documentsGet.results[0]).not.toHaveProperty('_vectors');
});

test(`${permission} key: Replace documents from index that has NO primary key`, async () => {
const client = await getClient(permission);
const { taskUid: addDocTask } = await client
Expand Down
65 changes: 65 additions & 0 deletions tests/embedders.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,39 @@ const index = {
uid: 'movies_test',
};

const datasetSimilarSearch = [
{
title: 'Shazam!',
release_year: 2019,
id: '287947',
_vectors: { manual: [0.8, 0.4, -0.5] },
},
{
title: 'Captain Marvel',
release_year: 2019,
id: '299537',
_vectors: { manual: [0.6, 0.8, -0.2] },
},
{
title: 'Escape Room',
release_year: 2019,
id: '522681',
_vectors: { manual: [0.1, 0.6, 0.8] },
},
{
title: 'How to Train Your Dragon: The Hidden World',
release_year: 2019,
id: '166428',
_vectors: { manual: [0.7, 0.7, -0.4] },
},
{
title: 'All Quiet on the Western Front',
release_year: 1930,
id: '143',
_vectors: { manual: [-0.5, 0.3, 0.85] },
},
];

jest.setTimeout(100 * 1000);

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

expect(response).toEqual(null);
});

test(`${permission} key: search for similar documents`, async () => {
const client = await getClient(permission);

const newEmbedder: Embedders = {
manual: {
source: 'userProvided',
dimensions: 3,
},
};
const { taskUid: updateEmbeddersTask }: EnqueuedTask = await client
.index(index.uid)
.updateEmbedders(newEmbedder);

await client.waitForTask(updateEmbeddersTask);

const { taskUid: documentAdditionTask } = await client
.index(index.uid)
.addDocuments(datasetSimilarSearch);

await client.waitForTask(documentAdditionTask);

const response = await client.index(index.uid).searchSimilarDocuments({
id: '143',
});

expect(response).toHaveProperty('hits');
expect(response.hits.length).toEqual(4);
expect(response).toHaveProperty('offset', 0);
expect(response).toHaveProperty('limit', 20);
expect(response).toHaveProperty('estimatedTotalHits', 4);
});
},
);

Expand Down
Loading

0 comments on commit 4b3dc78

Please sign in to comment.