Skip to content

Commit 3313aac

Browse files
committed
Add faceting index settings methods
1 parent f44b475 commit 3313aac

File tree

3 files changed

+258
-0
lines changed

3 files changed

+258
-0
lines changed

.code-samples.meilisearch.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@ update_displayed_attributes_1: |-
190190
])
191191
reset_displayed_attributes_1: |-
192192
client.index('movies').resetDisplayedAttributes()
193+
get_faceting_1: |-
194+
client.index('books').getFaceting()
195+
update_faceting_1: |-
196+
client.index('books').updateFaceting({ maxValuesPerFacet: 2 })
197+
reset_faceting_1: |-
198+
client.index('books').resetFaceting()
199+
settings_guide_faceting_1: |-
200+
client.index('movies').updateFaceting({ maxValuesPerFacet: 5 })
193201
get_typo_tolerance_1: |-
194202
client.index('books').getTypoTolerance()
195203
update_typo_tolerance_1: |-

src/indexes.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
DocumentsResults,
3939
TasksQuery,
4040
TasksResults,
41+
Faceting,
4142
} from './types'
4243
import { removeUndefinedFromObject } from './utils'
4344
import { HttpRequests } from './http-requests'
@@ -993,6 +994,52 @@ class Index<T = Record<string, any>> {
993994

994995
return task
995996
}
997+
998+
///
999+
/// FACETING
1000+
///
1001+
1002+
/**
1003+
* Get the faceting index settings
1004+
* @memberof Index
1005+
* @method getFaceting
1006+
* @returns {Promise<Faceting>} Promise containing object of faceting index settings
1007+
*/
1008+
async getFaceting(): Promise<Faceting> {
1009+
const url = `indexes/${this.uid}/settings/faceting`
1010+
return await this.httpRequest.get<Faceting>(url)
1011+
}
1012+
1013+
/**
1014+
* Update the faceting index settings
1015+
* @memberof Index
1016+
* @method updateFaceting
1017+
* @param {Faceting} faceting Faceting index settings object
1018+
* @returns {Promise<EnqueuedTask>} Promise containing object of the enqueued task
1019+
*/
1020+
async updateFaceting(faceting: Faceting): Promise<EnqueuedTask> {
1021+
const url = `indexes/${this.uid}/settings/faceting`
1022+
const task = await this.httpRequest.patch(url, faceting)
1023+
1024+
task.enqueuedAt = new Date(task.enqueuedAt)
1025+
1026+
return task
1027+
}
1028+
1029+
/**
1030+
* Reset the faceting index settings to default values
1031+
* @memberof Index
1032+
* @method resetFaceting
1033+
* @returns {Promise<EnqueuedTask>} Promise containing object of the enqueued task
1034+
*/
1035+
async resetFaceting(): Promise<EnqueuedTask> {
1036+
const url = `indexes/${this.uid}/settings/faceting`
1037+
const task = await this.httpRequest.delete<EnqueuedTask>(url)
1038+
1039+
task.enqueuedAt = new Date(task.enqueuedAt)
1040+
1041+
return task
1042+
}
9961043
}
9971044

9981045
export { Index }

