Skip to content

Commit 4f60551

Browse files
meili-bors[bot]meili-botbidoubiwa
authored
Merge #1456
1456: Changes related to the next Meilisearch release (v1.1.0) r=bidoubiwa a=meili-bot Related to this issue: meilisearch/integration-guides#251 This PR: - gathers the changes related to the next Meilisearch release (v1.1.0) so that this package is ready when the official release is out. - should pass the tests against the [latest pre-release of Meilisearch](https://github.com/meilisearch/meilisearch/releases). - might eventually contain test failures until the Meilisearch v1.1.0 is out. ⚠️ This PR should NOT be merged until the next release of Meilisearch (v1.1.0) is out. _This PR is auto-generated for the [pre-release week](https://github.com/meilisearch/integration-guides/blob/main/resources/pre-release-week.md) purpose._ Co-authored-by: meili-bot <[email protected]> Co-authored-by: cvermand <[email protected]>
2 parents 49b51b4 + 1ba51a6 commit 4f60551

File tree

4 files changed

+129
-1
lines changed

4 files changed

+129
-1
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,16 @@ client.index<T>('xxx').search(query: string, options: SearchParams = {}, config?
402402
client.index<T>('xxx').searchGet(query: string, options: SearchParams = {}, config?: Partial<Request>): Promise<SearchResponse<T>>
403403
```
404404

405+
### Multi Search
406+
407+
#### [Make multiple search requests](https://docs.meilisearch.com/reference/api/multi-search.html)
408+
409+
```ts
410+
client.multiSearch(queries?: MultiSearchParams, config?: Partial<Request>): Promise<Promise<MultiSearchResponse<T>>>
411+
```
412+
413+
`multiSearch` uses the `POST` method when performing its request to Meilisearch.
414+
405415
### Documents <!-- omit in toc -->
406416

407417
#### [Add or replace multiple documents](https://docs.meilisearch.com/reference/api/documents.html#add-or-replace-documents)

src/clients/client.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import {
3232
SwapIndexesParams,
3333
CancelTasksQuery,
3434
DeleteTasksQuery,
35+
MultiSearchParams,
36+
MultiSearchResponse,
3537
} from '../types'
3638
import { HttpRequests } from '../http-requests'
3739
import { TaskClient, Task } from '../task'
@@ -189,6 +191,40 @@ class Client {
189191
return await this.httpRequest.post(url, params)
190192
}
191193

194+
///
195+
/// Multi Search
196+
///
197+
198+
/**
199+
* Perform multiple search queries.
200+
*
201+
* It is possible to make multiple search queries on the same index or on
202+
* different ones
203+
*
204+
* @example
205+
*
206+
* ```ts
207+
* client.multiSearch({
208+
* queries: [
209+
* { indexUid: 'movies', q: 'wonder' },
210+
* { indexUid: 'books', q: 'flower' },
211+
* ],
212+
* })
213+
* ```
214+
*
215+
* @param queries - Search queries
216+
* @param config - Additional request configuration options
217+
* @returns Promise containing the search responses
218+
*/
219+
async multiSearch<T extends Record<string, any> = Record<string, any>>(
220+
queries?: MultiSearchParams,
221+
config?: Partial<Request>
222+
): Promise<MultiSearchResponse<T>> {
223+
const url = `/multi-search`
224+
225+
return await this.httpRequest.post(url, queries, undefined, config)
226+
}
227+
192228
///
193229
/// TASKS
194230
///

src/types/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ export type SearchRequestGET = Pagination &
107107
showMatchesPosition?: boolean
108108
}
109109

110+
export type MultiSearchQuery = SearchParams & { indexUid: string }
111+
112+
export type MultiSearchParams = {
113+
queries: MultiSearchQuery[]
114+
}
115+
110116
export type CategoriesDistribution = {
111117
[category: string]: number
112118
}
@@ -124,6 +130,9 @@ export type Hit<T = Record<string, any>> = T & {
124130

125131
export type Hits<T = Record<string, any>> = Array<Hit<T>>
126132

133+
export type FacetStat = { min: number; max: number }
134+
export type FacetStats = Record<string, FacetStat>
135+
127136
export type SearchResponse<
128137
T = Record<string, any>,
129138
S extends SearchParams | undefined = undefined
@@ -132,6 +141,7 @@ export type SearchResponse<
132141
processingTimeMs: number
133142
facetDistribution?: FacetDistribution
134143
query: string
144+
facetStats?: FacetStats
135145
} & (undefined extends S
136146
? Partial<FinitePagination & InfinitePagination>
137147
: true extends IsFinitePagination<NonNullable<S>>
@@ -169,6 +179,12 @@ type HasPage<S extends SearchParams> = undefined extends S['page']
169179
? false
170180
: true
171181

182+
export type MultiSearchResult<T> = SearchResponse<T> & { indexUid: string }
183+
184+
export type MultiSearchResponse<T = Record<string, any>> = {
185+
results: Array<MultiSearchResult<T>>
186+
}
187+
172188
export type FieldDistribution = {
173189
[field: string]: number
174190
}

tests/search.test.ts

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ const emptyIndex = {
1717
uid: 'empty_test',
1818
}
1919

20+
type Books = {
21+
id: number
22+
title: string
23+
comment: string
24+
genre: string
25+
}
26+
2027
const dataset = [
2128
{
2229
id: 123,
@@ -85,6 +92,52 @@ describe.each([
8592
await client.waitForTask(task2)
8693
})
8794

95+
test(`${permission} key: Multi index search no queries`, async () => {
96+
const client = await getClient(permission)
97+
const response = await client.multiSearch({
98+
queries: [],
99+
})
100+
101+
expect(response.results.length).toEqual(0)
102+
})
103+
104+
test(`${permission} key: Multi index search with one query`, async () => {
105+
const client = await getClient(permission)
106+
const response = await client.multiSearch({
107+
queries: [{ indexUid: index.uid, q: 'prince' }],
108+
})
109+
110+
expect(response.results[0].hits.length).toEqual(2)
111+
})
112+
113+
test(`${permission} key: Multi index search with multiple queries`, async () => {
114+
const client = await getClient(permission)
115+
const response = await client.multiSearch({
116+
queries: [
117+
{ indexUid: index.uid, q: 'something' },
118+
{ indexUid: emptyIndex.uid, q: 'something' },
119+
],
120+
})
121+
122+
expect(response.results.length).toEqual(2)
123+
})
124+
125+
test(`${permission} key: Multi index search with one query`, async () => {
126+
const client = await getClient(permission)
127+
128+
type MyIndex = {
129+
id: 1
130+
}
131+
132+
const response = await client.multiSearch<MyIndex & Books>({
133+
queries: [{ indexUid: index.uid, q: 'prince' }],
134+
})
135+
136+
expect(response.results[0].hits.length).toEqual(2)
137+
expect(response.results[0].hits[0].id).toEqual(456)
138+
expect(response.results[0].hits[0].title).toEqual('Le Petit Prince')
139+
})
140+
88141
test(`${permission} key: Basic search`, async () => {
89142
const client = await getClient(permission)
90143
const response = await client.index(index.uid).search('prince', {})
@@ -94,6 +147,7 @@ describe.each([
94147
expect(response).toHaveProperty('offset', 0)
95148
expect(response).toHaveProperty('processingTimeMs', expect.any(Number))
96149
expect(response).toHaveProperty('query', 'prince')
150+
expect(response.facetStats).toBeUndefined()
97151
expect(response.hits.length).toEqual(2)
98152
// @ts-expect-error Not present in the SearchResponse type because neither `page` or `hitsPerPage` is provided in the search params.
99153
expect(response.hitsPerPage).toBeUndefined()
@@ -453,12 +507,16 @@ describe.each([
453507
const client = await getClient(permission)
454508
const response = await client.index(index.uid).search('a', {
455509
filter: ['genre = romance'],
456-
facets: ['genre'],
510+
facets: ['genre', 'id'],
457511
})
458512

459513
expect(response).toHaveProperty('facetDistribution', {
460514
genre: { romance: 2 },
515+
id: { '123': 1, '2': 1 },
461516
})
517+
518+
expect(response.facetStats).toEqual({ id: { min: 2, max: 123 } })
519+
expect(response.facetStats?.['id']?.max).toBe(123)
462520
expect(response).toHaveProperty('hits', expect.any(Array))
463521
expect(response.hits.length).toEqual(2)
464522
})
@@ -739,6 +797,14 @@ describe.each([{ permission: 'No' }])(
739797
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
740798
)
741799
})
800+
801+
test(`${permission} key: Try multi search and be denied`, async () => {
802+
const client = await getClient(permission)
803+
await expect(client.multiSearch({ queries: [] })).rejects.toHaveProperty(
804+
'code',
805+
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
806+
)
807+
})
742808
}
743809
)
744810

0 commit comments

Comments
 (0)