Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changeset/first-version.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ First version of `meili`, the Meilisearch CLI built for coding agents.
- Tasks: `meili get tasks`, narrowed by `--ids`, `--statuses`, `--types`, `--index-ids`, `--batch-ids`, `--canceled-by` and the date filters of the route, paging with `--limit` and `--from` and following the `next` cursor with `--all`; `meili cancel tasks` and `meili delete tasks --yes`, which take the same filters and answer a task.
- Search: `meili search --index <index> --q <query>`, on `POST /indexes/{index_uid}/search`, with every non-experimental search parameter of the route as a flag, from `--filter` and `--sort` to `--hybrid` and `--vector`; `--data` or `--file` carries a whole search body, which a flag of the same field overrides. `meili multi-search --queries '<json>'`, on `POST /multi-search`, runs several queries in one request, each naming its index, answered side by side or merged into one ranked list with `--federation`.
- Similar documents: `meili similar --index <index> --id <document> --embedder <embedder>`, on `POST /indexes/{index_uid}/similar`, returns the documents of the index closest to one of them, narrowed by `--filter`, `--limit` and `--offset`; `--data` or `--file` carries a whole body, which a flag of the same field overrides.
- Facet values: `meili facet-search --index <index> --facet-name <attribute>`, on `POST /indexes/{index_uid}/facet-search`, searches the values of one filterable attribute with `--facet-query` and counts them on the documents `--q` and `--filter` keep; `--data` or `--file` carries a whole body, which a flag of the same field overrides.
- Settings: `meili get settings --index <index>`, which returns every setting with its current value or its default; `meili update settings --index <index>`, with one flag per setting, from `--searchable-attributes` and `--stop-words` to `--typo-tolerance` and `--embedders`, where a value of `null` resets that one setting and `--data` or `--file` carries a whole settings body; `meili delete settings --index <index> --yes`, which resets them all.
- `meili schema` prints the index of the command tree as JSON, one entry per command with its routes, and `meili schema --command "get indexes"` prints one command in full, with its key actions and whether it returns a task.
- Connection through `--project-url` and `--project-api-key`, or `MEILI_PROJECT_URL` and `MEILI_PROJECT_API_KEY`; `MEILI_MANAGEMENT_TOKEN` and `MEILI_MANAGEMENT_URL` for the Management API.
Expand Down
3 changes: 2 additions & 1 deletion docs/contract/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Every API command declares its routes, `static routes = ["GET /indexes", "GET /i
7. **Values.** A scalar is passed as it is. A boolean is a bare flag, `--retrieve-vectors`, unless the route also reads `false` from it, as the settings do: it then takes its value, `--facet-search false`, because a bare flag says neither `false` nor `null`. An array of scalars is comma-separated, `--fields id,title`, as the API's own GET syntax. An object or a nested array is JSON text, `--typo-tolerance '{"enabled":false}'`. The value `null` sends a JSON null, `--expires-at null`, `--stop-words null`.
8. **Body input.** On every route with a body, `--file <path>` or `--data '<json>'` replaces the body fields; `--file -` reads stdin. Path and query flags stay valid next to them. A body-field flag given together with `--file` or `--data` overrides that field, as a flag overrides its environment variable. When a route's body is not an object of named fields but the value itself, the array of identifiers of `delete documents --ids` or the documents of `add documents`, the body is that value, and its shape selects the route among the ones the command covers: `delete documents --data '[1,2]'` deletes by identifiers, `--data '{"filter":…}'` deletes by filter. Documents are sent as JSON, the only content type the document declares.
9. **Routes that are not implemented.** The `GET` twin of a `POST` route that takes the same parameters in a body (search, similar, the list of documents); the unit route of a resource whose list filters by identifiers (documents, tasks, batches); the settings sub-routes, since `update settings` sends any subset and `null` resets one setting; `GET /api/v2/meilisearch-versions`. Each is recorded without command in the exceptions.
10. **Experimental routes** are out of the contract until the feature is stable. Implementing one is a contract change: an exception row with the reason. `compact` is the one exception today. A body field or a query parameter that an experimental feature gates is out of the contract the same way: the command declares no flag for it, and `--data` or `--file` still carries it to the API. `useNetwork` on `get documents`, and `media`, `personalize`, `useNetwork` and `inlineRule` on `search`. These stay out of the exceptions table, which lists routes.
10. **Experimental routes** are out of the contract until the feature is stable. Implementing one is a contract change: an exception row with the reason. `compact` is the one exception today. A body field or a query parameter that an experimental feature gates is out of the contract the same way: the command declares no flag for it, and `--data` or `--file` still carries it to the API. `useNetwork` on `get documents`, `media`, `personalize`, `useNetwork` and `inlineRule` on `search`, and `media` and `useNetwork` on `facet-search`. These stay out of the exceptions table, which lists routes.
11. **Destructive commands.** A command of the verb `delete` takes `--yes` and refuses to run without it: `cli_usage`, exit 2, before any network call. `--yes` is a flag to write, never a question the CLI asks, see `output.md`.

| Routes | Command |
Expand All @@ -47,6 +47,7 @@ Every API command declares its routes, `static routes = ["GET /indexes", "GET /i
| `POST …/documents/delete-batch`, `POST …/documents/delete`, `DELETE …/documents` | `meili delete documents --index <index> (--ids <ids> \| --filter <filter> \| --all) --yes` |
| `POST /indexes/{index_uid}/search` | `meili search --index <index> --q <query>` |
| `POST /indexes/{index_uid}/similar` | `meili similar --index <index> --id <document> --embedder <embedder>` |
| `POST /indexes/{index_uid}/facet-search` | `meili facet-search --index <index> --facet-name <attribute>` |
| `POST /multi-search` | `meili multi-search --queries <json> [--federation <json>]` |
| `GET /indexes/{index_uid}/settings` | `meili get settings --index <index>` |
| `PATCH /indexes/{index_uid}/settings` | `meili update settings --index <index> --<setting> <value>` |
Expand Down
304 changes: 304 additions & 0 deletions oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,310 @@
"tasks.js"
]
},
"facet-search": {
"aliases": [],
"args": {},
"description": "Search the values of one facet attribute of an index, counted on the documents --q and --filter keep.",
"examples": [
"<%= config.bin %> <%= command.id %> --index movies --facet-name genres --facet-query ac",
"<%= config.bin %> <%= command.id %> --index movies --facet-name genres --facet-query ac --output json",
"<%= config.bin %> <%= command.id %> --index movies --facet-name genres --q horror --filter 'rating > 4'",
"<%= config.bin %> <%= command.id %> --index movies --data '{\"facetName\":\"genres\",\"facetQuery\":\"ac\"}'"
],
"flags": {
"output": {
"char": "o",
"description": "json (default): one document, the API body as it is, indented in a terminal, compact when piped. ndjson: one item per line, list commands only, streams with --all.",
"name": "output",
"hasDynamicHelp": false,
"helpValue": "<mode>",
"multiple": false,
"options": [
"json",
"ndjson"
],
"type": "option"
},
"debug": {
"description": "Print every HTTP request and response on stderr, secrets redacted.",
"name": "debug",
"allowNo": false,
"type": "boolean"
},
"project-url": {
"description": "Project URL, the Meilisearch instance to talk to.",
"name": "project-url",
"hasDynamicHelp": false,
"helpValue": "<url>",
"multiple": false,
"type": "option"
},
"project-api-key": {
"description": "Project API key. `-` reads it from stdin.",
"name": "project-api-key",
"hasDynamicHelp": false,
"helpValue": "<key>",
"multiple": false,
"type": "option"
},
"project": {
"description": "A project of the config file. Cannot be combined with --project-url. Required when the file has several projects.",
"name": "project",
"hasDynamicHelp": false,
"helpValue": "<name>",
"multiple": false,
"type": "option"
},
"index": {
"description": "The index to search the facet values in.",
"name": "index",
"required": true,
"hasDynamicHelp": false,
"helpValue": "<index>",
"multiple": false,
"type": "option"
},
"facet-name": {
"description": "The facet attribute to search in. It must be one of the filterable attributes of the index.",
"name": "facet-name",
"hasDynamicHelp": false,
"helpValue": "<attribute>",
"multiple": false,
"type": "option"
},
"facet-query": {
"description": "The terms the facet values are matched against, the first word only. Omit it to return every value, up to 100.",
"name": "facet-query",
"hasDynamicHelp": false,
"helpValue": "<query>",
"multiple": false,
"type": "option"
},
"q": {
"description": "The search terms that narrow the documents the facet values are computed on, not the values themselves.",
"name": "q",
"hasDynamicHelp": false,
"helpValue": "<query>",
"multiple": false,
"type": "option"
},
"filter": {
"description": "Filter expression, for example `rating > 4`. Its array-of-arrays form goes through --data.",
"name": "filter",
"hasDynamicHelp": false,
"helpValue": "<filter>",
"multiple": false,
"type": "option"
},
"matching-strategy": {
"description": "How the terms of --q are relaxed when there are not enough results.",
"name": "matching-strategy",
"hasDynamicHelp": false,
"multiple": false,
"options": [
"last",
"all",
"frequency"
],
"type": "option"
},
"attributes-to-search-on": {
"description": "Restrict the search of --q to these searchable attributes, comma-separated.",
"name": "attributes-to-search-on",
"hasDynamicHelp": false,
"helpValue": "<fields>",
"multiple": false,
"type": "option"
},
"ranking-score-threshold": {
"description": "Count only the documents whose ranking score reaches this value, between 0.0 and 1.0.",
"name": "ranking-score-threshold",
"hasDynamicHelp": false,
"helpValue": "<number>",
"multiple": false,
"type": "option"
},
"locales": {
"description": "ISO-639 locales of the query, comma-separated, instead of auto-detection.",
"name": "locales",
"hasDynamicHelp": false,
"helpValue": "<locales>",
"multiple": false,
"type": "option"
},
"hybrid": {
"description": "Hybrid search as JSON, for example `{\"embedder\":\"default\",\"semanticRatio\":0.5}`.",
"name": "hybrid",
"hasDynamicHelp": false,
"helpValue": "<json>",
"multiple": false,
"type": "option"
},
"vector": {
"description": "Query vector for a user-provided embedder, comma-separated numbers.",
"name": "vector",
"hasDynamicHelp": false,
"helpValue": "<numbers>",
"multiple": false,
"type": "option"
},
"exhaustive-facet-count": {
"description": "Count the facet values exhaustively instead of estimating the counts.",
"name": "exhaustive-facet-count",
"allowNo": false,
"type": "boolean"
},
"file": {
"description": "Read the body from a file. `-` reads from stdin.",
"exclusive": [
"data"
],
"name": "file",
"hasDynamicHelp": false,
"helpValue": "<path>",
"multiple": false,
"type": "option"
},
"data": {
"description": "Inline JSON body.",
"name": "data",
"hasDynamicHelp": false,
"helpValue": "<json>",
"multiple": false,
"type": "option"
}
},
"hasDynamicHelp": false,
"hiddenAliases": [],
"id": "facet-search",
"pluginAlias": "@meilisearch/cli",
"pluginName": "@meilisearch/cli",
"pluginType": "core",
"strict": true,
"enableJsonFlag": false,
"api": "meilisearch",
"routes": [
"POST /indexes/{index_uid}/facet-search"
],
"keyActions": [
"search"
],
"connectionFlags": {
"project-url": {
"description": "Project URL, the Meilisearch instance to talk to.",
"helpValue": "<url>",
"input": [],
"multiple": false,
"type": "option"
},
"project-api-key": {
"description": "Project API key. `-` reads it from stdin.",
"helpValue": "<key>",
"input": [],
"multiple": false,
"type": "option"
},
"project": {
"description": "A project of the config file. Cannot be combined with --project-url. Required when the file has several projects.",
"helpValue": "<name>",
"input": [],
"multiple": false,
"type": "option"
}
},
"waitFlags": {
"wait": {
"description": "Poll the task until it reaches a final status, then print the final task.",
"allowNo": false,
"type": "boolean"
},
"timeout": {
"description": "Maximum wait time, for example 30s, 2m. Default 60s. Only with --wait.",
"helpValue": "<duration>",
"dependsOn": [
"wait"
],
"input": [],
"multiple": false,
"type": "option"
}
},
"paginationFlags": {
"limit": {
"description": "Passed to the API.",
"helpValue": "<n>",
"input": [],
"multiple": false,
"type": "option"
},
"offset": {
"description": "Passed to the API.",
"helpValue": "<n>",
"input": [],
"multiple": false,
"type": "option"
},
"all": {
"description": "Fetch every page. Streams with ndjson, buffers into one array with json.",
"allowNo": false,
"type": "boolean"
}
},
"fromPaginationFlags": {
"limit": {
"description": "Passed to the API.",
"helpValue": "<n>",
"input": [],
"multiple": false,
"type": "option"
},
"from": {
"description": "Passed to the API: the uid the page starts at, going down.",
"helpValue": "<uid>",
"input": [],
"multiple": false,
"type": "option"
},
"all": {
"description": "Fetch every page. Streams with ndjson, buffers into one array with json.",
"allowNo": false,
"type": "boolean"
}
},
"bodyInputFlags": {
"file": {
"description": "Read the body from a file. `-` reads from stdin.",
"helpValue": "<path>",
"exclusive": [
"data"
],
"input": [],
"multiple": false,
"type": "option"
},
"data": {
"description": "Inline JSON body.",
"helpValue": "<json>",
"input": [],
"multiple": false,
"type": "option"
}
},
"confirmFlags": {
"yes": {
"required": true,
"description": "Confirm the deletion. Nothing is sent to the API without it.",
"allowNo": false,
"type": "boolean"
}
},
"isESM": true,
"relativePath": [
"dist",
"commands",
"facet-search.js"
]
},
"get:documents": {
"aliases": [],
"args": {},
Expand Down
Loading
Loading