tests/faceting.test.ts

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import { ErrorStatusCode } from '../src/types'
2+
import {
3+
clearAllIndexes,
4+
config,
5+
BAD_HOST,
6+
MeiliSearch,
7+
getClient,
8+
dataset,
9+
} from './utils/meilisearch-test-utils'
10+
11+
const index = {
12+
uid: 'movies_test',
13+
}
14+
15+
jest.setTimeout(100 * 1000)
16+
17+
afterAll(() => {
18+
return clearAllIndexes(config)
19+
})
20+
21+
describe.each([{ permission: 'Master' }, { permission: 'Private' }])(
22+
'Test on faceting',
23+
({ permission }) => {
24+
beforeEach(async () => {
25+
const client = await getClient('Master')
26+
const { taskUid } = await client.createIndex(index.uid)
27+
await client.waitForTask(taskUid)
28+
29+
const { taskUid: docTask } = await client
30+
.index(index.uid)
31+
.addDocuments(dataset)
32+
await client.waitForTask(docTask)
33+
})
34+
35+
test(`${permission} key: Get default faceting object`, async () => {
36+
const client = await getClient(permission)
37+
38+
const response = await client.index(index.uid).getFaceting()
39+
40+
expect(response).toEqual({ maxValuesPerFacet: 100 })
41+
})
42+
43+
test(`${permission} key: Update faceting settings`, async () => {
44+
const client = await getClient(permission)
45+
const newFaceting = { maxValuesPerFacet: 12 }
46+
const task = await client.index(index.uid).updateFaceting(newFaceting)
47+
await client.index(index.uid).waitForTask(task.taskUid)
48+
49+
const response = await client.index(index.uid).getFaceting()
50+
expect(response).toEqual(newFaceting)
51+
})
52+
53+
test(`${permission} key: Update faceting at null`, async () => {
54+
const client = await getClient(permission)
55+
const task = await client
56+
.index(index.uid)
57+
.updateFaceting({ maxValuesPerFacet: null })
58+
await client.index(index.uid).waitForTask(task.taskUid)
59+
60+
const response = await client.index(index.uid).getFaceting()
61+
62+
expect(response).toEqual({ maxValuesPerFacet: 100 })
63+
})
64+
65+
test(`${permission} key: Reset faceting`, async () => {
66+
const client = await getClient(permission)
67+
68+
await client
69+
.index(index.uid)
70+
.waitForTask(
71+
(
72+
await client
73+
.index(index.uid)
74+
.updateFaceting({ maxValuesPerFacet: 12 })
75+
).taskUid
76+
)
77+
78+
const task = await client.index(index.uid).resetFaceting()
79+
await client.index(index.uid).waitForTask(task.taskUid)
80+
81+
const response = await client.index(index.uid).getFaceting()
82+
83+
expect(response).toEqual({ maxValuesPerFacet: 100 })
84+
})
85+
}
86+
)
87+
88+
describe.each([{ permission: 'Public' }])(
89+
'Test on faceting',
90+
({ permission }) => {
91+
beforeEach(async () => {
92+
const client = await getClient('Master')
93+
const { taskUid } = await client.createIndex(index.uid)
94+
await client.waitForTask(taskUid)
95+
})
96+
97+
test(`${permission} key: try to get faceting and be denied`, async () => {
98+
const client = await getClient(permission)
99+
await expect(
100+
client.index(index.uid).getFaceting()
101+
).rejects.toHaveProperty('code', ErrorStatusCode.INVALID_API_KEY)
102+
})
103+
104+
test(`${permission} key: try to update faceting and be denied`, async () => {
105+
const client = await getClient(permission)
106+
await expect(
107+
client.index(index.uid).updateFaceting({ maxValuesPerFacet: 13 })
108+
).rejects.toHaveProperty('code', ErrorStatusCode.INVALID_API_KEY)
109+
})
110+
111+
test(`${permission} key: try to reset faceting and be denied`, async () => {
112+
const client = await getClient(permission)
113+
await expect(
114+
client.index(index.uid).resetFaceting()
115+
).rejects.toHaveProperty('code', ErrorStatusCode.INVALID_API_KEY)
116+
})
117+
}
118+
)
119+
120+
describe.each([{ permission: 'No' }])('Test on faceting', ({ permission }) => {
121+
beforeAll(async () => {
122+
const client = await getClient('Master')
123+
const { taskUid } = await client.createIndex(index.uid)
124+
await client.waitForTask(taskUid)
125+
})
126+
127+
test(`${permission} key: try to get faceting and be denied`, async () => {
128+
const client = await getClient(permission)
129+
await expect(client.index(index.uid).getFaceting()).rejects.toHaveProperty(
130+
'code',
131+
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
132+
)
133+
})
134+
135+
test(`${permission} key: try to update faceting and be denied`, async () => {
136+
const client = await getClient(permission)
137+
await expect(
138+
client.index(index.uid).updateFaceting({ maxValuesPerFacet: 13 })
139+
).rejects.toHaveProperty(
140+
'code',
141+
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
142+
)
143+
})
144+
145+
test(`${permission} key: try to reset faceting and be denied`, async () => {
146+
const client = await getClient(permission)
147+
await expect(
148+
client.index(index.uid).resetFaceting()
149+
).rejects.toHaveProperty(
150+
'code',
151+
ErrorStatusCode.MISSING_AUTHORIZATION_HEADER
152+
)
153+
})
154+
})
155+
156+
describe.each([
157+
{ host: BAD_HOST, trailing: false },
158+
{ host: `${BAD_HOST}/api`, trailing: false },
159+
{ host: `${BAD_HOST}/trailing/`, trailing: true },
160+
])('Tests on url construction', ({ host, trailing }) => {
161+
test(`Test getFaceting route`, async () => {
162+
const route = `indexes/${index.uid}/settings/faceting`
163+
const client = new MeiliSearch({ host })
164+
const strippedHost = trailing ? host.slice(0, -1) : host
165+
await expect(client.index(index.uid).getFaceting()).rejects.toHaveProperty(
166+
'message',
167+
`request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace(
168+
'http://',
169+
''
170+
)}`
171+
)
172+
})
173+
174+
test(`Test updateFaceting route`, async () => {
175+
const route = `indexes/${index.uid}/settings/faceting`
176+
const client = new MeiliSearch({ host })
177+
const strippedHost = trailing ? host.slice(0, -1) : host
178+
await expect(
179+
client.index(index.uid).updateFaceting({ maxValuesPerFacet: null })
180+
).rejects.toHaveProperty(
181+
'message',
182+
`request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace(
183+
'http://',
184+
''
185+
)}`
186+
)
187+
})
188+
189+
test(`Test resetFaceting route`, async () => {
190+
const route = `indexes/${index.uid}/settings/faceting`
191+
const client = new MeiliSearch({ host })
192+
const strippedHost = trailing ? host.slice(0, -1) : host
193+
await expect(
194+
client.index(index.uid).resetFaceting()
195+
).rejects.toHaveProperty(
196+
'message',
197+
`request to ${strippedHost}/${route} failed, reason: connect ECONNREFUSED ${BAD_HOST.replace(
198+
'http://',
199+
''
200+
)}`
201+
)
202+
})
203+
})

0 commit comments

Comments
 (0)