Skip to content

Commit 73c6c22

Browse files
committed
Add support for distinct attribute
1 parent 04b4e08 commit 73c6c22

File tree

5 files changed

+94
-70
lines changed

5 files changed

+94
-70
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,5 @@ data.ms
124124
.turbo
125125

126126
.angular
127+
128+
.idea

packages/instant-meilisearch/README.md

Lines changed: 62 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -160,15 +160,15 @@ Nonetheless you might want to still showcase them even if they have 0 matched do
160160

161161
Without `keepZeroFacets` set to `true`:
162162
genres:
163-
- [x] horror (2000)
164-
- [x] thriller (214)
165-
- [ ] comedy (0)
163+
- [x] horror (2000)
164+
- [x] thriller (214)
165+
- [ ] comedy (0)
166166

167167
With `keepZeroFacets` set to `false`, `comedy` disapears:
168168

169169
genres:
170-
- [x] horror (2000)
171-
- [x] thriller (214)
170+
- [x] horror (2000)
171+
- [x] thriller (214)
172172

173173
```js
174174
{ keepZeroFacets : true } // default: false
@@ -224,6 +224,7 @@ The following options can be overridden:
224224
[`showRankingScore`](https://www.meilisearch.com/docs/reference/api/search#ranking-score),
225225
[`attributesToSearchOn`](https://www.meilisearch.com/docs/reference/api/search#customize-attributes-to-search-on-at-search-time),
226226
[`hybrid`](https://www.meilisearch.com/docs/learn/experimental/vector_search)
227+
[`distinct`](https://www.meilisearch.com/docs/learn/relevancy/distinct_attribute)
227228

228229
```js
229230
instantMeiliSearch(
@@ -281,20 +282,20 @@ In `index.html`:
281282
```html
282283
<!DOCTYPE html>
283284
<html lang="en">
284-
<head>
285-
<meta charset="utf-8" />
286-
</head>
287-
288-
<body>
289-
<div>
290-
<div id="searchbox"></div>
291-
<div id="hits"></div>
292-
</div>
293-
294-
<script src="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
295-
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
296-
<script src="./app.js"></script>
297-
</body>
285+
<head>
286+
<meta charset="utf-8" />
287+
</head>
288+
289+
<body>
290+
<div>
291+
<div id="searchbox"></div>
292+
<div id="hits"></div>
293+
</div>
294+
295+
<script src="https://cdn.jsdelivr.net/npm/@meilisearch/instant-meilisearch/dist/instant-meilisearch.umd.min.js"></script>
296+
<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4"></script>
297+
<script src="./app.js"></script>
298+
</body>
298299
</html>
299300
```
300301

@@ -682,11 +683,11 @@ import injectScript from 'scriptjs'
682683
injectScript(
683684
`https://maps.googleapis.com/maps/api/js?v=quarterly&key=${GOOGLE_API}`,
684685
() => {
685-
const search = instantsearch({
686+
const search = instantsearch({
686687
indexName: 'geo',
687688
// ...
688-
})
689-
// ...
689+
})
690+
// ...
690691
})
691692
```
692693

@@ -700,9 +701,9 @@ The classic usage, with only the `required` elements, renders an embedded Google
700701

701702
```js
702703
instantsearch.widgets.geoSearch({
703-
container: '#maps',
704-
googleReference: window.google,
705-
}),
704+
container: '#maps',
705+
googleReference: window.google,
706+
}),
706707
```
707708

708709
For further customization, for example to determine an initial position for the map. Contrary to `initialZoom` and `initialPosition`, triggers a search request with the provided information.
@@ -718,24 +719,24 @@ For exemple, by adding `boundingBox` in the [`instantSearch`](#-instantsearch) w
718719

719720
```js
720721
initialUiState: {
721-
geo: {
722-
geoSearch: {
723-
boundingBox:
724-
'50.680720183653065, 3.273798366642514,50.55969330590075, 2.9625244444490253',
725-
},
722+
geo: {
723+
geoSearch: {
724+
boundingBox:
725+
'50.680720183653065, 3.273798366642514,50.55969330590075, 2.9625244444490253',
726726
},
727727
},
728+
},
728729
```
729730
Without providing this parameter, Google Maps will default to a window containing all markers from the provided search results.
730731

731732
Alternatively, the parameters can be passed through the [`searchFunction`](https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/#widget-param-searchfunction) parameter of the [`instantSearch`](#-instantsearch) widget. Contrary to `initialUiState` these parameters overwrite the values on each search.
732733

733734
```js
734735
searchFunction: function (helper) {
735-
helper.setQueryParameter('aroundRadius', 75000)
736-
helper.setQueryParameter('aroundLatLng', '51.1241999, 9.662499900000057');
737-
helper.search()
738-
},
736+
helper.setQueryParameter('aroundRadius', 75000)
737+
helper.setQueryParameter('aroundLatLng', '51.1241999, 9.662499900000057');
738+
helper.search()
739+
},
739740
```
740741

741742
[Read the guide on how GeoSearch works in Meilisearch](https://www.meilisearch.com/docs/learn/getting_started/filtering_and_sorting#geosearch).
@@ -805,12 +806,12 @@ Example:
805806
Give the following document structure:
806807
```json
807808
{
808-
"id": 1,
809-
"name": "Basic T-shirt",
810-
"categories.lvl0": "Men",
811-
"categories.lvl1": "Men > clothes",
812-
"categories.lvl2": "Men > clothes > t-shirt"
813-
}
809+
"id": 1,
810+
"name": "Basic T-shirt",
811+
"categories.lvl0": "Men",
812+
"categories.lvl1": "Men > clothes",
813+
"categories.lvl2": "Men > clothes > t-shirt"
814+
}
814815
```
815816

816817
You have to add the fields `categories.lvl0`, `categories.lvl1` and `categories.lvl2` in the `filterableAttributes` in your Meilisearch settings.
@@ -953,8 +954,8 @@ The `clearRefinement` widget displays a button that lets the user clean every re
953954

954955
```js
955956
instantsearch.widgets.clearRefinements({
956-
container: '#clear-refinements',
957-
}),
957+
container: '#clear-refinements',
958+
}),
958959
```
959960

960961
### ✅ Pagination
@@ -1060,8 +1061,8 @@ The usage of the `SortBy` widget differs from the one found in Algolia's documen
10601061
- Different `sort` rules on the same index.
10611062

10621063
The items list is composed of objects containing every sort possibility you want to provide to your user. Each object must contain two fields:
1063-
- `label`: What is showcased on the user interface ex: `Sort by Ascending Price`
1064-
- `value`: The sort formula.
1064+
- `label`: What is showcased on the user interface ex: `Sort by Ascending Price`
1065+
- `value`: The sort formula.
10651066

10661067
#### Sort formula
10671068

@@ -1090,23 +1091,23 @@ See [relevancy guide](https://www.meilisearch.com/docs/learn/core_concepts/relev
10901091

10911092
```js
10921093
instantsearch.widgets.sortBy({
1093-
container: '#sort-by',
1094-
items: [
1095-
{ value: 'clothes', label: 'Relevant' }, // default index
1096-
{
1097-
value: 'clothes:price:desc', // Sort on descending price
1098-
label: 'Ascending price using query time sort',
1099-
},
1100-
{
1101-
value: 'clothes:price:asc', // Sort on ascending price
1102-
label: 'Descending price using query time sort',
1103-
},
1104-
{
1105-
value: 'clothes-sorted', // different index with different ranking rules.
1106-
label: 'Custom sort using a different index',
1107-
},
1108-
],
1109-
}),
1094+
container: '#sort-by',
1095+
items: [
1096+
{ value: 'clothes', label: 'Relevant' }, // default index
1097+
{
1098+
value: 'clothes:price:desc', // Sort on descending price
1099+
label: 'Ascending price using query time sort',
1100+
},
1101+
{
1102+
value: 'clothes:price:asc', // Sort on ascending price
1103+
label: 'Descending price using query time sort',
1104+
},
1105+
{
1106+
value: 'clothes-sorted', // different index with different ranking rules.
1107+
label: 'Custom sort using a different index',
1108+
},
1109+
],
1110+
}),
11101111
```
11111112

11121113
### ❌ RelevantSort

packages/instant-meilisearch/src/adapter/search-request-adapter/__tests__/search-params.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ describe('Parameters adapter', () => {
9494

9595
expect(searchParams.hybrid).toBe(hybridSearchConfig)
9696
})
97+
98+
test('distinct search configuration can be set via search parameters', () => {
99+
const distinctSearchConfig = 'title'
100+
101+
const searchParams = adaptSearchParams({
102+
...DEFAULT_CONTEXT,
103+
meiliSearchParams: {
104+
distinct: distinctSearchConfig,
105+
},
106+
})
107+
108+
expect(searchParams.distinct).toBe(distinctSearchConfig)
109+
})
97110
})
98111

99112
describe('Geo filter adapter', () => {

packages/instant-meilisearch/src/adapter/search-request-adapter/search-params-adapter.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export function MeiliParamsCreator(searchContext: SearchContext) {
139139
addAttributesToHighlight() {
140140
meiliSearchParams.attributesToHighlight =
141141
overrideParams?.attributesToHighlight ??
142-
<Mutable<typeof attributesToHighlight>>attributesToHighlight ?? ['*']
142+
<Mutable<typeof attributesToHighlight>>attributesToHighlight ?? ['*']
143143
},
144144
addPreTag() {
145145
meiliSearchParams.highlightPreTag =
@@ -226,8 +226,8 @@ export function MeiliParamsCreator(searchContext: SearchContext) {
226226
overrideParams?.attributesToSearchOn !== undefined
227227
? overrideParams.attributesToSearchOn
228228
: <Mutable<typeof restrictSearchableAttributes>>(
229-
restrictSearchableAttributes
230-
)
229+
restrictSearchableAttributes
230+
)
231231
if (value !== undefined) {
232232
meiliSearchParams.attributesToSearchOn = value
233233
}
@@ -238,6 +238,12 @@ export function MeiliParamsCreator(searchContext: SearchContext) {
238238
meiliSearchParams.hybrid = value
239239
}
240240
},
241+
addDistinct() {
242+
const value = overrideParams?.distinct
243+
if (value !== undefined) {
244+
meiliSearchParams.distinct = value
245+
}
246+
},
241247
}
242248
}
243249

@@ -270,6 +276,7 @@ export function adaptSearchParams(
270276
meilisearchParams.addShowRankingScore()
271277
meilisearchParams.addAttributesToSearchOn()
272278
meilisearchParams.addHybridSearch()
279+
meilisearchParams.addDistinct()
273280

274281
return meilisearchParams.getParams()
275282
}

packages/instant-meilisearch/src/types/types.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export type OverridableMeiliSearchSearchParameters = Pick<
5555
| 'showRankingScore'
5656
| 'attributesToSearchOn'
5757
| 'hybrid'
58+
| 'distinct'
5859
>
5960

6061
type BaseInstantMeiliSearchOptions = {
@@ -104,15 +105,15 @@ export type InstantSearchPagination = {
104105

105106
export type MeilisearchMultiSearchResult<T = Record<string, any>> =
106107
MultiSearchResult<T> & {
107-
pagination: PaginationState
108-
}
108+
pagination: PaginationState
109+
}
109110

110111
export type SearchContext = InstantMeiliSearchOptions &
111112
InstantSearchParams & {
112-
pagination: PaginationState
113-
indexUid: string
114-
sort?: string | string[]
115-
}
113+
pagination: PaginationState
114+
indexUid: string
115+
sort?: string | string[]
116+
}
116117

117118
export type InstantSearchGeoParams = {
118119
aroundLatLng?: string

0 commit comments

Comments
 (0)