Skip to content

Commit 69323f6

Browse files
Merge #1041
1041: Add support for multiple sort attributes r=bidoubiwa a=fitimvata # Pull Request I created a new pull request with changes that `@bidoubiwa` requested in pull request #1024. ## Related issue Fixes #539 ## What does this PR do? - [x] Implement multiple sorting - [x] Add tests - [x] Update docs ## PR checklist Please check if your PR fulfills the following requirements: - [x] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)? - [x] Have you read the contributing guidelines? - [x] Have you made sure that the title is accurate and descriptive of the changes? Co-authored-by: Fitim Vata <[email protected]>
2 parents 87e7c42 + 1e6fe28 commit 69323f6

File tree

7 files changed

+85
-3
lines changed

7 files changed

+85
-3
lines changed

.changeset/red-fans-cross.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@meilisearch/instant-meilisearch": minor
3+
---
4+
5+
Add support for multiple sort attributes

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,19 @@ Example:
10321032

10331033
In this scenario, in the `clothes` index, we want the price to be sorted in an ascending way. For this formula to be valid, `price` must be added to the `sortableAttributes` settings of the `clothes` index.
10341034

1035+
#### Sort by multiple attributes
1036+
When sorting by mutiple fields sort formula is expressed like this: `index:attribute:order,attribute2:order`.
1037+
1038+
Example:
1039+
```js
1040+
[
1041+
{ label: 'Sort By Price And Title', value: 'clothes:price:asc,title:asc' }
1042+
]
1043+
```
1044+
1045+
⚠️ Attributes with comma in their name are not allowed.
1046+
1047+
10351048
#### Relevancy
10361049

10371050
The impact sorting has on the returned hits is determined by the [`ranking-rules`](https://docs.meilisearch.com/learn/core_concepts/relevancy.html#ranking-rules) ordered list of each index. The `sort` ranking-rule position in the list makes sorting documents more or less important than other rules. If you want to change the sort impact on the relevancy, it is possible to change it in the [ranking-rule setting](https://docs.meilisearch.com/learn/core_concepts/relevancy.html#relevancy). For example, to favor exhaustivity over relevancy.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {
2+
searchClient,
3+
dataset,
4+
Movies,
5+
meilisearchClient,
6+
} from './assets/utils'
7+
8+
describe('Sort browser test', () => {
9+
beforeAll(async () => {
10+
const deleteTask = await meilisearchClient.deleteIndex('movies')
11+
await meilisearchClient.waitForTask(deleteTask.taskUid)
12+
await meilisearchClient.index('movies').updateSettings({
13+
sortableAttributes: ['release_date', 'title'],
14+
})
15+
16+
const documentsTask = await meilisearchClient
17+
.index('movies')
18+
.addDocuments(dataset)
19+
await meilisearchClient.index('movies').waitForTask(documentsTask.taskUid)
20+
})
21+
22+
test('sort-by one field', async () => {
23+
const response = await searchClient.search<Movies>([
24+
{
25+
indexName: 'movies:release_date:desc',
26+
params: {
27+
query: '',
28+
hitsPerPage: 1,
29+
},
30+
},
31+
])
32+
33+
const hits = response.results[0].hits
34+
expect(hits.length).toBe(1)
35+
})
36+
37+
test('sort-by mutiple fields', async () => {
38+
const response = await searchClient.search<Movies>([
39+
{
40+
indexName: 'movies:release_date:desc,title:asc',
41+
params: {
42+
query: '',
43+
hitsPerPage: 1,
44+
},
45+
},
46+
])
47+
48+
const hits = response.results[0].hits
49+
expect(hits.length).toBe(1)
50+
})
51+
})

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export function MeiliParamsCreator(searchContext: SearchContext) {
166166
},
167167
addSort() {
168168
if (sort?.length) {
169-
meiliSearchParams.sort = [sort]
169+
meiliSearchParams.sort = Array.isArray(sort) ? sort : [sort]
170170
}
171171
},
172172
addGeoSearchRules() {

packages/instant-meilisearch/src/contexts/search-context.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from '../types'
66

77
import { createPaginationState } from './pagination-context'
8+
import { createSortState } from './sort-context'
89

910
/**
1011
* @param {AlgoliaMultipleQueriesQuery} searchRequest
@@ -25,10 +26,12 @@ export function createSearchContext(
2526
instantSearchParams?.page
2627
)
2728

29+
const sortState = createSortState(sortByArray.join(':'))
30+
2831
const searchContext: SearchContext = {
2932
...options,
3033
...instantSearchParams,
31-
sort: sortByArray.join(':') || '',
34+
sort: sortState,
3235
indexUid,
3336
pagination: paginationState,
3437
placeholderSearch: options.placeholderSearch !== false, // true by default
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* @param {string} rawSort
3+
* @returns {string[]}
4+
*/
5+
export function createSortState(rawSort: string): string[] {
6+
return rawSort
7+
.split(',')
8+
.map((sort) => sort.trim())
9+
.filter((sort) => !!sort)
10+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export type SearchContext = Omit<InstantSearchParams, 'insideBoundingBox'> &
7171
keepZeroFacets: boolean
7272
insideBoundingBox?: InsideBoundingBox
7373
cropMarker?: string
74-
sort?: string
74+
sort?: string | string[]
7575
primaryKey?: string
7676
matchingStrategy?: MatchingStrategies
7777
}

0 commit comments

Comments
 (0)