diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml
index f14e4a27b..70b9d81bc 100644
--- a/.code-samples.meilisearch.yaml
+++ b/.code-samples.meilisearch.yaml
@@ -1,422 +1,410 @@
-# This code-samples file is used by the Meilisearch documentation
+# This code-samples file is used by the Meilisearch documentation.
# Every example written here will be automatically fetched by
-# the documentation on build
-# You can read more on https://github.com/meilisearch/documentation/tree/master/.vuepress/code-samples
+# the documentation on build.
+# You can read more at https://github.com/meilisearch/documentation
+# This file is generated, read more in CONTRIBUTING.md "Tests and Linter" section.
---
synonyms_guide_1: |-
- client.index('movies').updateSynonyms({
- 'great': ['fantastic'],
- 'fantastic': ['great']
- })
+ await client.index("movies").updateSynonyms({
+ great: ["fantastic"],
+ fantastic: ["great"],
+ });
date_guide_index_1: |-
- const games = require('./games.json')
- client.index('games').addDocuments(games).then((res) => console.log(res))
+ import games from "./games.json" with { type: "json" };
+ await client.index("games").addDocuments(games);
date_guide_filterable_attributes_1: |-
- client.index('games').updateFilterableAttributes(['release_timestamp'])
+ await client.index("games").updateFilterableAttributes(["release_timestamp"]);
date_guide_filter_1: |-
- client.index('games').search('', {
- filter: 'release_timestamp >= 1514761200 AND release_timestamp < 1672527600'
- })
+ await client.index("games").search("", {
+ filter: "release_timestamp >= 1514761200 AND release_timestamp < 1672527600",
+ });
date_guide_sortable_attributes_1: |-
- client.index('games').updateSortableAttributes(['release_timestamp'])
+ await client.index("games").updateSortableAttributes(["release_timestamp"]);
date_guide_sort_1: |-
- client.index('games').search('', {
- sort: ['release_timestamp:desc'],
- })
+ await client.index("games").search("", {
+ sort: ["release_timestamp:desc"],
+ });
get_one_index_1: |-
- client.index('movies').getRawInfo()
+ await client.index("movies").getRawInfo();
list_all_indexes_1: |-
- client.getIndexes({ limit: 3 })
+ await client.getIndexes({ limit: 3 });
create_an_index_1: |-
- client.createIndex('movies', { primaryKey: 'id' })
+ await client.createIndex("movies", { primaryKey: "id" });
update_an_index_1: |-
- client.updateIndex('movies', { primaryKey: 'id' })
+ await client.updateIndex("movies", { primaryKey: "id" });
delete_an_index_1: |-
- client.deleteIndex('movies')
+ await client.deleteIndex("movies");
swap_indexes_1: |-
- client.swapIndexes([
- { 'indexes': ['indexA', 'indexB'] },
- { 'indexes': ['indexX', 'indexY'] }
- ])
+ await client.swapIndexes([
+ { indexes: ["indexA", "indexB"] },
+ { indexes: ["indexX", "indexY"] },
+ ]);
get_one_document_1: |-
- client
- .index('movies')
- .getDocument(25684, { fields: ['id', 'title', 'poster', 'release_date'] })
+ await client
+ .index("movies")
+ .getDocument(25684, { fields: ["id", "title", "poster", "release_date"] });
get_documents_1: |-
- client.index('movies').getDocuments({
+ await client.index("movies").getDocuments({
limit: 2,
- filter: 'genres = action'
- })
+ filter: "genres = action",
+ });
get_documents_post_1: |-
- client.index('books').getDocuments({
- filter: '(rating > 3 AND (genres = Adventure OR genres = Fiction)) AND language = English',
- fields: ['title', 'genres', 'rating', 'language'],
- limit: 3
- })
+ await client.index("books").getDocuments({
+ filter:
+ "(rating > 3 AND (genres = Adventure OR genres = Fiction)) AND language = English",
+ fields: ["title", "genres", "rating", "language"],
+ limit: 3,
+ });
add_or_replace_documents_1: |-
- client.index('movies').addDocuments([{
+ await client.index("movies").addDocuments([
+ {
id: 287947,
- title: 'Shazam',
- poster: 'https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg',
- overview: 'A boy is given the ability to become an adult superhero in times of need with a single magic word.',
- release_date: '2019-03-23'
- }])
+ title: "Shazam",
+ poster: "https://image.tmdb.org/t/p/w1280/xnopI5Xtky18MPhK40cZAGAOVeV.jpg",
+ overview:
+ "A boy is given the ability to become an adult superhero in times of need with a single magic word.",
+ release_date: "2019-03-23",
+ },
+ ]);
add_or_update_documents_1: |-
- client.index('movies').updateDocuments([{
+ await client.index("movies").updateDocuments([
+ {
id: 287947,
- title: 'Shazam ⚡️',
- genres: 'comedy'
- }])
+ title: "Shazam ⚡️",
+ genres: "comedy",
+ },
+ ]);
delete_all_documents_1: |-
- client.index('movies').deleteAllDocuments()
+ await client.index("movies").deleteAllDocuments();
delete_one_document_1: |-
- client.index('movies').deleteDocument(25684)
+ await client.index("movies").deleteDocument(25684);
delete_documents_by_batch_1: |-
- client.index('movies').deleteDocuments([23488, 153738, 437035, 363869])
+ await client.index("movies").deleteDocuments([23488, 153738, 437035, 363869]);
delete_documents_by_filter_1: |-
- client.index('movies').deleteDocuments({
- filter: 'genres = action OR genres = adventure'
- })
+ await client.index("movies").deleteDocuments({
+ filter: "genres = action OR genres = adventure",
+ });
search_post_1: |-
- client.index('movies').search('American ninja')
+ await client.index("movies").search("American ninja");
search_get_1: |-
- client.index('movies').searchGet('American ninja')
+ await client.index("movies").searchGet("American ninja");
multi_search_1: |-
- client.multiSearch({ queries: [
- {
- indexUid: 'movies',
- q: 'pooh',
- limit: 5,
- },
- {
- indexUid: 'movies',
- q: 'nemo',
- limit: 5,
- },
- {
- indexUid: 'movie_ratings',
- q: 'us',
- },
- ]})
+ await client.multiSearch({
+ queries: [
+ {
+ indexUid: "movies",
+ q: "pooh",
+ limit: 5,
+ },
+ {
+ indexUid: "movies",
+ q: "nemo",
+ limit: 5,
+ },
+ {
+ indexUid: "movie_ratings",
+ q: "us",
+ },
+ ],
+ });
get_all_tasks_1: |-
- client.tasks.getTasks()
+ await client.tasks.getTasks();
get_task_1: |-
- client.tasks.getTask(1)
+ await client.tasks.getTask(1);
async_guide_filter_by_date_1: |-
- client.tasks.getTasks({ afterEnqueuedAt: '2020-10-11T11:49:53.000Z' })
+ await client.tasks.getTasks({
+ afterEnqueuedAt: "2020-10-11T11:49:53.000Z",
+ });
async_guide_multiple_filters_1: |-
- client.tasks.getTasks({
- indexUids: ['movies'],
- types: ['documentAdditionOrUpdate','documentDeletion'],
- statuses: ['processing']
- })
+ await client.tasks.getTasks({
+ indexUids: ["movies"],
+ types: ["documentAdditionOrUpdate", "documentDeletion"],
+ statuses: ["processing"],
+ });
async_guide_filter_by_ids_1: |-
- client.tasks.getTasks({ uids: [5, 10, 13] })
+ await client.tasks.getTasks({ uids: [5, 10, 13] });
async_guide_filter_by_statuses_1: |-
- client.tasks.getTasks({ statuses: ['failed', 'canceled'] })
+ await client.tasks.getTasks({
+ statuses: ["failed", "canceled"],
+ });
async_guide_filter_by_types_1: |-
- client.tasks.getTasks({ types: ['dumpCreation', 'indexSwap'] })
+ await client.tasks.getTasks({
+ types: ["dumpCreation", "indexSwap"],
+ });
async_guide_filter_by_index_uids_1: |-
- client.tasks.getTasks({ indexUids: ['movies'] })
+ await client.tasks.getTasks({ indexUids: ["movies"] });
get_all_tasks_paginating_1: |-
- client.tasks.getTasks({ limit: 2, from: 10 })
+ await client.tasks.getTasks({ limit: 2, from: 10 });
get_all_tasks_paginating_2: |-
- client.tasks.getTasks({ limit: 2, from: 8 })
+ await client.tasks.getTasks({ limit: 2, from: 8 });
async_guide_canceled_by_1: |-
- client.tasks.getTasks({ canceledBy: [9, 15] })
+ await client.tasks.getTasks({ canceledBy: [9, 15] });
delete_tasks_1: |-
- client.tasks.deleteTasks({ uids: [1, 2] })
+ await client.tasks.deleteTasks({ uids: [1, 2] });
cancel_tasks_1: |-
- client.tasks.cancelTasks({ uids: [1, 2] })
+ await client.tasks.cancelTasks({ uids: [1, 2] });
get_one_key_1: |-
- client.getKey('6062abda-a5aa-4414-ac91-ecd7944c0f8d')
+ await client.getKey("6062abda-a5aa-4414-ac91-ecd7944c0f8d");
get_all_keys_1: |-
- client.getKeys({ limit: 3 })
+ await client.getKeys({ limit: 3 });
create_a_key_1: |-
- client.createKey({
- description: 'Add documents: Products API key',
- actions: ['documents.add'],
- indexes: ['products'],
- expiresAt: '2021-11-13T00:00:00Z'
- })
+ await client.createKey({
+ description: "Add documents: Products API key",
+ actions: ["documents.add"],
+ indexes: ["products"],
+ expiresAt: new Date("2021-11-13T00:00:00Z"),
+ });
update_a_key_1: |-
- client.updateKey('6062abda-a5aa-4414-ac91-ecd7944c0f8d', {
- name: 'Products/Reviews API key',
- description: 'Manage documents: Products/Reviews API key',
- })
+ await client.updateKey("6062abda-a5aa-4414-ac91-ecd7944c0f8d", {
+ name: "Products/Reviews API key",
+ description: "Manage documents: Products/Reviews API key",
+ });
delete_a_key_1: |-
- client.deleteKey('6062abda-a5aa-4414-ac91-ecd7944c0f8d')
+ await client.deleteKey("6062abda-a5aa-4414-ac91-ecd7944c0f8d");
get_settings_1: |-
- client.index('movies').getSettings()
+ await client.index("movies").getSettings();
update_settings_1: |-
- client.index('movies').updateSettings({
- rankingRules: [
- 'words',
- 'typo',
- 'proximity',
- 'attribute',
- 'sort',
- 'exactness',
- 'release_date:desc',
- 'rank:desc'
- ],
- distinctAttribute: 'movie_id',
- searchableAttributes: [
- 'title',
- 'overview',
- 'genres'
- ],
- displayedAttributes: [
- 'title',
- 'overview',
- 'genres',
- 'release_date'
- ],
- stopWords: [
- 'the',
- 'a',
- 'an'
- ],
- sortableAttributes: [
- 'title',
- 'release_date'
- ],
- synonyms: {
- 'wolverine': ['xmen', 'logan'],
- 'logan': ['wolverine']
- },
- typoTolerance: {
- 'minWordSizeForTypos': {
- 'oneTypo': 8,
- 'twoTypos': 10
- },
- 'disableOnAttributes': [
- 'title'
- ]
- },
- pagination: {
- maxTotalHits: 5000
- },
- faceting: {
- maxValuesPerFacet: 200
+ await client.index("movies").updateSettings({
+ rankingRules: [
+ "words",
+ "typo",
+ "proximity",
+ "attribute",
+ "sort",
+ "exactness",
+ "release_date:desc",
+ "rank:desc",
+ ],
+ distinctAttribute: "movie_id",
+ searchableAttributes: ["title", "overview", "genres"],
+ displayedAttributes: ["title", "overview", "genres", "release_date"],
+ stopWords: ["the", "a", "an"],
+ sortableAttributes: ["title", "release_date"],
+ synonyms: {
+ wolverine: ["xmen", "logan"],
+ logan: ["wolverine"],
+ },
+ typoTolerance: {
+ minWordSizeForTypos: {
+ oneTypo: 8,
+ twoTypos: 10,
},
- searchCutoffMs: 150
- })
+ disableOnAttributes: ["title"],
+ },
+ pagination: {
+ maxTotalHits: 5000,
+ },
+ faceting: {
+ maxValuesPerFacet: 200,
+ },
+ searchCutoffMs: 150,
+ });
reset_settings_1: |-
- client.index('movies').resetSettings()
+ await client.index("movies").resetSettings();
get_synonyms_1: |-
- client.index('movies').getSynonyms()
+ await client.index("movies").getSynonyms();
update_synonyms_1: |-
- client.index('movies').updateSynonyms({
- wolverine: ['xmen', 'logan'],
- logan: ['wolverine', 'xmen'],
- wow: ['world of warcraft']
- })
+ await client.index("movies").updateSynonyms({
+ wolverine: ["xmen", "logan"],
+ logan: ["wolverine", "xmen"],
+ wow: ["world of warcraft"],
+ });
reset_synonyms_1: |-
- client.index('movies').resetSynonyms()
+ await client.index("movies").resetSynonyms();
get_stop_words_1: |-
- client.index('movies').getStopWords()
+ await client.index("movies").getStopWords();
update_stop_words_1: |-
- client.index('movies').updateStopWords(['of', 'the', 'to'])
+ await client.index("movies").updateStopWords(["of", "the", "to"]);
reset_stop_words_1: |-
- client.index('movies').resetStopWords()
+ await client.index("movies").resetStopWords();
get_ranking_rules_1: |-
- client.index('movies').getRankingRules()
+ await client.index("movies").getRankingRules();
update_ranking_rules_1: |-
- client.index('movies').updateRankingRules([
- 'words',
- 'typo',
- 'proximity',
- 'attribute',
- 'sort',
- 'exactness',
- 'release_date:asc',
- 'rank:desc'
- ])
+ await client
+ .index("movies")
+ .updateRankingRules([
+ "words",
+ "typo",
+ "proximity",
+ "attribute",
+ "sort",
+ "exactness",
+ "release_date:asc",
+ "rank:desc",
+ ]);
reset_ranking_rules_1: |-
- client.index('movies').resetRankingRules()
+ await client.index("movies").resetRankingRules();
get_distinct_attribute_1: |-
- client.index('shoes').getDistinctAttribute()
+ await client.index("shoes").getDistinctAttribute();
update_distinct_attribute_1: |-
- client.index('shoes').updateDistinctAttribute('skuid')
+ await client.index("shoes").updateDistinctAttribute("skuid");
reset_distinct_attribute_1: |-
- client.index('shoes').resetDistinctAttribute()
+ await client.index("shoes").resetDistinctAttribute();
get_searchable_attributes_1: |-
- client.index('movies').getSearchableAttributes()
+ await client.index("movies").getSearchableAttributes();
update_searchable_attributes_1: |-
- client.index('movies').updateSearchableAttributes([
- 'title',
- 'overview',
- 'genres'
- ])
+ await client
+ .index("movies")
+ .updateSearchableAttributes(["title", "overview", "genres"]);
reset_searchable_attributes_1: |-
- client.index('movies').resetSearchableAttributes()
+ await client.index("movies").resetSearchableAttributes();
get_displayed_attributes_1: |-
- client.index('movies').getDisplayedAttributes()
+ await client.index("movies").getDisplayedAttributes();
update_displayed_attributes_1: |-
- client.index('movies').updateDisplayedAttributes([
- 'title',
- 'overview',
- 'genres',
- 'release_date'
- ])
+ await client
+ .index("movies")
+ .updateDisplayedAttributes(["title", "overview", "genres", "release_date"]);
reset_displayed_attributes_1: |-
- client.index('movies').resetDisplayedAttributes()
+ await client.index("movies").resetDisplayedAttributes();
get_typo_tolerance_1: |-
- client.index('books').getTypoTolerance()
+ await client.index("books").getTypoTolerance();
update_typo_tolerance_1: |-
- client.index('books').updateTypoTolerance({
+ await client.index("books").updateTypoTolerance({
minWordSizeForTypos: {
- oneTypo: 4,
- twoTypos: 10
- },
- disableOnAttributes: [
- 'title'
- ]
- })
+ oneTypo: 4,
+ twoTypos: 10,
+ },
+ disableOnAttributes: ["title"],
+ });
reset_typo_tolerance_1: |-
- client.index('books').resetTypoTolerance()
+ await client.index("books").resetTypoTolerance();
get_index_stats_1: |-
- client.index('movies').getStats()
+ await client.index("movies").getStats();
get_indexes_stats_1: |-
- client.getStats()
+ await client.getStats();
get_health_1: |-
- client.health()
+ await client.health();
get_version_1: |-
- client.getVersion()
+ await client.getVersion();
distinct_attribute_guide_1: |-
- client.index('jackets').updateDistinctAttribute('product_id')
+ await client.index("jackets").updateDistinctAttribute("product_id");
field_properties_guide_searchable_1: |-
- client.index('movies').updateSearchableAttributes([
- 'title',
- 'overview',
- 'genres',
- ]
- )
+ await client
+ .index("movies")
+ .updateSearchableAttributes(["title", "overview", "genres"]);
field_properties_guide_displayed_1: |-
- client.index('movies').updateDisplayedAttributes([
- 'title',
- 'overview',
- 'genres',
- 'release_date',
- ]
- )
+ await client
+ .index("movies")
+ .updateDisplayedAttributes(["title", "overview", "genres", "release_date"]);
filtering_guide_1: |-
- client.index('movie_ratings').search('Avengers', {
- filter: 'release_date > 795484800'
- })
+ await client.index("movie_ratings").search("Avengers", {
+ filter: "release_date > 795484800",
+ });
filtering_guide_2: |-
- client.index('movie_ratings').search('Batman', {
- filter: 'release_date > 795484800 AND (director = "Tim Burton" OR director = "Christopher Nolan")'
- })
+ await client.index("movie_ratings").search("Batman", {
+ filter:
+ 'release_date > 795484800 AND (director = "Tim Burton" OR director = "Christopher Nolan")',
+ });
filtering_guide_3: |-
- client.index('movie_ratings').search('Planet of the Apes', {
- filter: "release_date > 1577884550 AND (NOT director = \"Tim Burton\")"
- })
+ await client.index("movie_ratings").search("Planet of the Apes", {
+ filter: 'release_date > 1577884550 AND (NOT director = "Tim Burton")',
+ });
filtering_guide_nested_1: |-
- client.index('movie_ratings').search('thriller', {
- filter: 'rating.users >= 90'
- })
+ await client.index("movie_ratings").search("thriller", {
+ filter: "rating.users >= 90",
+ });
search_parameter_guide_query_1: |-
- client.index('movies').search('shifu')
+ await client.index("movies").search("shifu");
search_parameter_guide_offset_1: |-
- client.index('movies').search('shifu', {
- offset: 1
- })
+ await client.index("movies").search("shifu", {
+ offset: 1,
+ });
search_parameter_guide_limit_1: |-
- client.index('movies').search('shifu', {
- limit: 2
- })
+ await client.index("movies").search("shifu", {
+ limit: 2,
+ });
search_parameter_guide_retrieve_1: |-
- client.index('movies').search('shifu', {
- attributesToRetrieve: ['overview', 'title']
- })
+ await client.index("movies").search("shifu", {
+ attributesToRetrieve: ["overview", "title"],
+ });
search_parameter_guide_crop_1: |-
- client.index('movies').search('shifu', {
- attributesToCrop: ['overview'],
- cropLength: 5
- })
+ await client.index("movies").search("shifu", {
+ attributesToCrop: ["overview"],
+ cropLength: 5,
+ });
search_parameter_guide_crop_marker_1: |-
- client.index('movies').search('shifu', {
- attributesToCrop: ['overview'],
- cropMarker: '[…]'
- })
+ await client.index("movies").search("shifu", {
+ attributesToCrop: ["overview"],
+ cropMarker: "[…]",
+ });
search_parameter_guide_highlight_1: |-
- client.index('movies').search('winter feast', {
- attributesToHighlight: ['overview']
- })
+ await client.index("movies").search("winter feast", {
+ attributesToHighlight: ["overview"],
+ });
search_parameter_guide_highlight_tag_1: |-
- client.index('movies').search('winter feast', {
- attributesToHighlight: ['overview'],
+ await client.index("movies").search("winter feast", {
+ attributesToHighlight: ["overview"],
highlightPreTag: '',
- highlightPostTag: ''
- })
+ highlightPostTag: "",
+ });
search_parameter_guide_show_matches_position_1: |-
- client.index('movies').search('winter feast', {
- showMatchesPosition: true
- })
+ await client.index("movies").search("winter feast", {
+ showMatchesPosition: true,
+ });
search_parameter_guide_matching_strategy_1: |-
- client.index('movies').search('big fat liar', {
- matchingStrategy: 'last'
- })
+ await client.index("movies").search("big fat liar", {
+ matchingStrategy: "last",
+ });
search_parameter_guide_matching_strategy_2: |-
- client.index('movies').search('big fat liar', {
- matchingStrategy: 'all'
- })
+ await client.index("movies").search("big fat liar", {
+ matchingStrategy: "all",
+ });
search_parameter_guide_hitsperpage_1: |-
- client.index('movies').search('', {
- hitsPerPage: 15
- })
+ await client.index("movies").search("", {
+ hitsPerPage: 15,
+ });
search_parameter_guide_page_1: |-
- client.index('movies').search('', {
- page: 2
- })
+ await client.index("movies").search("", {
+ page: 2,
+ });
search_parameter_guide_show_ranking_score_1: |-
- client.index('movies').search('dragon', {
- showRankingScore: true
- })
+ await client.index("movies").search("dragon", {
+ showRankingScore: true,
+ });
search_parameter_guide_attributes_to_search_on_1: |-
- client.index('movies').search('adventure', {
- attributesToSearchOn: ['overview']
- })
+ await client.index("movies").search("adventure", {
+ attributesToSearchOn: ["overview"],
+ });
typo_tolerance_guide_1: |-
- client.index('movies').updateTypoTolerance({
- enabled: false
- })
+ await client.index("movies").updateTypoTolerance({
+ enabled: false,
+ });
typo_tolerance_guide_2: |-
- client.index('movies').updateTypoTolerance({
- disableOnAttributes: ['title']
- })
+ await client.index("movies").updateTypoTolerance({
+ disableOnAttributes: ["title"],
+ });
typo_tolerance_guide_3: |-
- client.index('movies').updateTypoTolerance({
- disableOnWords: ['shrek']
- })
+ await client.index("movies").updateTypoTolerance({
+ disableOnWords: ["shrek"],
+ });
typo_tolerance_guide_4: |-
- client.index('movies').updateTypoTolerance({
+ await client.index("movies").updateTypoTolerance({
minWordSizeForTypos: {
oneTypo: 4,
- twoTypos: 10
- }
- })
+ twoTypos: 10,
+ },
+ });
add_movies_json_1: |-
- const movies = require('./movies.json')
- client.index('movies').addDocuments(movies).then((res) => console.log(res))
+ import movies from "./movies.json" with { type: "json" };
+ const task = await client.index("movies").addDocuments(movies);
+ console.log(task);
primary_field_guide_update_document_primary_key: |-
- client.updateIndex('books', {
- primaryKey: 'title'
- })
+ await client.updateIndex("books", { primaryKey: "title" });
primary_field_guide_create_index_primary_key: |-
- client.createIndex('books', { primaryKey: 'reference_number' })
+ await client.createIndex("books", { primaryKey: "reference_number" });
primary_field_guide_add_document_primary_key: |-
- client.index('books').addDocuments([
- {
- reference_number: 287947,
- title: 'Diary of a Wimpy Kid',
- author: 'Jeff Kinney',
- genres: ['comedy','humor'],
- price: 5.00
- }
- ], { primaryKey: 'reference_number' })
+ await client.index("books").addDocuments(
+ [
+ {
+ reference_number: 287947,
+ title: "Diary of a Wimpy Kid",
+ author: "Jeff Kinney",
+ genres: ["comedy", "humor"],
+ price: 5.0,
+ },
+ ],
+ { primaryKey: "reference_number" },
+ );
getting_started_add_documents: |-
// With npm:
// npm install meilisearch
@@ -425,397 +413,427 @@ getting_started_add_documents: |-
// yarn add meilisearch
// In your .js file:
+ import { MeiliSearch } from "meilisearch";
+ import movies from "./movies.json" with { type: "json" };
+
// With the `require` syntax:
- const { MeiliSearch } = require('meilisearch')
- const movies = require('./movies.json')
- // With the `import` syntax:
- import { MeiliSearch } from 'meilisearch'
- import movies from './movies.json'
+ // const { MeiliSearch } = require("meilisearch");
+ // const movies = require("./movies.json");
const client = new MeiliSearch({
- host: 'http://localhost:7700',
- apiKey: 'aSampleMasterKey'
- })
- client.index('movies').addDocuments(movies)
- .then((res) => console.log(res))
+ host: "http://localhost:7700",
+ apiKey: "aSampleMasterKey",
+ });
+
+ const task = await client.index("movies").addDocuments(movies);
+ console.log(task);
getting_started_search: |-
- client.index('movies').search('botman').then((res) => console.log(res))
+ const response = await client.index("movies").search("botman");
+
+ console.log(response);
getting_started_update_ranking_rules: |-
- client.index('movies').updateRankingRules([
- 'exactness',
- 'words',
- 'typo',
- 'proximity',
- 'attribute',
- 'sort',
- 'release_date:asc',
- 'rank:desc'
- ])
+ await client
+ .index("movies")
+ .updateRankingRules([
+ "exactness",
+ "words",
+ "typo",
+ "proximity",
+ "attribute",
+ "sort",
+ "release_date:asc",
+ "rank:desc",
+ ]);
getting_started_update_searchable_attributes: |-
- client.index('movies').updateSearchableAttributes([
- 'title'
- ])
+ await client.index("movies").updateSearchableAttributes(["title"]);
getting_started_update_stop_words: |-
- client.index('movies').updateStopWords(['the'])
+ await client.index("movies").updateStopWords(["the"]);
getting_started_check_task_status: |-
- client.tasks.getTask(0)
+ await client.tasks.getTask(0);
getting_started_synonyms: |-
- client.index('movies').updateSynonyms({
- winnie: ['piglet'],
- piglet: ['winnie']
- })
+ await client.index("movies").updateSynonyms({
+ winnie: ["piglet"],
+ piglet: ["winnie"],
+ });
getting_started_update_displayed_attributes: |-
- client.index('movies').updateDisplayedAttributes([
- 'title',
- 'overview',
- 'poster'
- ])
+ await client
+ .index("movies")
+ .updateDisplayedAttributes(["title", "overview", "poster"]);
getting_started_add_meteorites: |-
- const meteorites = require('./meteorites.json')
+ import meteorites from "./meteorites.json" with { type: "json" };
- client.index('meteorites').addDocuments(meteorites)
+ await client.index("meteorites").addDocuments(meteorites);
getting_started_configure_settings: |-
- client.index('meteorites').updateSettings({
- filterableAttributes: ['mass', '_geo'],
- sortableAttributes: ['mass', '_geo']
- })
+ await client.index("meteorites").updateSettings({
+ filterableAttributes: ["mass", "_geo"],
+ sortableAttributes: ["mass", "_geo"],
+ });
getting_started_geo_radius: |-
- client.index('meteorites').search('', { filter: '_geoRadius(46.9480, 7.4474, 210000)' })
+ await client
+ .index("meteorites")
+ .search("", { filter: "_geoRadius(46.9480, 7.4474, 210000)" });
getting_started_geo_point: |-
- client.index('meteorites').search('', { sort: ['_geoPoint(48.8583701, 2.2922926):asc'] })
+ await client
+ .index("meteorites")
+ .search("", { sort: ["_geoPoint(48.8583701, 2.2922926):asc"] });
getting_started_sorting: |-
- client.index('meteorites').search('', {
- sort: ['mass:asc'],
- filter: 'mass < 200'
- })
+ await client.index("meteorites").search("", {
+ sort: ["mass:asc"],
+ filter: "mass < 200",
+ });
getting_started_faceting: |-
- client.index('movies').updateFaceting({
+ await client.index("movies").updateFaceting({
maxValuesPerFacet: 2,
sortFacetValuesBy: {
- '*': 'count'
- }
- })
+ "*": "count",
+ },
+ });
getting_started_typo_tolerance: |-
- client.index('movies').updateTypoTolerance({
+ await client.index("movies").updateTypoTolerance({
minWordSizeForTypos: {
- oneTypo: 4
- }
- })
+ oneTypo: 4,
+ },
+ });
getting_started_filtering: |-
- client.index('meteorites').search('', { filter: 'mass < 200' })
+ await client.index("meteorites").search("", { filter: "mass < 200" });
getting_started_pagination: |-
- client.index('movies').updatePagination({ maxTotalHits: 500 })
+ await client.index("movies").updatePagination({ maxTotalHits: 500 });
get_filterable_attributes_1: |-
- client.index('movies').getFilterableAttributes()
+ await client.index("movies").getFilterableAttributes();
update_filterable_attributes_1: |-
- client.index('movies')
- .updateFilterableAttributes([
- "genres",
- {
- attributePatterns: ["genre"],
- features: {
- facetSearch: true,
- filter: { equality: true, comparison: false },
- },
- }
- ])
+ await client.index("movies").updateFilterableAttributes([
+ "genres",
+ {
+ attributePatterns: ["genre"],
+ features: {
+ facetSearch: true,
+ filter: { equality: true, comparison: false },
+ },
+ },
+ ]);
reset_filterable_attributes_1: |-
- client.index('movies').resetFilterableAttributes()
+ await client.index("movies").resetFilterableAttributes();
filtering_update_settings_1: |-
- client.index('movies')
- .updateFilterableAttributes([
- 'director',
- 'genres'
- ])
+ await client.index("movies").updateFilterableAttributes(["director", "genres"]);
faceted_search_walkthrough_filter_1: |-
- client.index('movies')
- .search('thriller', {
- filter: [['genres = Horror', 'genres = Mystery'], 'director = "Jordan Peele"']
- })
+ await client.index("movies").search("thriller", {
+ filter: [
+ ["genres = Horror", "genres = Mystery"],
+ 'director = "Jordan Peele"',
+ ],
+ });
faceted_search_update_settings_1: |-
- client.index('movie_ratings').updateFilterableAttributes(['genres', 'rating', 'language'])
+ await client
+ .index("movie_ratings")
+ .updateFilterableAttributes(["genres", "rating", "language"]);
faceted_search_1: |-
- client.index('books').search('classic', { facets: ['genres', 'rating', 'language'] })
+ await client
+ .index("books")
+ .search("classic", { facets: ["genres", "rating", "language"] });
post_dump_1: |-
- client.createDump()
+ await client.createDump();
create_snapshot_1: |-
- client.createSnapshot()
+ await client.createSnapshot();
phrase_search_1: |-
- client.index('movies')
- .search('"african american" horror')
+ await client.index("movies").search('"african american" horror');
sorting_guide_update_sortable_attributes_1: |-
- client.index('books').updateSortableAttributes([
- 'author',
- 'price'
- ])
+ await client.index("books").updateSortableAttributes(["author", "price"]);
sorting_guide_update_ranking_rules_1: |-
- client.index('books').updateRankingRules([
- 'words',
- 'sort',
- 'typo',
- 'proximity',
- 'attribute',
- 'exactness'
- ])
+ await client
+ .index("books")
+ .updateRankingRules([
+ "words",
+ "sort",
+ "typo",
+ "proximity",
+ "attribute",
+ "exactness",
+ ]);
sorting_guide_sort_parameter_1: |-
- client.index('books').search('science fiction', {
- sort: ['price:asc'],
- })
+ await client.index("books").search("science fiction", {
+ sort: ["price:asc"],
+ });
sorting_guide_sort_parameter_2: |-
- client.index('books').search('butler', {
- sort: ['author:desc'],
- })
+ await client.index("books").search("butler", {
+ sort: ["author:desc"],
+ });
sorting_guide_sort_nested_1: |-
- client.index('books').search('science fiction', {
- 'sort': ['rating.users:asc'],
- })
+ await client.index("books").search("science fiction", {
+ sort: ["rating.users:asc"],
+ });
get_sortable_attributes_1: |-
- client.index('books').getSortableAttributes()
+ await client.index("books").getSortableAttributes();
update_sortable_attributes_1: |-
- client.index('books')
- .updateSortableAttributes([
- 'price',
- 'author'
- ])
+ await client.index("books").updateSortableAttributes(["price", "author"]);
reset_sortable_attributes_1: |-
- client.index('books').resetSortableAttributes()
+ await client.index("books").resetSortableAttributes();
get_pagination_settings_1: |-
- client.index('books').getPagination()
+ await client.index("books").getPagination();
update_pagination_settings_1: |-
- client.index('books').updateSettings({ pagination: { maxTotalHits: 100 }})
+ await client
+ .index("books")
+ .updateSettings({ pagination: { maxTotalHits: 100 } });
reset_pagination_settings_1: |-
- client.index('books').resetPagination()
+ await client.index("books").resetPagination();
get_faceting_settings_1: |-
- client.index('books').getFaceting()
+ await client.index("books").getFaceting();
update_faceting_settings_1: |-
- client.index('books').updateFaceting({
- maxValuesPerFacet: 2
+ await client.index("books").updateFaceting({
+ maxValuesPerFacet: 2,
sortFacetValuesBy: {
- '*': 'alpha',
- genres: 'count'
- }
- })
+ "*": "alpha",
+ genres: "count",
+ },
+ });
reset_faceting_settings_1: |-
- client.index('books').resetFaceting()
+ await client.index("books").resetFaceting();
get_dictionary_1: |-
- client.index('books').getDictionary()
+ await client.index("books").getDictionary();
update_dictionary_1: |-
- client.index('books').updateDictionary(['J. R. R.', 'W. E. B.'])
+ await client.index("books").updateDictionary(["J. R. R.", "W. E. B."]);
reset_dictionary_1: |-
- client.index('books').resetDictionary()
+ await client.index("books").resetDictionary();
search_parameter_guide_sort_1: |-
- client.index('books').search('science fiction', {
- sort: ['price:asc'],
- })
+ await client.index("books").search("science fiction", {
+ sort: ["price:asc"],
+ });
get_separator_tokens_1: |-
- client.index('books').getSeparatorTokens()
+ await client.index("books").getSeparatorTokens();
update_separator_tokens_1: |-
- client.index('books').updateSeparatorTokens(['|', '…'])
+ await client.index("books").updateSeparatorTokens(["|", "…"]);
reset_separator_tokens_1: |-
- client.index('books').resetSeparatorTokens()
+ await client.index("books").resetSeparatorTokens();
get_non_separator_tokens_1: |-
- client.index('books').getNonSeparatorTokens()
+ await client.index("books").getNonSeparatorTokens();
update_non_separator_tokens_1: |-
- client.index('books').updateNonSeparatorTokens(['@', '#'])
+ await client.index("books").updateNonSeparatorTokens(["@", "#"]);
reset_non_separator_tokens_1: |-
- client.index('books').resetNonSeparatorTokens()
+ await client.index("books").resetNonSeparatorTokens();
get_proximity_precision_settings_1: |-
- client.index('books').getProximityPrecision()
+ await client.index("books").getProximityPrecision();
update_proximity_precision_settings_1: |-
- client.index('books').updateProximityPrecision('byAttribute')
+ await client.index("books").updateProximityPrecision("byAttribute");
reset_proximity_precision_settings_1: |-
- client.index('books').resetProximityPrecision()
+ await client.index("books").resetProximityPrecision();
get_search_cutoff_1: |-
- client.index('movies').getSearchCutoffMs()
+ await client.index("movies").getSearchCutoffMs();
update_search_cutoff_1: |-
- client.index('movies').updateSearchCutoffMs(150)
+ await client.index("movies").updateSearchCutoffMs(150);
reset_search_cutoff_1: |-
- client.index('movies').resetSearchCutoffMs()
+ await client.index("movies").resetSearchCutoffMs();
search_parameter_guide_facet_stats_1: |-
- client.index('movie_ratings').search('Batman', { facets: ['genres', 'rating'] })
+ await client
+ .index("movie_ratings")
+ .search("Batman", { facets: ["genres", "rating"] });
geosearch_guide_filter_settings_1: |-
- client.index('restaurants')
- .updateFilterableAttributes([
- '_geo'
- ])
+ await client.index("restaurants").updateFilterableAttributes(["_geo"]);
geosearch_guide_filter_usage_1: |-
- client.index('restaurants').search('', {
- filter: ['_geoRadius(45.472735, 9.184019, 2000)'],
- })
+ await client.index("restaurants").search("", {
+ filter: ["_geoRadius(45.472735, 9.184019, 2000)"],
+ });
geosearch_guide_filter_usage_2: |-
- client.index('restaurants').search('', {
- filter: ['_geoRadius(45.472735, 9.184019, 2000) AND type = pizza'],
- })
+ await client.index("restaurants").search("", {
+ filter: ["_geoRadius(45.472735, 9.184019, 2000) AND type = pizza"],
+ });
geosearch_guide_filter_usage_3: |-
- client.index('restaurants').search('', {
- filter: ['_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])'],
- })
+ await client.index("restaurants").search("", {
+ filter: ["_geoBoundingBox([45.494181, 9.214024], [45.449484, 9.179175])"],
+ });
geosearch_guide_sort_settings_1: |-
- client.index('restaurants').updateSortableAttributes([
- '_geo'
- ])
+ await client.index("restaurants").updateSortableAttributes(["_geo"]);
geosearch_guide_sort_usage_1: |-
- client.index('restaurants').search('', {
- sort: ['_geoPoint(48.8561446, 2.2978204):asc'],
- })
+ await client.index("restaurants").search("", {
+ sort: ["_geoPoint(48.8561446, 2.2978204):asc"],
+ });
geosearch_guide_sort_usage_2: |-
- client.index('restaurants').search('', {
- sort: ['_geoPoint(48.8561446, 2.2978204):asc', 'rating:desc'],
- })
+ await client.index("restaurants").search("", {
+ sort: ["_geoPoint(48.8561446, 2.2978204):asc", "rating:desc"],
+ });
security_guide_search_key_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'apiKey' })
- client.index('patient_medical_records').search()
+ const client = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "apiKey",
+ });
+
+ await client.index("patient_medical_records").search();
security_guide_update_key_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
- client.updateKey('74c9c733-3368-4738-bbe5-1d18a5fecb37', {
- description: 'Default Search API Key'
- })
+ const client = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "masterKey",
+ });
+
+ await client.updateKey("74c9c733-3368-4738-bbe5-1d18a5fecb37", {
+ description: "Default Search API Key",
+ });
security_guide_create_key_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
- client.createKey({
- description: 'Search patient records key',
- actions: ['search'],
- indexes: ['patient_medical_records'],
- expiresAt: '2023-01-01T00:00:00Z'
- })
+ const client = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "masterKey",
+ });
+
+ await client.createKey({
+ description: "Search patient records key",
+ actions: ["search"],
+ indexes: ["patient_medical_records"],
+ expiresAt: new Date("2023-01-01T00:00:00Z"),
+ });
security_guide_list_keys_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
- client.getKeys()
+ await client.getKeys();
security_guide_delete_key_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
- client.deleteKey('ac5cd97d-5a4b-4226-a868-2d0eb6d197ab')
+ const client = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "masterKey",
+ });
+
+ await client.deleteKey("ac5cd97d-5a4b-4226-a868-2d0eb6d197ab");
authorization_header_1: |-
- const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
- client.getKeys()
+ await client.getKeys();
tenant_token_guide_generate_sdk_1: |-
- import { generateTenantToken } from 'meilisearch/token'
-
- const searchRules = {
- patient_medical_records: {
- filter: 'user_id = 1'
- }
- }
- const apiKey = 'B5KdX2MY2jV6EXfUs6scSfmC...'
- const apiKeyUid = '85c3c2f9-bdd6-41f1-abd8-11fcf80e0f76'
- const expiresAt = new Date('2025-12-20') // optional
+ import { generateTenantToken } from "meilisearch/token";
- const token = await generateTenantToken({ apiKey, apiKeyUid, searchRules, expiresAt })
+ await generateTenantToken({
+ apiKey: "B5KdX2MY2jV6EXfUs6scSfmC...",
+ apiKeyUid: "85c3c2f9-bdd6-41f1-abd8-11fcf80e0f76",
+ searchRules: { patient_medical_records: { filter: "user_id = 1" } },
+ expiresAt: new Date("2025-12-20"), // optional
+ });
tenant_token_guide_search_sdk_1: |-
- const frontEndClient = new MeiliSearch({ host: 'http://localhost:7700', apiKey: token })
- frontEndClient.index('patient_medical_records').search('blood test')
+ const frontEndClient = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "",
+ });
+
+ await frontEndClient.index("patient_medical_records").search("blood test");
landing_getting_started_1: |-
- const client = new MeiliSearch('http://localhost:7700', 'masterKey')
+ const client = new MeiliSearch({
+ host: "http://localhost:7700",
+ apiKey: "masterKey",
+ });
- await client.index('movies').addDocuments([
- { 'id': 1, 'title': 'Carol' },
- { 'id': 2, 'title': 'Wonder Woman' },
- { 'id': 3, 'title': 'Life of Pi' },
- { 'id': 4, 'title': 'Mad Max: Fury Road' },
- { 'id': 5, 'title': 'Moana' },
- { 'id': 6, 'title': 'Philadelphia'}
- ])
+ await client.index("movies").addDocuments([
+ { id: 1, title: "Carol" },
+ { id: 2, title: "Wonder Woman" },
+ { id: 3, title: "Life of Pi" },
+ { id: 4, title: "Mad Max: Fury Road" },
+ { id: 5, title: "Moana" },
+ { id: 6, title: "Philadelphia" },
+ ]);
// be aware this client is using the masterKey, it should not be used in front end
- const search = await index.search('philodelphia')
- console.log(search)
+ const search = await client.index("movies").search("philodelphia");
+ console.log(search);
facet_search_1: |-
- client.index('books').searchForFacetValues({
- facetQuery: 'fiction',
- facetName: 'genres'
- filter: 'rating > 3'
- })
+ await client.index("books").searchForFacetValues({
+ facetQuery: "fiction",
+ facetName: "genres",
+ filter: "rating > 3",
+ });
facet_search_2: |-
- client.index('books').updateFaceting({
+ await client.index("books").updateFaceting({
sortFacetValuesBy: {
- genres: 'count'
- }
- })
+ genres: "count",
+ },
+ });
facet_search_3: |-
- client.index('books').searchForFacetValues({
- facetQuery: 'c',
- facetName: 'genres'
- })
+ await client.index("books").searchForFacetValues({
+ facetQuery: "c",
+ facetName: "genres",
+ });
search_parameter_guide_show_ranking_score_details_1: |-
- client.index('movies').search('dragon', { showRankingScoreDetails: true })
+ await client
+ .index("movies")
+ .search("dragon", { showRankingScoreDetails: true });
negative_search_1: |-
- client.index('movies').search('-escape')
+ await client.index("movies").search("-escape");
negative_search_2: |-
- client.index('movies').search('-"escape"')
+ await client.index("movies").search('-"escape"');
search_parameter_reference_ranking_score_threshold_1: |-
- client.index('INDEX_NAME').search('badman', { rankingScoreThreshold: 0.2 })
+ await client
+ .index("INDEX_NAME")
+ .search("badman", { rankingScoreThreshold: 0.2 });
search_parameter_reference_retrieve_vectors_1: |-
- client.index('INDEX_NAME').search('kitchen utensils', {
+ await client.index("INDEX_NAME").search("kitchen utensils", {
retrieveVectors: true,
hybrid: {
- embedder: 'EMBEDDER_NAME'
- }
- })
+ embedder: "EMBEDDER_NAME",
+ },
+ });
search_parameter_guide_hybrid_1: |-
- client.index('INDEX_NAME').search('kitchen utensils', {
+ await client.index("INDEX_NAME").search("kitchen utensils", {
hybrid: {
semanticRatio: 0.9,
- embedder: 'EMBEDDER_NAME'
- }
- })
+ embedder: "EMBEDDER_NAME",
+ },
+ });
get_similar_post_1: |-
- client.index('INDEX_NAME').searchSimilarDocuments({ id: 'TARGET_DOCUMENT_ID', embedder: 'default' })
+ await client
+ .index("INDEX_NAME")
+ .searchSimilarDocuments({ id: "TARGET_DOCUMENT_ID", embedder: "default" });
search_parameter_guide_matching_strategy_3: |-
- client.index('movies').search('white shirt', {
- matchingStrategy: 'frequency'
- })
+ await client.index("movies").search("white shirt", {
+ matchingStrategy: "frequency",
+ });
search_parameter_reference_distinct_1: |-
- client.index('INDEX_NAME').search('QUERY TERMS', { distinct: 'ATTRIBUTE_A' })
+ await client
+ .index("INDEX_NAME")
+ .search("QUERY TERMS", { distinct: "ATTRIBUTE_A" });
distinct_attribute_guide_filterable_1: |-
- client.index('products').updateFilterableAttributes(['product_id', 'sku', 'url'])
+ await client
+ .index("products")
+ .updateFilterableAttributes(["product_id", "sku", "url"]);
distinct_attribute_guide_distinct_parameter_1: |-
- client.index('products').search('white shirt', { distinct: 'sku' })
+ await client.index("products").search("white shirt", { distinct: "sku" });
multi_search_federated_1: |-
- client.multiSearch({
+ await client.multiSearch({
federation: {},
queries: [
{
- indexUid: 'movies',
- q: 'batman',
+ indexUid: "movies",
+ q: "batman",
},
{
- indexUid: 'comics',
- q: 'batman',
+ indexUid: "comics",
+ q: "batman",
},
- ]
- })
+ ],
+ });
search_parameter_reference_locales_1: |-
- client.index('INDEX_NAME').search('QUERY TEXT IN JAPANESE', { locales: ['jpn'] })
+ await client
+ .index("INDEX_NAME")
+ .search("QUERY TEXT IN JAPANESE", { locales: ["jpn"] });
get_localized_attribute_settings_1: |-
- client.index('INDEX_NAME').getLocalizedAttributes()
+ await client.index("INDEX_NAME").getLocalizedAttributes();
update_localized_attribute_settings_1: |-
- client.index('INDEX_NAME').updateLocalizedAttributes([
- { attributePatterns: ['*_ja'], locales: ['jpn'] },
- ])
+ await client
+ .index("INDEX_NAME")
+ .updateLocalizedAttributes([
+ { attributePatterns: ["*_ja"], locales: ["jpn"] },
+ ]);
reset_localized_attribute_settings_1: |-
- client.index('INDEX_NAME').resetLocalizedAttributes()
+ await client.index("INDEX_NAME").resetLocalizedAttributes();
get_facet_search_settings_1: |-
- client.index('INDEX_NAME').getFacetSearch();
+ await client.index("INDEX_NAME").getFacetSearch();
update_facet_search_settings_1: |-
- client.index('INDEX_NAME').updateFacetSearch(false);
+ await client.index("INDEX_NAME").updateFacetSearch(false);
reset_facet_search_settings_1: |-
- client.index('INDEX_NAME').resetFacetSearch();
+ await client.index("INDEX_NAME").resetFacetSearch();
get_prefix_search_settings_1: |-
- client.index('INDEX_NAME').getPrefixSearch();
+ await client.index("INDEX_NAME").getPrefixSearch();
update_prefix_search_settings_1: |-
- client.index('INDEX_NAME').updatePrefixSearch('disabled');
+ await client.index("INDEX_NAME").updatePrefixSearch("disabled");
reset_prefix_search_settings_1: |-
- client.index('INDEX_NAME').resetPrefixSearch();
+ await client.index("INDEX_NAME").resetPrefixSearch();
get_all_batches_1: |-
- client.batches.getBatches();
+ await client.batches.getBatches();
get_batch_1: |-
- client.batches.getBatch(BATCH_UID);
-# Vector search
+ await client.batches.getBatch(123);
update_embedders_1: |-
- client.index('INDEX_NAME').updateEmbedders({
+ await client.index("INDEX_NAME").updateEmbedders({
default: {
- source: 'openAi',
- apiKey: 'OPEN_AI_API_KEY',
- model: 'text-embedding-3-small',
- documentTemplate: 'A document titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}'
- }
+ source: "openAi",
+ apiKey: "OPEN_AI_API_KEY",
+ model: "text-embedding-3-small",
+ documentTemplate:
+ "A document titled '{{doc.title}}' whose description starts with {{doc.overview|truncatewords: 20}}",
+ },
});
diff --git a/.gitignore b/.gitignore
index 868fe3fb0..4ee31bb32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -133,3 +133,4 @@ package
dist_default_export_in_index
no_default_export_in_index
playgrounds/javascript/yarn.lock
+generated-code-samples
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index aea3406bf..071853847 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -70,6 +70,25 @@ yarn style:fix
yarn build
```
+### Code samples
+
+In this repository, code samples are linted and type-checked. To achieve this,
+we generate TypeScript files from `.code-samples.meilisearch.yaml` and vice
+versa.
+
+> [!WARNING]
+>
+> Each of these commands overwrite their target files, so use them carefully.
+
+```bash
+# Generate all the code sample files from YAML file
+yarn generate-code-sample-files
+# Generate YAML file from all the code sample files
+yarn generate-code-samples-yaml
+# Generate all + new code sample files from YAML file
+yarn generate-code-sample-files new_sample_one new_sample_two
+```
+
## Git Guidelines
### Git Branches
diff --git a/package.json b/package.json
index 4121006e3..03d9304e5 100644
--- a/package.json
+++ b/package.json
@@ -44,7 +44,7 @@
"build": "vite build && tsc -p tsconfig.build.json && vite --mode production-umd build",
"postbuild": "node scripts/build.js",
"test": "vitest run --coverage",
- "types": "tsc -p tsconfig.json --noEmit",
+ "types": "yarn generate-code-sample-files && tsc -p tsconfig.json --noEmit",
"types:watch": "yarn types --watch",
"test:env:browser": "yarn build && node scripts/copy-umd-file.js --to ./tests/env/express/public && yarn --cwd tests/env/express && yarn --cwd tests/env/express test",
"test:watch": "vitest watch",
@@ -55,12 +55,14 @@
"test:env:nodejs": "yarn build && node tests/env/node/index.cjs && node tests/env/node/getting_started.cjs",
"test:env:esm": "yarn --cwd tests/env/esm && yarn --cwd tests/env/esm start",
"test:env:nitro-app": "yarn build && yarn --cwd tests/env/nitro-app test",
+ "generate-code-sample-files": "node scripts/code-samples.js from-yaml",
+ "generate-code-samples-yaml": "node scripts/code-samples.js to-yaml",
"fmt": "prettier -c ./**/*.{js,ts}",
"fmt:fix": "prettier -w ./**/*.{js,ts}",
"lint": "eslint",
"lint:fix": "eslint --fix",
- "style": "yarn fmt && yarn lint",
- "style:fix": "yarn fmt:fix && yarn lint:fix",
+ "style": "yarn generate-code-sample-files && prettier --ignore-path=.prettierignore -c generated-code-samples && yarn fmt && yarn lint",
+ "style:fix": "yarn generate-code-sample-files && prettier --ignore-path=.prettierignore -c generated-code-samples && yarn fmt:fix && yarn lint:fix",
"prepare": "husky"
},
"files": [
@@ -70,22 +72,24 @@
],
"devDependencies": {
"@eslint/js": "^9.23.0",
- "@vitest/coverage-v8": "^3.1.1",
+ "@types/js-yaml": "^4.0.9",
"@types/node": "^22.15.3",
"@typescript-eslint/utils": "^8.29.0",
+ "@vitest/coverage-v8": "^3.1.1",
"@vitest/eslint-plugin": "^1.1.38",
"eslint": "^9.25.1",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-tsdoc": "^0.4.0",
- "typescript": "^5.8.3",
- "vite": "^6.3.4",
"globals": "^16.0.0",
"husky": "^9.1.7",
+ "js-yaml": "^4.1.0",
"lint-staged": "15.5.1",
"prettier": "^3.5.3",
"prettier-plugin-jsdoc": "^1.3.2",
"typedoc": "^0.28.3",
+ "typescript": "^5.8.3",
"typescript-eslint": "^8.31.1",
+ "vite": "^6.3.4",
"vitest": "^3.1.1"
},
"packageManager": "yarn@1.22.22"
diff --git a/scripts/code-samples.js b/scripts/code-samples.js
new file mode 100644
index 000000000..a1868e2bb
--- /dev/null
+++ b/scripts/code-samples.js
@@ -0,0 +1,11 @@
+import { argv } from "node:process";
+
+if (argv[2] === "to-yaml" && argv.length === 3) {
+ await import("./code-samples/to-yaml.js");
+} else if (argv[2] === "from-yaml") {
+ await import("./code-samples/from-yaml.js");
+} else {
+ throw new Error(
+ "expected `to-yaml` (+ new code samples names) or `from-yaml` as arguments",
+ );
+}
diff --git a/scripts/code-samples/from-yaml.js b/scripts/code-samples/from-yaml.js
new file mode 100644
index 000000000..5adc76fa2
--- /dev/null
+++ b/scripts/code-samples/from-yaml.js
@@ -0,0 +1,80 @@
+import { argv } from "node:process";
+import { writeFileSync, mkdirSync } from "node:fs";
+import {
+ generatedCodeSamplesDir,
+ iterateCodeSamples,
+ delimiter,
+} from "./shared.js";
+
+const headerImport = 'import { MeiliSearch } from "meilisearch";\n';
+const headerClientDeclaration =
+ 'const client = new MeiliSearch({ host: "http://127.0.0.1:7700" });\n';
+const headerComment =
+ "// Code below this line will be written to code samples YAML file\n" +
+ '// For more information consult CONTRIBUTING.md "Tests and Linter" section\n' +
+ delimiter +
+ "\n";
+
+const jsonFilesToGenerate = ["games", "movies", "meteorites"];
+
+try {
+ mkdirSync(generatedCodeSamplesDir);
+} catch (error) {
+ if (error.code !== "EEXIST") {
+ throw error;
+ }
+}
+
+// generate JSON files used by samples, so type check passes
+for (const jsonFileToGenerate of jsonFilesToGenerate) {
+ writeFileSync(
+ new URL(jsonFileToGenerate + ".json", generatedCodeSamplesDir),
+ "[]\n",
+ );
+}
+
+const clientVarRegExp = /(?<=const|let ).+(?= = new MeiliSearch\()/;
+
+let generatedFileTally = 0;
+
+for (const { sampleName, code } of iterateCodeSamples()) {
+ let header = "";
+
+ const clientVarMatch = code.match(clientVarRegExp);
+ const clientVarLiteral = clientVarMatch?.[0] ?? "client";
+ const clientVarUsageRegExp = new RegExp(`${clientVarLiteral}\\s*\\.`);
+
+ // if there is client usage in the code sample
+ if (clientVarUsageRegExp.test(code)) {
+ // generate import if there isn't already one
+ if (!code.includes('from "meilisearch";\n')) {
+ header += headerImport;
+ }
+
+ // generate client declaration if there isn't already one
+ if (clientVarMatch === null) {
+ header += headerClientDeclaration;
+ }
+ }
+
+ header += headerComment;
+
+ writeFileSync(
+ new URL(sampleName + ".ts", generatedCodeSamplesDir),
+ header + code + "\n",
+ );
+
+ generatedFileTally += 1;
+}
+
+// generate additional files from arguments passed
+for (const sampleName of argv.slice(3)) {
+ writeFileSync(
+ new URL(sampleName + ".ts", generatedCodeSamplesDir),
+ headerImport + headerClientDeclaration + headerComment,
+ );
+
+ generatedFileTally += 1;
+}
+
+console.log(`generated ${generatedFileTally} code sample file(s)`);
diff --git a/scripts/code-samples/shared.js b/scripts/code-samples/shared.js
new file mode 100644
index 000000000..922e4f3bb
--- /dev/null
+++ b/scripts/code-samples/shared.js
@@ -0,0 +1,59 @@
+import { readFileSync } from "node:fs";
+import { load } from "js-yaml";
+
+export const codeSamplesPath = new URL(
+ "../../.code-samples.meilisearch.yaml",
+ import.meta.url,
+);
+
+export const generatedCodeSamplesDir = new URL(
+ "../../generated-code-samples/",
+ import.meta.url,
+);
+
+export const delimiter = "// -~-~-~-~-";
+
+export function* iterateCodeSamples() {
+ let codeSamplesContents;
+ try {
+ codeSamplesContents = readFileSync(codeSamplesPath, {
+ encoding: "utf-8",
+ });
+ } catch (error) {
+ if (error?.code !== "ENOENT") {
+ throw error;
+ }
+
+ return;
+ }
+
+ const codeSamples = load(codeSamplesContents, {
+ filename: codeSamplesPath.href,
+ onWarning: console.warn,
+ });
+
+ // YAML file is empty
+ if (codeSamples === undefined) {
+ return;
+ }
+
+ if (codeSamples === null || typeof codeSamples !== "object") {
+ throw new Error(
+ `expected YAML contents to be of type \`Record\`; got ${String(codeSamples)}`,
+ {
+ cause: codeSamples,
+ },
+ );
+ }
+
+ for (const [sampleName, code] of Object.entries(codeSamples)) {
+ if (typeof code !== "string") {
+ throw new Error(
+ `expected YAML contents to be of type \`Record\`; at ${sampleName} got ${String(code)}`,
+ { cause: code },
+ );
+ }
+
+ yield { sampleName, code };
+ }
+}
diff --git a/scripts/code-samples/to-yaml.js b/scripts/code-samples/to-yaml.js
new file mode 100644
index 000000000..03be665c9
--- /dev/null
+++ b/scripts/code-samples/to-yaml.js
@@ -0,0 +1,101 @@
+import { readdir } from "node:fs/promises";
+import { readFileSync, writeFileSync } from "node:fs";
+import { parse, join } from "node:path";
+import {
+ codeSamplesPath,
+ generatedCodeSamplesDir,
+ iterateCodeSamples,
+ delimiter,
+} from "./shared.js";
+
+const codeSampleNamesFromYaml = Array.from(
+ iterateCodeSamples(),
+ (v) => v.sampleName,
+);
+
+/** @type {import("node:fs").Dirent[]} */
+const dirEntries = await readdir(generatedCodeSamplesDir, {
+ withFileTypes: true,
+}).catch((error) => {
+ if (error?.code !== "ENOENT") {
+ throw error;
+ }
+
+ return [];
+});
+
+if (dirEntries.length === 0) {
+ throw new Error(
+ `there are no code sample files at ${generatedCodeSamplesDir.href}\n` +
+ "tip: first generate them from the YAML file, consult CONTRIBUTING.md on how to use this script",
+ );
+}
+
+function throwError() {
+ throw new Error(
+ `expected generated code samples directory at ${generatedCodeSamplesDir.href} to only contain TypeScript and JSON files`,
+ { cause: dirEntries },
+ );
+}
+
+const manipulatedCodeSamples = dirEntries
+ .map((dirEnt) => {
+ if (!dirEnt.isFile()) {
+ throwError();
+ }
+
+ const { ext, name } = parse(dirEnt.name);
+ if (ext !== ".ts" && ext !== ".json") {
+ throwError();
+ }
+
+ if (ext === ".json") {
+ return null;
+ }
+
+ const codeSampleContent = readFileSync(
+ join(dirEnt.parentPath, dirEnt.name),
+ { encoding: "utf-8" },
+ );
+
+ const splitContent = codeSampleContent.split("\n");
+ const indexOfDelimiter = splitContent.findIndex((v) => v === delimiter);
+
+ const indentedContent = splitContent
+ // get rid of code before delimiter
+ .slice(indexOfDelimiter === -1 ? 0 : indexOfDelimiter + 1)
+ // add padding
+ .map((v) => (v === "" ? v : " " + v))
+ .join("\n")
+ .trimEnd();
+
+ // get position in current code samples YAML file, to be able to order it the same way
+ const index = codeSampleNamesFromYaml.indexOf(name);
+
+ return { name, indentedContent, index };
+ })
+ .filter((v) => v !== null)
+ .sort(({ index: indexA }, { index: indexB }) => indexA - indexB);
+
+// for every new code sample, place them at the end of the file instead of the start
+if (manipulatedCodeSamples.some((v) => v.index !== -1)) {
+ while (manipulatedCodeSamples.at(0)?.index === -1) {
+ manipulatedCodeSamples.push(manipulatedCodeSamples.shift());
+ }
+}
+
+const serializedCodeSamples = manipulatedCodeSamples
+ .map(({ name, indentedContent }) => name + ": |-\n" + indentedContent)
+ .join("\n");
+
+const header =
+ "# This code-samples file is used by the Meilisearch documentation.\n" +
+ "# Every example written here will be automatically fetched by\n" +
+ "# the documentation on build.\n" +
+ "# You can read more at https://github.com/meilisearch/documentation\n" +
+ '# This file is generated, read more in CONTRIBUTING.md "Tests and Linter" section.\n' +
+ "---\n";
+
+writeFileSync(codeSamplesPath, header + serializedCodeSamples + "\n");
+
+console.log(`generated ${manipulatedCodeSamples.length} code sample(s)`);
diff --git a/tsconfig.json b/tsconfig.json
index 2c9559fc9..0bb66c7e7 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -8,6 +8,12 @@
"lib": ["ESNext", "DOM", "DOM.Iterable"],
"resolveJsonModule": true,
"strict": true,
- "verbatimModuleSyntax": true
+ "verbatimModuleSyntax": true,
+ // For testing purposes
+ // TODO: Should use this for tests as well perhaps, resolve.alias
+ "paths": {
+ "meilisearch": ["./src/index.ts"],
+ "meilisearch/token": ["./src/token.ts"]
+ }
}
}
diff --git a/yarn.lock b/yarn.lock
index 827be91b8..3f010e7cc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -539,6 +539,11 @@
dependencies:
"@types/unist" "*"
+"@types/js-yaml@^4.0.9":
+ version "4.0.9"
+ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2"
+ integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==
+
"@types/json-schema@^7.0.15":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"