Skip to content

Commit 816b98e

Browse files
authored
Merge branch 'main' into bump-meilisearch-v1.7.0
2 parents 337420e + 4c7a4ac commit 816b98e

File tree

7 files changed

+240
-7
lines changed

7 files changed

+240
-7
lines changed

.code-samples.meilisearch.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,5 +288,11 @@ security_guide_delete_key_1: |-
288288
await client.deleteKey('ac5cd97d-5a4b-4226-a868-2d0eb6d197ab');
289289
search_parameter_guide_crop_marker_1: "await client.index('movies').search(\n 'shifu',\n SearchQuery(\n attributesToCrop: ['overview'],\n cropMarker: '[…]',\n ),\n );"
290290
search_parameter_guide_highlight_tag_1: "await client.index('movies').search(\n 'winter feast',\n SearchQuery(\n attributesToHighlight: ['overview'],\n highlightPreTag: '<span class=\"highlight\">',\n highlightPostTag: '<\/span>',\n ),\n );"
291-
geosearch_guide_filter_usage_3: "await client.index('restaurants').search(\n '',\n SearchQuery(\n filter:\n '_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])'));\n});"
291+
geosearch_guide_filter_usage_3: "await client.index('restaurants').search(\n '',\n SearchQuery(\n filter:\n '_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])',\n ),\n );"
292292
search_get_1: await client.index('movies').search('American ninja');
293+
get_separator_tokens_1: await client.index('articles').getSeparatorTokens();
294+
update_separator_tokens_1: "await client.index('articles').updateSeparatorTokens([\"|\", \"&hellip;\"]);"
295+
reset_separator_tokens_1: await client.index('articles').resetSeparatorTokens();
296+
get_non_separator_tokens_1: await client.index('articles').getNonSeparatorTokens();
297+
update_non_separator_tokens_1: "await client.index('articles').updateNonSeparatorTokens([\"@\", \"#\"]);"
298+
reset_non_separator_tokens_1: await client.index('articles').resetNonSeparatorTokens();

.github/workflows/release-drafter.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
update_release_draft:
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: release-drafter/release-drafter@v5
12+
- uses: release-drafter/release-drafter@v6
1313
with:
1414
config-name: release-draft-template.yml
1515
env:

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@
2828

