Skip to content

Commit

Permalink
Merge #1030
Browse files Browse the repository at this point in the history
1030: 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 <74670311+meili-bot@users.noreply.github.com>
Co-authored-by: cvermand <33010418+bidoubiwa@users.noreply.github.com>
Co-authored-by: Charlotte Vermandel <charlottevermandel@gmail.com>
  • Loading branch information
4 people authored Apr 3, 2023
2 parents 1bd7e3e + c4abafb commit 2d8296a
Show file tree
Hide file tree
Showing 31 changed files with 612 additions and 526 deletions.
5 changes: 5 additions & 0 deletions .changeset/fresh-countries-move.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@meilisearch/instant-meilisearch": minor
---

Replaces search with multiSearch API.
5 changes: 5 additions & 0 deletions .changeset/small-masks-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@meilisearch/instant-meilisearch": patch
---

Use the `_geoBoundingBox` filter to adapt the `insideBoundingBox`parameter
6 changes: 6 additions & 0 deletions .changeset/stupid-mirrors-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@meilisearch/instant-meilisearch": patch
---

Add the facetStats of numeric facets, giving access to the min and max value of these facets.
The following widgets are now compatible with Meilisearch: `RangeSlider` and `RangeInput`
51 changes: 3 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,6 @@ const search = instantsearch({

`Index` is the component that lets you apply widgets to a dedicated index. It’s useful if you want to build an interface that targets multiple indices.

Using this component, instant-meilisearch does an http-request for each different `Index` widget added. More http requests are made when using the [`RefinementList`](#✅-refinementlist) widget.

### ✅ SearchBox

[SearchBox references](https://www.algolia.com/doc/api-reference/widgets/search-box/js/)
Expand Down Expand Up @@ -675,9 +673,6 @@ The `refinementList` widget is one of the most common widgets you can find in a
- ✅ templates: The templates to use for the widget.
- ✅ cssClasses: The CSS classes to override.

The `RefinementList` widget uses the `disjunctive facet search` principle when using the `or` operator. For each different facet category used, an additional http call is made.
For example, if I ask for `color=green` and `size=2`, three http requests are made. One for the hits, one for the `color` facet distribution, and one for the `size` facet distribution. To provide feedback on the subject, refer to [this discussion](https://github.com/meilisearch/product/issues/54).

The following example will create a UI component with the a list of genres on which you will be able to facet.

```js
Expand Down Expand Up @@ -746,54 +741,14 @@ The `rangeSlider` widget provides a user-friendly way to filter the results, bas
- ✅ attribute: The name of the attribute in the document. _required_.
- ✅ min: The minimum value for the input. _required_
- ✅ max: The maximum value for the input. _required_
- precision: The number of digits after the decimal point to use. Not compatible as only integers work with `rangeSlider`.
- precision: The number of digits after the decimal point to use. Not compatible as only integers work with `rangeSlider`.
- ✅ step: The number of steps between each handle move.
- ✅ pips: Whether to show slider pips (ruler marks).
- ✅ tooltips: Whether to show tooltips. The default tooltips show the raw value.
- ✅ cssClasses: The CSS classes to override.

#### ⚠️ The component is compatible but only by applying the following requirements:

#### 1. Manual Min Max

Min and max of attributes are not returned from Meilisearch and thus **must be set manually**.

```js
instantsearch.widgets.rangeSlider({
// ...
min: 0,
max: 100000,
}),
```

#### 2. Attribute must be in `filterableAttributes`

If the attribute is not in the [`filterableAttributes`](https://docs.meilisearch.com/reference/features/filtering_and_faceted_search.html#configuring-filters) setting list, filtering on this attribute is not possible.

Example:
Given the attribute `id` that has not been added in `filterableAttributes`:

```js
instantsearch.widgets.rangeSlider({
attribute: 'id',
// ...
}),
```

The widget throws the following error:

```json
{
"message": " .. attribute `id` is not filterable, available filterable attributes are: author, price, genres",
"errorCode": "bad_request",
"errorType": "invalid_request_error",
"errorLink": "https://docs.meilisearch.com/errors#bad_request"
}
```

To avoid this error, the attribute must be added to the [`filterableAttributes` setting](https://docs.meilisearch.com/reference/api/filterable_attributes.html#get-filterable-attributes).
To be able to use the `rangeSlider` on an attribute, the attribute must be in the[`filterableAttributes`](https://docs.meilisearch.com/reference/features/filtering_and_faceted_search.html#configuring-filters) and must contain numeric values.

After these steps, `rangeSlider` becomes compatible.

### ✅ Menu

Expand Down Expand Up @@ -837,7 +792,7 @@ The `rangeInput` widget allows a user to select a numeric range using a minimum
- ✅ templates: The templates to use for the widget.
- ✅ cssClasses: The CSS classes to override.

⚠️ Not compatible with Meilisearch by default, needs a workaround. See workaround in [RangeSlider](#-rangeslider) section.
To be able to use the `RangeInput` on an attribute, the attribute must be in the[`filterableAttributes`](https://docs.meilisearch.com/reference/features/filtering_and_faceted_search.html#configuring-filters) and must contain numeric values.

### ✅ MenuSelect

Expand Down
68 changes: 68 additions & 0 deletions packages/instant-meilisearch/__tests__/facet-stats.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { searchClient, dataset, meilisearchClient } from './assets/utils'

describe('Facet stats tests', () => {
beforeAll(async () => {
const deleteTask = await meilisearchClient.deleteIndex('movies')
await meilisearchClient.waitForTask(deleteTask.taskUid)
await meilisearchClient
.index('movies')
.updateFilterableAttributes(['genres', 'release_date', 'id'])
const documentsTask = await meilisearchClient
.index('movies')
.addDocuments(dataset)
await meilisearchClient.index('movies').waitForTask(documentsTask.taskUid)
})

test('Facet stats on an empty facets array', async () => {
const response = await searchClient.search([
{
indexName: 'movies',
params: {
query: '',
facets: [],
},
},
])

expect(response.results[0].facets_stats?.release_date).toEqual(undefined)
})

test('Facet stats on a facet with no numeric values', async () => {
const response = await searchClient.search([
{
indexName: 'movies',
params: {
query: '',
facets: ['genres'],
},
},
])

expect(response.results[0].facets_stats?.genres).toEqual(undefined)
})

test('Facet stats on two facet', async () => {
const response = await searchClient.search([
{
indexName: 'movies',
params: {
query: '',
facets: ['release_date', 'id'],
},
},
])

expect(response.results[0].facets_stats?.release_date).toEqual({
avg: 0,
max: 1065744000,
min: 233366400,
sum: 0,
})
expect(response.results[0].facets_stats?.id).toEqual({
avg: 0,
max: 30,
min: 2,
sum: 0,
})
})
})
14 changes: 7 additions & 7 deletions packages/instant-meilisearch/__tests__/geosearch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('Instant Meilisearch Browser test', () => {
])

const hits = response.results[0].hits
expect(hits.length).toEqual(7)
expect(hits.length).toEqual(5)
expect(hits[0].city).toEqual('Lille')
})

Expand All @@ -68,8 +68,8 @@ describe('Instant Meilisearch Browser test', () => {
])

const hits = response.results[0].hits
expect(hits.length).toEqual(4)
expect(hits[0].city).toEqual('Ghent')
expect(hits.length).toEqual(2)
expect(hits[0].city).toEqual('Brussels')
})

test('insideBoundingBox and aroundRadius in geo search', async () => {
Expand All @@ -86,8 +86,8 @@ describe('Instant Meilisearch Browser test', () => {
])

const hits = response.results[0].hits
expect(hits.length).toEqual(4)
expect(hits[0].city).toEqual('Ghent')
expect(hits.length).toEqual(2)
expect(hits[0].city).toEqual('Brussels')
})

test('insideBoundingBox and aroundLatLng in geo search', async () => {
Expand All @@ -104,7 +104,7 @@ describe('Instant Meilisearch Browser test', () => {
])

const hits = response.results[0].hits
expect(hits.length).toEqual(4)
expect(hits[0].city).toEqual('Ghent')
expect(hits.length).toEqual(2)
expect(hits[0].city).toEqual('Brussels')
})
})
59 changes: 50 additions & 9 deletions packages/instant-meilisearch/__tests__/search-resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { instantMeiliSearch } from '../src'
import { MeiliSearch } from 'meilisearch'
import { mocked } from 'ts-jest/utils'
import { PACKAGE_VERSION } from '../src/package-version'
import { MeiliSearchMultiSearchParams } from '../src/types'

jest.mock('meilisearch')

Expand All @@ -18,19 +19,22 @@ export const searchResponse = {

// Mocking of Meilisearch package
const mockedMeilisearch = mocked(MeiliSearch, true)
const mockedSearch = jest.fn(() => searchResponse)
const mockedIndex = jest.fn(() => {
const mockedMultiSearch = jest.fn((request) => {
const response = request.queries.map((req: MeiliSearchMultiSearchParams) => ({
...searchResponse,
indexUid: req.indexUid,
}))
return {
search: mockedSearch,
results: response,
}
})

mockedMeilisearch.mockReturnValue({
// @ts-ignore
index: mockedIndex,
multiSearch: mockedMultiSearch,
})

describe('Pagination browser test', () => {
describe('Cached search tests', () => {
afterEach(() => {
jest.clearAllMocks()
})
Expand All @@ -51,7 +55,7 @@ describe('Pagination browser test', () => {
apiKey: '',
clientAgents: [`Meilisearch instant-meilisearch (v${PACKAGE_VERSION})`],
})
expect(mockedSearch).toHaveBeenCalledTimes(2)
expect(mockedMultiSearch).toHaveBeenCalledTimes(2)
})

test('two different search parameters', async () => {
Expand All @@ -77,7 +81,7 @@ describe('Pagination browser test', () => {
apiKey: '',
clientAgents: [`Meilisearch instant-meilisearch (v${PACKAGE_VERSION})`],
})
expect(mockedSearch).toHaveBeenCalledTimes(3)
expect(mockedMultiSearch).toHaveBeenCalledTimes(3)
})

test('two identical and one different search parameters', async () => {
Expand All @@ -104,7 +108,7 @@ describe('Pagination browser test', () => {
apiKey: '',
clientAgents: [`Meilisearch instant-meilisearch (v${PACKAGE_VERSION})`],
})
expect(mockedSearch).toHaveBeenCalledTimes(3)
expect(mockedMultiSearch).toHaveBeenCalledTimes(3)
})

test('two same and two different search parameter', async () => {
Expand Down Expand Up @@ -132,6 +136,43 @@ describe('Pagination browser test', () => {
apiKey: '',
clientAgents: [`Meilisearch instant-meilisearch (v${PACKAGE_VERSION})`],
})
expect(mockedSearch).toHaveBeenCalledTimes(3)
expect(mockedMultiSearch).toHaveBeenCalledTimes(3)
})

test('Multiple search parameters on different index uids', async () => {
const searchParameters1 = [
{
indexName: 'movies',
params: {
query: '',
},
},
{
indexName: 'game',
params: {
query: '',
},
},
]

const searchParameters2 = {
indexName: 'movies',
params: {
query: 'other query',
},
}
const searchClient = instantMeiliSearch('http://localhost:7700')
await searchClient.search<Movies>(searchParameters1)
await searchClient.search<Movies>([searchParameters2])
await searchClient.search<Movies>(searchParameters1)
await searchClient.search<Movies>([searchParameters2])

expect(mockedMeilisearch).toHaveBeenCalledWith({
host: 'http://localhost:7700',
apiKey: '',
clientAgents: [`Meilisearch instant-meilisearch (v${PACKAGE_VERSION})`],
})

expect(mockedMultiSearch).toHaveBeenCalledTimes(3)
})
})
2 changes: 1 addition & 1 deletion packages/instant-meilisearch/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"templates"
],
"dependencies": {
"meilisearch": "^0.31.1"
"meilisearch": "^0.32.1"
},
"devDependencies": {
"@babel/cli": "^7.21.0",
Expand Down
Loading

0 comments on commit 2d8296a

Please sign in to comment.