Skip to content

Commit 521b7cb

Browse files
authored
Add multi-search method (#1458)
1 parent 4e10856 commit 521b7cb

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

README.md

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

365+
### Multi Search
366+
367+
#### [Make multiple search requests](https://docs.meilisearch.com/reference/api/multi-search.html)
368+
369+
```ts
370+
client.multiSearch(queries?: MultiSearchParams, config?: Partial<Request>): Promise<Promise<MultiSearchResponse<T>>>
371+
```
372+
373+
`multiSearch` uses the `POST` method when performing its request to Meilisearch.
374+
365375
### Documents <!-- omit in toc -->
366376

367377
#### [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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ export type SearchRequestGET = Pagination &
106106
showMatchesPosition?: boolean
107107
}
108108

109+
export type MultiSearchParams = {
110+
queries: Array<SearchParams & { indexUid: string }>
111+
}
112+
109113
export type CategoriesDistribution = {
110114
[category: string]: number
111115
}
@@ -168,6 +172,10 @@ type HasPage<S extends SearchParams> = undefined extends S['page']
168172
? false
169173
: true
170174

175+
export type MultiSearchResponse<T = Record<string, any>> = {
176+
results: Array<SearchResponse<T> & { indexUid: string }>
177+
}
178+
171179
export type FieldDistribution = {
172180
[field: string]: number
173181
}

tests/search.test.ts

Lines changed: 61 additions & 0 deletions
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', {})
@@ -739,6 +792,14 @@ describe.each([{ permission: 'No' }])(
739792
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
740793
)
741794
})
795+
796+
test(`${permission} key: Try multi search and be denied`, async () => {
797+
const client = await getClient(permission)
798+
await expect(client.multiSearch({ queries: [] })).rejects.toHaveProperty(
799+
'code',
800+
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
801+
)
802+
})
742803
}
743804
)
744805

0 commit comments

Comments
 (0)