2929
**Meilisearch** is an open-source search engine. [Learn more about Meilisearch.](https://github.com/meilisearch/meilisearch)
3030

31-
## Table of Contents <!-- omit in TOC -->
31+
## Table of Contents <!-- omit from toc -->
3232

3333
- [📖 Documentation](#-documentation)
3434
- [⚡ Supercharge your Meilisearch experience](#-supercharge-your-meilisearch-experience)
3535
- [🔧 Installation](#-installation)
3636
- [🚀 Getting started](#-getting-started)
37+
- [Advanced Configuration](#advanced-configuration)
38+
- [Customizing the dio instance](#customizing-the-dio-instance)
39+
- [Using MeiliDocumentContainer](#using-meilidocumentcontainer)
3740
- [🤖 Compatibility with Meilisearch](#-compatibility-with-meilisearch)
3841
- [💡 Learn more](#-learn-more)
3942
- [⚙️ Contributing](#️-contributing)
@@ -198,6 +201,25 @@ await index.search('wonder', filter: ['id > 1 AND genres = Action']);
198201
}
199202
```
200203

204+
## Advanced Configuration
205+
206+
### Customizing the dio instance
207+
208+
Meilisearch uses [dio](https://pub.dev/packages/dio) internally to send requests, you can provide it with your own interceptors or adapter using the `MeiliSearchClient.withCustomDio` constructor.
209+
210+
### Using MeiliDocumentContainer
211+
212+
The `MeiliDocumentContainer<T>` class contains meilisearch-specific fields (e.g. `rankingScoreDetails`, `_formatted`, `matchesPosition`, etc...).
213+
214+
We define the `mapToContainer()` extension to help you quickly opt-in to this class, example:
215+
216+
```dart
217+
final res = await index
218+
.search("hello world")
219+
.asSearchResult() //or .asPaginatedResult() if using page parameters
220+
.mapToContainer();
221+
```
222+
201223
## 🤖 Compatibility with Meilisearch
202224

203225
This package guarantees compatibility with [version v1.x of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/latest), but some features may not be present. Please check the [issues](https://github.com/meilisearch/meilisearch-dart/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22+label%3Aenhancement) for more info.

lib/src/index.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,56 @@ class MeiliSearchIndex {
608608
);
609609
}
610610

611+
/// Get separator tokens of the index.
612+
Future<List<String>> getSeparatorTokens() async {
613+
final response = await http
614+
.getMethod<List<Object?>>('/indexes/$uid/settings/separator-tokens');
615+
616+
return response.data!.cast<String>();
617+
}
618+
619+
/// Reset separator tokens of the index.
620+
Future<Task> resetSeparatorTokens() async {
621+
return await _getTask(
622+
http.deleteMethod('/indexes/$uid/settings/separator-tokens'),
623+
);
624+
}
625+
626+
/// Update separator tokens of the index.
627+
Future<Task> updateSeparatorTokens(List<String> separatorTokens) async {
628+
return await _getTask(
629+
http.putMethod(
630+
'/indexes/$uid/settings/separator-tokens',
631+
data: separatorTokens,
632+
),
633+
);
634+
}
635+
636+
/// Get non separator tokens of the index.
637+
Future<List<String>> getNonSeparatorTokens() async {
638+
final response = await http.getMethod<List<Object?>>(
639+
'/indexes/$uid/settings/non-separator-tokens');
640+
641+
return response.data!.cast<String>();
642+
}
643+
644+
/// Reset separator tokens of the index.
645+
Future<Task> resetNonSeparatorTokens() async {
646+
return await _getTask(
647+
http.deleteMethod('/indexes/$uid/settings/non-separator-tokens'),
648+
);
649+
}
650+
651+
/// Update separator tokens of the index.
652+
Future<Task> updateNonSeparatorTokens(List<String> nonSeparatorTokens) async {
653+
return await _getTask(
654+
http.putMethod(
655+
'/indexes/$uid/settings/non-separator-tokens',
656+
data: nonSeparatorTokens,
657+
),
658+
);
659+
}
660+
611661
/// Get searchable attributes of the index.
612662
Future<List<String>> getSearchableAttributes() async {
613663
final response = await http.getMethod<List<Object?>>(

lib/src/settings/index_settings.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class IndexSettings {
1515
this.typoTolerance,
1616
this.pagination,
1717
this.faceting,
18+
this.separatorTokens,
19+
this.nonSeparatorTokens,
1820
});
1921

2022
static const allAttributes = <String>['*'];
@@ -28,6 +30,12 @@ class IndexSettings {
2830
/// List of ranking rules sorted by order of importance
2931
List<String>? rankingRules;
3032

33+
/// List of tokens that will be considered as word separators by Meilisearch.
34+
List<String>? separatorTokens;
35+
36+
/// List of tokens that will not be considered as word separators by Meilisearch.
37+
List<String>? nonSeparatorTokens;
38+
3139
/// Attributes to use in [filters](https://www.meilisearch.com/docs/reference/api/search#filter)
3240
List<String>? filterableAttributes;
3341

@@ -64,6 +72,8 @@ class IndexSettings {
6472
'typoTolerance': typoTolerance?.toMap(),
6573
'pagination': pagination?.toMap(),
6674
'faceting': faceting?.toMap(),
75+
'separatorTokens': separatorTokens,
76+
'nonSeparatorTokens': nonSeparatorTokens
6777
};
6878

6979
factory IndexSettings.fromMap(Map<String, Object?> map) {
@@ -77,6 +87,8 @@ class IndexSettings {
7787
final searchableAttributes = map['searchableAttributes'];
7888
final displayedAttributes = map['displayedAttributes'];
7989
final sortableAttributes = map['sortableAttributes'];
90+
final separatorTokens = map['separatorTokens'];
91+
final nonSeparatorTokens = map['nonSeparatorTokens'];
8092

8193
return IndexSettings(
8294
synonyms: synonyms is Map<String, Object?>
@@ -109,6 +121,12 @@ class IndexSettings {
109121
: null,
110122
faceting:
111123
faceting is Map<String, Object?> ? Faceting.fromMap(faceting) : null,
124+
nonSeparatorTokens: nonSeparatorTokens is List<Object?>
125+
? nonSeparatorTokens.cast<String>()
126+
: null,
127+
separatorTokens: separatorTokens is List<Object?>
128+
? separatorTokens.cast<String>()
129+
: null,
112130
);
113131
}
114132
}

test/code_samples.dart

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -846,12 +846,33 @@ void main() {
846846

847847
// #docregion geosearch_guide_filter_usage_3
848848
await client.index('restaurants').search(
849-
'',
850-
SearchQuery(
849+
'',
850+
SearchQuery(
851851
filter:
852-
'_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])'));
852+
'_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])',
853+
),
854+
);
855+
// #enddocregion
856+
// #docregion get_separator_tokens_1
857+
await client.index('articles').getSeparatorTokens();
858+
// #enddocregion
859+
// #docregion update_separator_tokens_1
860+
await client.index('articles').updateSeparatorTokens(["|", "&hellip;"]);
861+
// #enddocregion
862+
// #docregion reset_separator_tokens_1
863+
await client.index('articles').resetSeparatorTokens();
864+
// #enddocregion
865+
// #docregion get_non_separator_tokens_1
866+
await client.index('articles').getNonSeparatorTokens();
867+
// #enddocregion
868+
// #docregion update_non_separator_tokens_1
869+
await client.index('articles').updateNonSeparatorTokens(["@", "#"]);
870+
// #enddocregion
871+
// #docregion reset_non_separator_tokens_1
872+
await client.index('articles').resetNonSeparatorTokens();
873+
// #enddocregion
853874
});
854-
// #enddocregion
875+
855876
// skip this test, since it's only used for generating code samples
856877
}, skip: true);
857878

test/settings_test.dart

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,122 @@ void main() {
149149
expect(resetRules, defaultRankingRules);
150150
});
151151

152+
group('separator tokens', () {
153+
Future<List<String>> doUpdate() async {
154+
final toUpdate = <String>['zz', 'ff'];
155+
var response =
156+
await index.updateSeparatorTokens(toUpdate).waitFor(client: client);
157+
158+
expect(response.status, "succeeded");
159+
return toUpdate;
160+
}
161+
162+
test("Get", () async {
163+
final initial = await index.getSeparatorTokens();
164+
final initialFromSettings =
165+
await index.getSettings().then((value) => value.separatorTokens);
166+
167+
expect(
168+
initial,
169+
equals(initialFromSettings),
170+
);
171+
});
172+
173+
test("Update", () async {
174+
final toUpdate = await doUpdate();
175+
176+
final afterUpdate = await index.getSeparatorTokens();
177+
final afterUpdateFromSettings =
178+
await index.getSettings().then((value) => value.separatorTokens);
179+
expect(
180+
afterUpdateFromSettings,
181+
unorderedEquals(toUpdate),
182+
);
183+
expect(
184+
afterUpdate,
185+
unorderedEquals(toUpdate),
186+
);
187+
});
188+
189+
test("Reset", () async {
190+
//first update, then reset
191+
await doUpdate();
192+
final response =
193+
await index.resetSeparatorTokens().waitFor(client: client);
194+
195+
expect(response.status, 'succeeded');
196+
final afterReset = await index.getSeparatorTokens();
197+
final afterResetFromSettings =
198+
await index.getSettings().then((value) => value.separatorTokens);
199+
expect(
200+
afterReset,
201+
equals(<String>[]),
202+
);
203+
expect(
204+
afterResetFromSettings,
205+
equals(<String>[]),
206+
);
207+
});
208+
});
209+
group('Non separator tokens', () {
210+
Future<List<String>> doUpdate() async {
211+
final toUpdate = <String>['/'];
212+
var response = await index
213+
.updateNonSeparatorTokens(toUpdate)
214+
.waitFor(client: client);
215+
216+
expect(response.status, "succeeded");
217+
return toUpdate;
218+
}
219+
220+
test("Get", () async {
221+
final initial = await index.getNonSeparatorTokens();
222+
final initialFromSettings =
223+
await index.getSettings().then((value) => value.nonSeparatorTokens);
224+
225+
expect(
226+
initial,
227+
equals(initialFromSettings),
228+
);
229+
});
230+
231+
test("Update", () async {
232+
final toUpdate = await doUpdate();
233+
234+
final afterUpdate = await index.getNonSeparatorTokens();
235+
final afterUpdateFromSettings =
236+
await index.getSettings().then((value) => value.nonSeparatorTokens);
237+
expect(
238+
afterUpdateFromSettings,
239+
unorderedEquals(toUpdate),
240+
);
241+
expect(
242+
afterUpdate,
243+
unorderedEquals(toUpdate),
244+
);
245+
});
246+
247+
test("Reset", () async {
248+
//first update, then reset
249+
await doUpdate();
250+
final response =
251+
await index.resetNonSeparatorTokens().waitFor(client: client);
252+
253+
expect(response.status, 'succeeded');
254+
final afterReset = await index.getNonSeparatorTokens();
255+
final afterResetFromSettings =
256+
await index.getSettings().then((value) => value.nonSeparatorTokens);
257+
expect(
258+
afterReset,
259+
equals(<String>[]),
260+
);
261+
expect(
262+
afterResetFromSettings,
263+
equals(<String>[]),
264+
);
265+
});
266+
});
267+
152268
test('Getting, setting, and deleting searchable attributes', () async {
153269
final updatedSearchableAttributes = ['title', 'id'];
154270
await index

0 commit comments

Comments
 (0)