From 169845c3e5d6604d501b880aa136141f195532a1 Mon Sep 17 00:00:00 2001 From: Abdullah Kaya Date: Sat, 24 Oct 2026 12:00:48 +0300 Subject: [PATCH] feat(weaviate): add the Weaviate provider, read-only over its REST API Add the weaviate connection type. Studio browses a Weaviate server's collections with their properties and vectors, shows tenants and aliases in a collection's Source, and runs Weaviate's own REST read requests from a closed console of 17 routes: object reads, BM25, hybrid at alpha 0, near-vector and near-object searches, and aggregates. A search is written in the REST shape on every server. The provider sends it over REST search from 1.39.7 (near-vector from 1.39.8) and over GraphQL below, falls back once when a path is switched off, and shows the same columns and cell types on both paths. Tested on 1.40.2, 1.38.22 and 1.37.4, the line DigitalOcean Managed Weaviate runs. Every request is a read. Searches that would make the server send text to a model (near-text, generative, rerank, hybrid with alpha other than 0) are refused before anything is sent; a request naming a tenant that is not HOT is refused after reading the tenant's own record, so no read wakes a COLD tenant; an API key or OIDC token goes without TLS only to this machine or through an SSH tunnel. Register the type in every shared table, add the provider document, security control 3.25, six fixture servers with seeds, 17 captures with the harness that writes them, a live check and a REST/GraphQL parity check, unit, integration and end-to-end tests, and update every engine count and list in the docs, READMEs, chart, operator and listings. Closes #1566 --- CLAUDE.md | 4 +- DOCKERHUB.md | 9 +- README.md | 22 +- README_es.md | 7 +- README_hi.md | 5 +- README_ja.md | 5 +- README_ko.md | 15 +- README_pt.md | 7 +- README_ru.md | 7 +- README_ur.md | 5 +- README_zh.md | 17 +- charts/libredb-studio/Chart.yaml | 8 +- charts/libredb-studio/README.md | 4 +- database-compose.yml | 241 +- deploy/aws/listing/description.md | 2 +- deploy/aws/listing/listing-fields.md | 4 +- deploy/azure/listing/description.html | 4 +- deploy/azure/listing/listing-fields.md | 6 +- deploy/caprover/libredb-studio.yml | 6 +- .../digitalocean/assets/description-long.md | 4 +- deploy/koyeb/CATALOG_SUBMISSION.md | 2 +- deploy/railway/TEMPLATE_OVERVIEW.md | 4 +- deploy/railway/template.json | 2 +- deploy/rancher/CATALOG_LISTING.md | 22 +- deploy/rancher/app-readme.md | 4 +- deploy/rancher/pcsc-listing.html | 4 +- desktop/src-tauri/desktop-entry.hbs | 2 +- desktop/src-tauri/tauri.conf.json | 2 +- docker/weaviate/README.md | 100 + docker/weaviate/keys.sh | 34 + docker/weaviate/seed.py | 354 ++ docs/ADDING_A_PROVIDER.md | 12 +- docs/AGENT.md | 10 +- docs/AGENT_DATA_FLOW.md | 22 +- docs/AGENT_GUIDE.md | 10 +- docs/API_DOCS.md | 10 +- docs/ARCHITECTURE.md | 8 +- docs/BRAND_MESSAGING.md | 18 +- docs/DATABASE_PROVIDERS.md | 10 +- docs/FEATURES.md | 9 +- docs/MCP.md | 1 + docs/SCHEMA_DIFF.md | 2 +- docs/SECURITY.md | 24 +- docs/SEED_CONNECTIONS.md | 12 +- docs/editor/query-optimization.md | 4 +- docs/providers/README.md | 12 +- docs/providers/weaviate.md | 376 ++ e2e/weaviate-provider.spec.ts | 80 + ...studio-operator.clusterserviceversion.yaml | 10 +- ...studio-operator.clusterserviceversion.yaml | 10 +- .../helm-charts/libredb-studio/Chart.yaml | 8 +- operator/helm-charts/libredb-studio/README.md | 4 +- packaging/aur/.SRCINFO | 2 +- packaging/aur/PKGBUILD | 2 +- packaging/aur/README.md | 2 +- .../chocolatey/libredb-studio.nuspec.tmpl | 2 +- packaging/flatpak/org.libredb.Studio.desktop | 2 +- .../flatpak/org.libredb.Studio.metainfo.xml | 1 + packaging/flatpark/org.libredb.Studio.desktop | 2 +- .../flatpark/org.libredb.Studio.metainfo.xml | 1 + packaging/linux/nfpm.yaml | 4 +- .../LibreDB.Studio.locale.en-US.yaml.tmpl | 2 +- playwright.config.ts | 13 +- portainer-template.json | 2 +- scripts/security-check.mjs | 1 + snap/snapcraft.yaml | 2 +- src/components/QueryEditor.tsx | 1 + src/components/agent/AnswerCard.tsx | 8 + src/components/icons/db-icons.tsx | 25 + src/lib/agent/agent-manifest.ts | 1 + src/lib/db-showcase.ts | 31 +- src/lib/db-ui-config.ts | 6 + src/lib/db/compatibility.ts | 17 + src/lib/db/connection-fields.ts | 2 + src/lib/db/connection-form.ts | 19 + src/lib/db/connection-string/index.ts | 2 + src/lib/db/credential-warnings.ts | 11 + src/lib/db/destructive-commands.ts | 18 + src/lib/db/execution-ui/index.ts | 2 + src/lib/db/factory.ts | 9 +- src/lib/db/migration-ddl/index.ts | 2 + .../db/providers/vector/weaviate/client.ts | 120 + .../vector/weaviate/connection-options.ts | 200 ++ .../vector/weaviate/connection-string.ts | 8 + .../db/providers/vector/weaviate/errors.ts | 299 ++ .../db/providers/vector/weaviate/execute.ts | 309 ++ .../providers/vector/weaviate/execution-ui.ts | 8 + .../providers/vector/weaviate/generators.ts | 98 + .../db/providers/vector/weaviate/graphql.ts | 261 ++ src/lib/db/providers/vector/weaviate/guard.ts | 35 + src/lib/db/providers/vector/weaviate/index.ts | 383 ++ .../db/providers/vector/weaviate/labels.ts | 80 + .../vector/weaviate/migration-ddl.ts | 18 + .../vector/weaviate/monitoring-reads.ts | 50 + .../providers/vector/weaviate/monitoring.ts | 74 + .../db/providers/vector/weaviate/objects.ts | 332 ++ .../db/providers/vector/weaviate/request.ts | 682 ++++ .../providers/vector/weaviate/rest-client.ts | 198 ++ .../db/providers/vector/weaviate/results.ts | 466 +++ .../db/providers/vector/weaviate/routes.ts | 362 ++ .../db/providers/vector/weaviate/schema.ts | 326 ++ .../db/providers/vector/weaviate/source.ts | 121 + .../providers/vector/weaviate/sql-grammar.ts | 18 + .../providers/vector/weaviate/sql-writing.ts | 44 + .../db/providers/vector/weaviate/versions.ts | 95 + src/lib/db/query-dialects.ts | 11 +- src/lib/db/sql-grammar/index.ts | 2 + src/lib/db/sql-writing/index.ts | 2 + src/lib/db/types.ts | 5 + src/lib/editor/dialect-editors.ts | 10 + src/lib/editor/tab-language.ts | 1 + src/lib/query-generators.ts | 7 + src/lib/seed/types.ts | 1 + src/lib/sql/fence-tags.ts | 3 + src/lib/types.ts | 7 + src/styles/theme.css | 10 + tests/components/QueryEditor.test.tsx | 5 +- .../golden-dialect-outputs.json | 12 + tests/fixtures/weaviate/README.md | 32 + .../weaviate/weaviate-1-37/reads.json | 3088 ++++++++++++++++ .../weaviate/weaviate-1-37/searches.json | 1302 +++++++ .../weaviate/weaviate-1-37/surface.json | 1708 +++++++++ .../weaviate/weaviate-1-38/searches.json | 1296 +++++++ .../weaviate/weaviate-1-38/surface.json | 1708 +++++++++ .../weaviate/weaviate-auth/no-key.json | 44 + .../weaviate/weaviate-auth/reader.json | 600 ++++ .../fixtures/weaviate/weaviate-auth/root.json | 109 + .../weaviate/weaviate-auth/wrong-key.json | 46 + .../weaviate/weaviate-nographql/searches.json | 1293 +++++++ .../weaviate/weaviate-nographql/surface.json | 1708 +++++++++ .../weaviate/weaviate-tls/plain-to-tls.json | 44 + .../weaviate/weaviate-tls/reader.json | 201 ++ tests/fixtures/weaviate/weaviate/reads.json | 3113 +++++++++++++++++ .../fixtures/weaviate/weaviate/refusals.json | 121 + .../fixtures/weaviate/weaviate/searches.json | 1293 +++++++ tests/fixtures/weaviate/weaviate/surface.json | 1708 +++++++++ tests/helpers/census-connection.ts | 1 + tests/helpers/object-edit-expectation.ts | 3 + tests/helpers/weaviate-request-fixtures.ts | 116 + tests/helpers/weaviate-scenario.ts | 239 ++ tests/helpers/weaviate-surface.ts | 220 ++ tests/helpers/weaviate-wire.ts | 79 + .../integration/db/weaviate-provider.test.ts | 156 + tests/isolated/factory.test.ts | 33 +- tests/isolated/monaco-language-ids.test.ts | 5 +- .../object-column-declarations.test.ts | 3 +- .../object-source-declarations.test.ts | 17 +- tests/live/weaviate-evidence.ts | 126 + tests/live/weaviate-live-check.ts | 148 + tests/live/weaviate-path-parity.ts | 151 + tests/live/weaviate-scenarios.ts | 204 ++ tests/unit/db/compatibility.test.ts | 14 +- .../db/connection-form/golden/bigquery.txt | 1 + .../db/connection-form/golden/cassandra.txt | 1 + .../db/connection-form/golden/clickhouse.txt | 2 + .../db/connection-form/golden/couchbase.txt | 2 + .../db/connection-form/golden/databend.txt | 1 + tests/unit/db/connection-form/golden/db2.txt | 1 + .../unit/db/connection-form/golden/druid.txt | 1 + .../unit/db/connection-form/golden/duckdb.txt | 1 + .../connection-form/golden/elasticsearch.txt | 1 + tests/unit/db/connection-form/golden/etcd.txt | 1 + .../db/connection-form/golden/firestore.txt | 1 + .../db/connection-form/golden/influxdb.txt | 1 + .../db/connection-form/golden/influxdb3.txt | 1 + .../unit/db/connection-form/golden/kafka.txt | 1 + .../db/connection-form/golden/kubernetes.txt | 1 + .../db/connection-form/golden/libredb.txt | 1 + .../unit/db/connection-form/golden/libsql.txt | 2 + .../unit/db/connection-form/golden/milvus.txt | 1 + .../unit/db/connection-form/golden/modbus.txt | 1 + .../db/connection-form/golden/mongodb.txt | 2 + tests/unit/db/connection-form/golden/mqtt.txt | 1 + .../unit/db/connection-form/golden/mssql.txt | 2 + .../db/connection-form/golden/mtconnect.txt | 1 + .../unit/db/connection-form/golden/mysql.txt | 1 + .../unit/db/connection-form/golden/neo4j.txt | 1 + .../db/connection-form/golden/netconf.txt | 1 + .../unit/db/connection-form/golden/opcua.txt | 1 + .../db/connection-form/golden/opensearch.txt | 1 + .../unit/db/connection-form/golden/oracle.txt | 2 + tests/unit/db/connection-form/golden/oxia.txt | 1 + .../db/connection-form/golden/postgres.txt | 1 + .../db/connection-form/golden/prometheus.txt | 1 + .../unit/db/connection-form/golden/qdrant.txt | 1 + .../db/connection-form/golden/rabbitmq.txt | 1 + .../unit/db/connection-form/golden/redis.txt | 1 + tests/unit/db/connection-form/golden/s3.txt | 1 + tests/unit/db/connection-form/golden/snmp.txt | 1 + .../db/connection-form/golden/snowflake.txt | 1 + .../unit/db/connection-form/golden/spark.txt | 1 + .../db/connection-form/golden/sparkplug.txt | 1 + .../unit/db/connection-form/golden/sqlite.txt | 1 + .../unit/db/connection-form/golden/trino.txt | 1 + .../db/connection-form/golden/weaviate.txt | 82 + .../unit/db/connection-form/isolation.test.ts | 2 +- .../unit/db/connection-string-records.test.ts | 1 + .../unit/db/connection-string/census.test.ts | 2 +- tests/unit/db/connection-string/docs.test.ts | 2 +- .../db/connection-string/golden/weaviate.txt | 3 + .../db/connection-string/isolation.test.ts | 2 +- .../container-path-shapes-capability.test.ts | 1 + tests/unit/db/destructive-commands.test.ts | 22 +- tests/unit/db/execution-ui/census.test.ts | 2 +- tests/unit/db/execution-ui/docs.test.ts | 2 +- .../unit/db/execution-ui/golden/weaviate.txt | 4 + tests/unit/db/execution-ui/isolation.test.ts | 2 +- tests/unit/db/firestore/docs-listings.test.ts | 2 +- .../unit/db/influxdb/security-control.test.ts | 2 +- .../db/maintenance-surface-census.test.ts | 5 +- tests/unit/db/migration-ddl/census.test.ts | 2 + .../unit/db/migration-ddl/golden/weaviate.txt | 8 + tests/unit/db/milvus/provider-doc.test.ts | 2 +- tests/unit/db/object-edit-expectation.test.ts | 4 +- tests/unit/db/oxia/provider-doc.test.ts | 2 +- tests/unit/db/qdrant/provider-doc.test.ts | 2 +- tests/unit/db/query-dialects.test.ts | 12 +- tests/unit/db/rabbitmq/docs-listings.test.ts | 2 +- .../db/result-pagination-capability.test.ts | 1 + tests/unit/db/s3/provider-doc.test.ts | 68 +- tests/unit/db/sql-grammar/census.test.ts | 2 +- tests/unit/db/sql-grammar/golden/weaviate.txt | 56 + tests/unit/db/sql-writing/census.test.ts | 1 + tests/unit/db/sql-writing/golden/weaviate.txt | 443 +++ .../test-data-generation-capability.test.ts | 1 + tests/unit/db/weaviate/client.test.ts | 77 + .../db/weaviate/connection-options.test.ts | 346 ++ tests/unit/db/weaviate/errors.test.ts | 566 +++ tests/unit/db/weaviate/execute.test.ts | 601 ++++ tests/unit/db/weaviate/generators.test.ts | 127 + tests/unit/db/weaviate/graphql.test.ts | 289 ++ tests/unit/db/weaviate/guard.test.ts | 72 + tests/unit/db/weaviate/labels.test.ts | 93 + .../unit/db/weaviate/monitoring-reads.test.ts | 139 + tests/unit/db/weaviate/monitoring.test.ts | 118 + tests/unit/db/weaviate/objects.test.ts | 376 ++ tests/unit/db/weaviate/provider.test.ts | 460 +++ tests/unit/db/weaviate/registry-rows.test.ts | 67 + tests/unit/db/weaviate/request-filter.test.ts | 251 ++ tests/unit/db/weaviate/request-phase0.test.ts | 356 ++ tests/unit/db/weaviate/request-phase1.test.ts | 179 + tests/unit/db/weaviate/request-search.test.ts | 297 ++ tests/unit/db/weaviate/rest-client.test.ts | 443 +++ tests/unit/db/weaviate/results.test.ts | 476 +++ tests/unit/db/weaviate/routes.test.ts | 256 ++ tests/unit/db/weaviate/schema.test.ts | 253 ++ tests/unit/db/weaviate/source.test.ts | 187 + tests/unit/db/weaviate/versions.test.ts | 155 + tests/unit/e2e-project-servers.test.ts | 1 + tests/unit/editor/dialect-editors.test.ts | 23 +- .../lib/catalog-copy-engine-count.test.ts | 2 + tests/unit/lib/db-ui-config.test.ts | 38 +- .../lib/db/connection-fingerprint.test.ts | 4 +- tests/unit/lib/db/connection-form.test.ts | 2 + tests/unit/lib/db/credential-warnings.test.ts | 4 +- tests/unit/lib/table-count.test.ts | 1 + tests/unit/readme-numeral-names.test.ts | 18 +- .../schema-diff/migration-dialects.test.ts | 1 + .../schema-diff/migration-generator.test.ts | 5 + tests/unit/security-check.test.ts | 6 +- tests/unit/sql/grammar.test.ts | 2 + tests/unit/theme-accent-contrast.test.ts | 5 + .../src/webview/vscode-bridge.css | 1 + .../test/unit/editor/editor-language.test.ts | 1 + .../test/unit/webview/stylesheet.test.ts | 1 + 265 files changed, 34145 insertions(+), 292 deletions(-) create mode 100644 docker/weaviate/README.md create mode 100644 docker/weaviate/keys.sh create mode 100644 docker/weaviate/seed.py create mode 100644 docs/providers/weaviate.md create mode 100644 e2e/weaviate-provider.spec.ts create mode 100644 src/lib/db/providers/vector/weaviate/client.ts create mode 100644 src/lib/db/providers/vector/weaviate/connection-options.ts create mode 100644 src/lib/db/providers/vector/weaviate/connection-string.ts create mode 100644 src/lib/db/providers/vector/weaviate/errors.ts create mode 100644 src/lib/db/providers/vector/weaviate/execute.ts create mode 100644 src/lib/db/providers/vector/weaviate/execution-ui.ts create mode 100644 src/lib/db/providers/vector/weaviate/generators.ts create mode 100644 src/lib/db/providers/vector/weaviate/graphql.ts create mode 100644 src/lib/db/providers/vector/weaviate/guard.ts create mode 100644 src/lib/db/providers/vector/weaviate/index.ts create mode 100644 src/lib/db/providers/vector/weaviate/labels.ts create mode 100644 src/lib/db/providers/vector/weaviate/migration-ddl.ts create mode 100644 src/lib/db/providers/vector/weaviate/monitoring-reads.ts create mode 100644 src/lib/db/providers/vector/weaviate/monitoring.ts create mode 100644 src/lib/db/providers/vector/weaviate/objects.ts create mode 100644 src/lib/db/providers/vector/weaviate/request.ts create mode 100644 src/lib/db/providers/vector/weaviate/rest-client.ts create mode 100644 src/lib/db/providers/vector/weaviate/results.ts create mode 100644 src/lib/db/providers/vector/weaviate/routes.ts create mode 100644 src/lib/db/providers/vector/weaviate/schema.ts create mode 100644 src/lib/db/providers/vector/weaviate/source.ts create mode 100644 src/lib/db/providers/vector/weaviate/sql-grammar.ts create mode 100644 src/lib/db/providers/vector/weaviate/sql-writing.ts create mode 100644 src/lib/db/providers/vector/weaviate/versions.ts create mode 100644 tests/fixtures/weaviate/README.md create mode 100644 tests/fixtures/weaviate/weaviate-1-37/reads.json create mode 100644 tests/fixtures/weaviate/weaviate-1-37/searches.json create mode 100644 tests/fixtures/weaviate/weaviate-1-37/surface.json create mode 100644 tests/fixtures/weaviate/weaviate-1-38/searches.json create mode 100644 tests/fixtures/weaviate/weaviate-1-38/surface.json create mode 100644 tests/fixtures/weaviate/weaviate-auth/no-key.json create mode 100644 tests/fixtures/weaviate/weaviate-auth/reader.json create mode 100644 tests/fixtures/weaviate/weaviate-auth/root.json create mode 100644 tests/fixtures/weaviate/weaviate-auth/wrong-key.json create mode 100644 tests/fixtures/weaviate/weaviate-nographql/searches.json create mode 100644 tests/fixtures/weaviate/weaviate-nographql/surface.json create mode 100644 tests/fixtures/weaviate/weaviate-tls/plain-to-tls.json create mode 100644 tests/fixtures/weaviate/weaviate-tls/reader.json create mode 100644 tests/fixtures/weaviate/weaviate/reads.json create mode 100644 tests/fixtures/weaviate/weaviate/refusals.json create mode 100644 tests/fixtures/weaviate/weaviate/searches.json create mode 100644 tests/fixtures/weaviate/weaviate/surface.json create mode 100644 tests/helpers/weaviate-request-fixtures.ts create mode 100644 tests/helpers/weaviate-scenario.ts create mode 100644 tests/helpers/weaviate-surface.ts create mode 100644 tests/helpers/weaviate-wire.ts create mode 100644 tests/integration/db/weaviate-provider.test.ts create mode 100644 tests/live/weaviate-evidence.ts create mode 100644 tests/live/weaviate-live-check.ts create mode 100644 tests/live/weaviate-path-parity.ts create mode 100644 tests/live/weaviate-scenarios.ts create mode 100644 tests/unit/db/connection-form/golden/weaviate.txt create mode 100644 tests/unit/db/connection-string/golden/weaviate.txt create mode 100644 tests/unit/db/execution-ui/golden/weaviate.txt create mode 100644 tests/unit/db/migration-ddl/golden/weaviate.txt create mode 100644 tests/unit/db/sql-grammar/golden/weaviate.txt create mode 100644 tests/unit/db/sql-writing/golden/weaviate.txt create mode 100644 tests/unit/db/weaviate/client.test.ts create mode 100644 tests/unit/db/weaviate/connection-options.test.ts create mode 100644 tests/unit/db/weaviate/errors.test.ts create mode 100644 tests/unit/db/weaviate/execute.test.ts create mode 100644 tests/unit/db/weaviate/generators.test.ts create mode 100644 tests/unit/db/weaviate/graphql.test.ts create mode 100644 tests/unit/db/weaviate/guard.test.ts create mode 100644 tests/unit/db/weaviate/labels.test.ts create mode 100644 tests/unit/db/weaviate/monitoring-reads.test.ts create mode 100644 tests/unit/db/weaviate/monitoring.test.ts create mode 100644 tests/unit/db/weaviate/objects.test.ts create mode 100644 tests/unit/db/weaviate/provider.test.ts create mode 100644 tests/unit/db/weaviate/registry-rows.test.ts create mode 100644 tests/unit/db/weaviate/request-filter.test.ts create mode 100644 tests/unit/db/weaviate/request-phase0.test.ts create mode 100644 tests/unit/db/weaviate/request-phase1.test.ts create mode 100644 tests/unit/db/weaviate/request-search.test.ts create mode 100644 tests/unit/db/weaviate/rest-client.test.ts create mode 100644 tests/unit/db/weaviate/results.test.ts create mode 100644 tests/unit/db/weaviate/routes.test.ts create mode 100644 tests/unit/db/weaviate/schema.test.ts create mode 100644 tests/unit/db/weaviate/source.test.ts create mode 100644 tests/unit/db/weaviate/versions.test.ts diff --git a/CLAUDE.md b/CLAUDE.md index ff26b71cbf..c22b7486ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ Guidance for Claude Code in this repo — conventions, rules, and gotchas only. ## Project Overview -Web-based SQL IDE for cloud-native teams: forty-one external engines, plus the embedded LibreDB store (`EXTERNAL_DATABASE_TYPES` in [`src/lib/db/compatibility.ts`](src/lib/db/compatibility.ts) is the external-engine list, never a prose enumeration), plus AI query assistance. +Web-based SQL IDE for cloud-native teams: forty-two external engines, plus the embedded LibreDB store (`EXTERNAL_DATABASE_TYPES` in [`src/lib/db/compatibility.ts`](src/lib/db/compatibility.ts) is the external-engine list, never a prose enumeration), plus AI query assistance. It runs **two ways**, as a standalone Next.js app and as a published npm package, and the two render different chrome, so a UI change verified in one is not verified in the other. ## Branching & PRs @@ -90,7 +90,7 @@ A clean local pass is still not a guarantee: the same job also runs `build:lib` > - **Agent leg.** A type-id whose `AGENT_STATEMENT_LANGUAGE` row is non-null also keeps, in the same PR: Code: `src/lib/agent/languages//engines/.ts` plus its client row in `languages//engines/client.ts` · Docs: the `Agent language pack` subsection of `docs/providers/.md`, naming the statement-language family and every overlay member · Tests: `tests/unit/lib/agent/engine-docs.test.ts`, which holds that subsection to the overlay, plus the engine's cases in `engine-overlays.test.ts` and `engine-pack-contract.test.ts`. > - Any change to one side MUST sync the others **in the same PR**. The doc mirrors the code and the code mirrors the doc — never let them drift. -- **DB abstraction:** Strategy Pattern. SQL-dialect providers extend `SQLBaseProvider`; the non-SQL ones (`mongodb`, `redis`, `couchbase`, `firestore`, `prometheus`, `influxdb`, `kafka`, `mqtt`, `etcd`, `oxia`, `milvus`, `qdrant`, `s3`, `kubernetes`, `rabbitmq`, `libredb`) extend `BaseDatabaseProvider` directly, `neo4j` extends `GraphBaseProvider` (`src/lib/db/graph/`), and `SQLBaseProvider` and `GraphBaseProvider` themselves extend it. Inside `src/lib/db`, never branch on the type id; drive behaviour through capabilities/labels. Outside the provider layer, a per-engine fact is a row of a contract registry, never a type-id branch: the `src/lib/db/connection-string/`, `src/lib/db/execution-ui/`, `src/lib/db/sql-grammar/`, `src/lib/db/migration-ddl/` and `src/lib/db/sql-writing/` rows are declared beside each provider, and `CONNECTION_FIELDS` and `SEED_ONLY_FIELDS` are central UI-free tables in `src/lib/db/connection-fields.ts`; `tests/unit/lib/no-engine-branches.test.ts` fails on any other type-id branch, and its debt list is empty, so a new branch is moved into a contract rather than listed. +- **DB abstraction:** Strategy Pattern. SQL-dialect providers extend `SQLBaseProvider`; the non-SQL ones (`mongodb`, `redis`, `couchbase`, `firestore`, `prometheus`, `influxdb`, `kafka`, `mqtt`, `etcd`, `oxia`, `milvus`, `qdrant`, `weaviate`, `s3`, `kubernetes`, `rabbitmq`, `libredb`) extend `BaseDatabaseProvider` directly, `neo4j` extends `GraphBaseProvider` (`src/lib/db/graph/`), and `SQLBaseProvider` and `GraphBaseProvider` themselves extend it. Inside `src/lib/db`, never branch on the type id; drive behaviour through capabilities/labels. Outside the provider layer, a per-engine fact is a row of a contract registry, never a type-id branch: the `src/lib/db/connection-string/`, `src/lib/db/execution-ui/`, `src/lib/db/sql-grammar/`, `src/lib/db/migration-ddl/` and `src/lib/db/sql-writing/` rows are declared beside each provider, and `CONNECTION_FIELDS` and `SEED_ONLY_FIELDS` are central UI-free tables in `src/lib/db/connection-fields.ts`; `tests/unit/lib/no-engine-branches.test.ts` fails on any other type-id branch, and its debt list is empty, so a new branch is moved into a contract rather than listed. - **Auth:** `NEXT_PUBLIC_AUTH_PROVIDER` = `local` (email/password) or `oidc` (PKCE → the same JWT cookie); `src/proxy.ts` enforces RBAC (admin vs user). [`docs/OIDC.md`](docs/OIDC.md). - **Storage:** write-through cache — localStorage serves reads, `useStorageSync` pushes mutations to the server (debounced). `STORAGE_PROVIDER` (server-side only) = `local` | `sqlite` | `postgres`. [`docs/STORAGE.md`](docs/STORAGE.md). - **API routes:** all backend in `src/app/api/`, except `/health`, which is a route at the app root so the plainest liveness path exists; JWT-protected except the public set in [`src/proxy.ts`](src/proxy.ts) — `/login`, `/launch`, `/api/auth/*`, `/health`, `/api/health`, `/api/db/health`, `/api/ready`, `/api/storage/config`, `/_next`, `/favicon.ico` and static assets — plus two machine paths gated by bearer credentials of their own instead of the JWT: the agent drive callback and /api/mcp. `src/proxy.ts` is the authority; do not restate the list elsewhere. diff --git a/DOCKERHUB.md b/DOCKERHUB.md index 7f788a6a22..feeb8cc0f5 100644 --- a/DOCKERHUB.md +++ b/DOCKERHUB.md @@ -20,7 +20,7 @@ > 📖 **Full documentation, source, and issues:** -Query **PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, NETCONF, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes** from your browser, with AI query assistance, RBAC and OIDC SSO. +Query **PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, NETCONF, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes** from your browser, with AI query assistance, RBAC and OIDC SSO. --- @@ -110,8 +110,8 @@ Every one of those tags is published on three bases, and the suffix is appended ## Supported databases -Forty-one external engines share one interface. -The forty-second row is the embedded LibreDB store: it ships inside the image. +Forty-two external engines share one interface. +The forty-third row is the embedded LibreDB store: it ships inside the image. | Database | Driver | Highlights | | :--- | :--- | :--- | @@ -143,6 +143,7 @@ The forty-second row is the embedded LibreDB store: it ships inside the image. | **Neo4j** | `neo4j-driver-lite` | Read-only Cypher editor, label and relationship-type browser | | **Milvus** | `@grpc/grpc-js` | Read-only REST v2 request editor, vector search, admin Load and Release | | **Qdrant** | none, HTTP | Read-only REST request editor, vector search, collection browser | +| **Weaviate** | none, HTTP | Read-only REST requests, vector search | | **InfluxDB (InfluxQL)** | none, HTTP | Read-only InfluxQL editor, 1.x to 3 | | **InfluxDB 3 (SQL)** | none, HTTP | Read-only SQL editor | | **Oxia** | `@grpc/grpc-js` | Read-only oxia client commands, shard map, key browser | @@ -158,7 +159,7 @@ Firestore, Prometheus, InfluxDB, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect ### Engines with no provider of their own -Twenty-seven further engines speak the wire protocol of one of the forty-one drivers above: pick that driver in the connection dialog. Each was measured against a real instance, and how much worked is recorded per engine. +Twenty-seven further engines speak the wire protocol of one of the forty-two drivers above: pick that driver in the connection dialog. Each was measured against a real instance, and how much worked is recorded per engine. | Engine | Connect as | Support | | :--- | :--- | :--- | diff --git a/README.md b/README.md index 3f42318c3e..f2d9a87199 100644 --- a/README.md +++ b/README.md @@ -130,8 +130,10 @@ You create a Postgres on a managed platform. It is ready in forty seconds. Then LibreDB Studio goes the other way. It deploys next to the data: a container, a Helm chart, an operator, a one-click template on your PaaS, or `npm i @libredb/studio` inside your own product. Nothing has to face outward. -Forty-one engines share one interface: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B, with the same explorer everywhere, and ER diagrams, schema diff and monitoring wherever the engine has something to report. Three of the forty-one are read-only because their own SQL is: Druid, Elasticsearch and OpenSearch have no `UPDATE` and no `CREATE TABLE` in the grammar at all, so those controls are reported as unsupported instead of failing when used. Cassandra is the one that reports the least on purpose: it publishes no row count and no size that is true, so the object browser shows neither rather than showing a number that is wrong; the estimate it does publish counts partitions from flushed files, and it read 143 for a 500-row table. Trino is the other odd one: it is a query engine rather than a database, so it declares no keys and no indexes and reports the bytes as belonging to the systems behind its connectors. -Sparkplug B is the newest: one broker read over MQTT, the metrics an edge node's birth certificate declares and the values the data messages after it carry, read-only by construction, because the encoder has no function that writes a PUBLISH and the CONNECT carries no will: 5.4 registers an edge node's death certificate as its will, so a reader that set one would publish a death when its own socket dropped. A group and an edge node are containers, a metric is a row whose value, timestamp and definition come from the certificate that declared it, and a sequence gap is read from two consecutive data messages rather than guessed. +Forty-two engines share one interface: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B, with the same explorer everywhere, and ER diagrams, schema diff and monitoring wherever the engine has something to report. Three of the forty-two are read-only because their own SQL is: Druid, Elasticsearch and OpenSearch have no `UPDATE` and no `CREATE TABLE` in the grammar at all, so those controls are reported as unsupported instead of failing when used. Cassandra is the one that reports the least on purpose: it publishes no row count and no size that is true, so the object browser shows neither rather than showing a number that is wrong; the estimate it does publish counts partitions from flushed files, and it read 143 for a 500-row table. Trino is the other odd one: it is a query engine rather than a database, so it declares no keys and no indexes and reports the bytes as belonging to the systems behind its connectors. +Weaviate is the newest: Weaviate's own REST requests typed in the editor read a Weaviate 1.37 or later server, the browser shows collections with their properties and vectors, and tenants and aliases sit in a collection's Source, read-only by construction, because the console runs seventeen read routes and refuses every request that would send text to a model. A search is written in the REST search shape on every server and runs over REST on 1.39.7 and later and over GraphQL before it, and no read ever wakes a cold tenant. + +Sparkplug B came before Weaviate: one broker read over MQTT, the metrics an edge node's birth certificate declares and the values the data messages after it carry, read-only by construction, because the encoder has no function that writes a PUBLISH and the CONNECT carries no will: 5.4 registers an edge node's death certificate as its will, so a reader that set one would publish a death when its own socket dropped. A group and an edge node are containers, a metric is a row whose value, timestamp and definition come from the certificate that declared it, and a sequence gap is read from two consecutive data messages rather than guessed. SNMP came before Sparkplug B: one agent read over UDP, the managed objects a numbered name points at, read-only by construction, because the outgoing valve refuses any PDU that is not a Get, GetNext or GetBulk, so a Set never reaches the socket. Four commands reach the agent, `get`, `next`, `walk` and `table`, and one file decides when a walk is over and nothing else does: the end of a subtree, a budget, an OID that did not move forward, or silence. An object group is a container, a walk over a subtree is the read, and a table is assembled from GetBulk answers. It speaks SNMPv2c today, and that is a fact about the connection form rather than a preference: the v3 security layer is written and measured byte for byte against its own captures, but the shared connection record carries no security level, privacy passphrase, context name or engine id pin, so there is nowhere for an operator to turn it on. @@ -155,20 +157,20 @@ Qdrant came before Milvus: Qdrant's own REST requests typed in the editor read a Neo4j came before Qdrant: Cypher typed in the editor reads a Neo4j 5.26 database over Bolt, the browser shows node labels, relationship types, indexes and constraints, and nodes, relationships and paths reach the grid as JSON cells, read-only by construction, because every statement passes a read policy, the server's own classification (which an allowlisted SHOW form skips) and a READ session before it runs. etcd is the one before it: an etcdctl subset over etcd's gRPC API reads and writes keys, the browser shows key-prefix groups and a key browser, a key's value is edited in one transaction guarded by its revision, and an admin can compact, defragment and disarm alarms, while every write under a Kubernetes prefix is refused and every Kubernetes secret withheld. Apache Kafka came before etcd: a JSON read request reads a topic's messages over the Kafka protocol, by partition, offset or timestamp, and the browser shows topics, consumer groups with their lag, and brokers, read-only by construction, because Studio never produces, commits an offset, joins a consumer group or creates a topic. -None of OPC UA, Kubernetes, S3-compatible object storage, Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Neo4j, etcd, Apache Kafka, MQTT, RabbitMQ and Prometheus is SQL at all, as MongoDB and Redis are not: InfluxQL looks like SQL and is its own language, one `SELECT`, `SHOW` or `EXPLAIN` per run here, while InfluxDB 3 (SQL) is SQL; Prometheus speaks PromQL over the Prometheus HTTP API, browses metrics, rules and scrape targets, and is read-only because Studio calls none of the server's write or admin endpoints. +None of OPC UA, Kubernetes, S3-compatible object storage, Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Weaviate, Neo4j, etcd, Apache Kafka, MQTT, RabbitMQ and Prometheus is SQL at all, as MongoDB and Redis are not: InfluxQL looks like SQL and is its own language, one `SELECT`, `SHOW` or `EXPLAIN` per run here, while InfluxDB 3 (SQL) is SQL; Prometheus speaks PromQL over the Prometheus HTTP API, browses metrics, rules and scrape targets, and is read-only because Studio calls none of the server's write or admin endpoints. And nothing is held back. Single sign-on, ER diagrams, the AI features and the NoSQL engines all ship in the MIT build. MIT is not generosity here, it is a requirement of the architecture: you cannot place a per-seat licensed, feature-gated tool into every environment you own. ### Why LibreDB Studio? - **Deploys next to the data**: container, Helm chart, Rancher, OpenShift operator, one-click PaaS template, or embedded via npm. -- **Forty-one engines, one interface**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Prometheus, Apache Kafka, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B. +- **Forty-two engines, one interface**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Prometheus, Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B. - **Runs where you are**: browser, phone, Windows, MacOS, Linux desktop. - **A read-only agent, with your own model**: state a question, and the run drafts SQL, reads the results, and writes a report whose claims cite them. Gemini, OpenAI, or a local Ollama with open-source models. - **Nothing behind a wall**: RBAC, OIDC single sign-on, the audit log, and ER diagrams all ship under MIT.

Multi-Database Connection Manager -
Connect to PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Redis, SQLite, DuckDB, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MTConnect and Modbus with SSL/TLS and SSH Tunnel support (Kafka takes TLS and no tunnel, and OPC UA carries its own transport security instead of the shared panel, NETCONF Sparkplug B is reached over SSH with the device's own host key pinned rather than through either, and SNMP takes neither: its transport is UDP, which the shared tunnel cannot carry, and v3's security is inside the message). +
Connect to PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Redis, SQLite, DuckDB, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MTConnect and Modbus with SSL/TLS and SSH Tunnel support (Kafka takes TLS and no tunnel, and OPC UA carries its own transport security instead of the shared panel, NETCONF Sparkplug B is reached over SSH with the device's own host key pinned rather than through either, and SNMP takes neither: its transport is UDP, which the shared tunnel cannot carry, and v3's security is inside the message).

--- @@ -353,6 +355,7 @@ Standalone application only: the embedded `@libredb/studio` package carries no a | **Neo4j** | `neo4j-driver-lite` (pure JavaScript, Bolt, port 7687) | Read-only Cypher in the editor, one statement per run, against Neo4j 5.26 LTS; node labels and relationship types with their properties as columns, indexes and constraints in the tree; nodes, relationships and paths as tagged JSON cells in the grid, with 64-bit integers and temporal values kept exact; the monitoring panels Community serves. Every statement passes a read policy over its tokens, then the server's own classification through `EXPLAIN`, which runs only a read or an allowlisted procedure call and which an allowlisted SHOW form skips, and runs in a READ session, so a write has to defeat all three. No EXPLAIN or PROFILE view, no maintenance, no agent execution and no MCP `run_read_query`. TLS with a custom CA and SSH tunnel; no connection string | | **Milvus** | `@grpc/grpc-js` (pure JavaScript, gRPC, port 19530) | Milvus's own REST v2 requests in the editor (`POST /v2/vectordb/` with one JSON body) for reads, exact counts and vector searches over every vector type, BM25 and hybrid search included; databases and collections in the tree with fields, partitions, indexes and load state; vector cells with their dimension and full-value copy; Load and Release for admins, previewed and confirmed. Studio writes no data, refuses requests that would make the server call another service, and warns about the default `root` password. TLS with a custom CA and client certificates; a password only over TLS, on loopback or through the SSH tunnel; a seed-declared read-only mode | | **Qdrant** | none, HTTP (Qdrant's REST API, port 6333) | Qdrant's own REST requests in the editor (`METHOD /path` with one JSON body), seventeen read routes: point reads, scrolls, exact counts, facets, and queries, batches and grouped queries over dense, sparse and multivector data, the local BM25 model included; collections in the tree with their vectors, payload indexes and a sampled view of payload keys; vector cells with their dimension and full-value copy. Studio writes nothing, refuses every inference input except local BM25, and warns about a JWT with no expiry or manage access. TLS with a custom CA and client certificates; a key only over TLS, on loopback or through the SSH tunnel; a seed-declared read-only mode | +| **Weaviate** | none, HTTP (Weaviate's REST API, and GraphQL below 1.39.7, port 8080) | Weaviate's own REST requests in the editor (`METHOD /v1/path` with one JSON body), seventeen read routes: object lists and reads by id, BM25, hybrid at alpha 0, near-vector and near-object searches, filters and aggregate counts, written in the REST search shape on every server and run over GraphQL on a server older than 1.39.7; collections in the tree with their properties and vectors, tenants and aliases in a collection's Source, exact counts. Studio writes nothing, refuses every request that would send text to a model, and never wakes a cold tenant. TLS with a custom CA; an API key or OIDC access token only over TLS, on loopback or through the SSH tunnel; tested on Weaviate 1.40.2, 1.38.22 and 1.37.4. | | **InfluxDB (InfluxQL)** | none, HTTP (InfluxDB's v1 API, port 8086) | Read-only InfluxQL in the editor against InfluxDB 1.x, 2.x and 3 over the v1 `/query` API, one `SELECT`, `SHOW` or `EXPLAIN` per run; databases and measurements in the tree, a measurement's tags and fields as its columns, and integers beyond 2^53 and nanosecond timestamps kept exact in the grid. Read-only whatever the connection says: on 1.x and 2.x Studio's own read policy is the only boundary before `DROP DATABASE`, so every other statement is refused before any request, and no write endpoint is reached. A user and password, or a token in the password field; a credential over plain HTTP to a host that is neither loopback nor tunnelled is refused unless the connection consents; `_internal` is never read on an InfluxDB 3 server | | **InfluxDB 3 (SQL)** | none, HTTP (InfluxDB 3's SQL API, port 8181) | Read-only SQL in the editor against InfluxDB 3 Core and Enterprise; the tables of the connection's database in the tree with their columns. Read-only whatever the connection says: the route table reaches no write, token, cache or plugin endpoint, and of the configure endpoints only the database listing, a GET, every statement that does not lead with a read keyword is refused before any request, and the server's planner refuses every write besides. A token, and no user name; a token over plain HTTP to a host that is neither loopback nor tunnelled is refused unless the connection consents; pointed at a 1.x or 2.x server it says to pick InfluxDB (InfluxQL) instead | | **Oxia** | `@grpc/grpc-js` (pure JavaScript, gRPC, port 6648) | Read-only `oxia client` commands (`get`, `list`, `range-scan`), shards in the tree, every key in the Keys panel | @@ -368,7 +371,7 @@ Standalone application only: the embedded `@libredb/studio` package carries no a | **Sparkplug B** | none: Studio's own bounded MQTT session over the shared `node:net` and `node:tls` transports (port 1883, or 8883 through the SSL / TLS panel) | Read-only by construction: the encoder has no function that writes a PUBLISH, and the CONNECT carries no will, because 5.4 registers an edge node's death certificate as its will and a reader that set one would publish a death when its own socket dropped. A group and an edge node are containers, and a metric is a row whose value, timestamp and definition come from the birth certificate that declared it | | **Redis** | `ioredis` | Command editor, key browser, INFO-based monitoring | -> **Twenty-seven more engines have no driver of their own.** The forty-one above are the drivers this build ships. Twenty-seven further engines speak one of those wire protocols and connect through an existing driver unchanged, so forty-one drivers reach sixty-eight named engines in all. They are MariaDB, Percona Server for MySQL, TiDB, Vitess, StarRocks, Apache Doris, OceanBase, SingleStore, Citus, Percona Distribution for PostgreSQL, [ParadeDB](https://www.paradedb.com/), OrioleDB, TimescaleDB, YugabyteDB, AlloyDB Omni, Apache Cloudberry (incubating), CockroachDB, Materialize and RisingWave (as PostgreSQL or MySQL), Valkey, DragonflyDB, KeyDB and Garnet (as Redis), FerretDB (as MongoDB), ScyllaDB (as Cassandra), VictoriaMetrics (as Prometheus), and Redpanda (as Apache Kafka). Each was measured against a live instance, and how much of the product works differs per engine. MariaDB, both Percona distributions, TiDB, Vitess, AlloyDB Omni, Citus, TimescaleDB, YugabyteDB, ParadeDB, OrioleDB, Valkey, DragonflyDB, KeyDB and FerretDB behave as their driver's own engine, though three of them report statistics you should not trust: a Citus distributed table and a TimescaleDB hypertable report row counts and sizes that are wrong rather than missing, and YugabyteDB reports 0 until you run `ANALYZE`. Vitess is not one of those three, its row counts and sizes being exact to the byte, but a running query cannot be cancelled there: vtgate refuses `KILL QUERY` and the statement runs to completion. AlloyDB Omni is not one of them either, reporting 2000 rows for 2000 and 270336 bytes for 270336, but two things there surprise: `version()` names AlloyDB nowhere, so the version panel cannot be told apart from a stock PostgreSQL 17, and eight of AlloyDB's own `google_ml` tables list in the object browser, which any role that can connect at all may also read. StarRocks reports itself as MySQL 5.1 and loses its overview, health and session panels, its monitoring dashboard rendering six panels with the session one carrying the engine's own refusal; Apache Doris - the engine StarRocks is a fork of - loses only the overview and health panels, to one statement form its grammar rejects, and is the more trustworthy of the two where it counts: it reports 2000 rows and 10187 bytes for a table holding exactly that, where StarRocks reads zero at first too - its own background statistics collector is slower, measured 4.5 minutes against 3.3.22 where Doris's is about a minute - and, until a 2026-09-16 fix, read zero forever afterward for sizes specifically, because StarRocks' `INDEX_LENGTH` is NULL rather than Doris's real 0 and poisoned the sum the provider computed in SQL; no index is ever reported, and a foreign key is accepted, listed by `SHOW CONSTRAINTS`, invisible to the ER diagram and unenforced; Cloudberry loses the monitoring dashboard and its table and index statistics, all three to one MPP planner restriction, and reads a foreign key back as though it were enforced when it is not, though its row counts are correct; CockroachDB loses the object browser and the size panels; OceanBase answers fourteen of the fifteen surfaces but only twelve of them usefully, health failing outright because its tenant has no `performance_schema` database at all and every size reading 0 B, though its row counts are correct once `ANALYZE TABLE` has run; SingleStore lost five surfaces to a cause that was ours rather than its own - the provider sent every statement through the prepared-statement protocol, which SingleStore refuses for the `SHOW` and `EXPLAIN` statements four panels need - and four of those five are now recovered, its Explain panel being the one that is not, because there the grammar wants `EXPLAIN JSON` and the statement fails on either protocol; its numbers are still missing rather than wrong, a 2000-row table reading 0 rows and 0 B with no `ANALYZE` able to change it; ScyllaDB loses five surfaces and Test Connection with them, all six to one absent keyspace - the overview, health, performance-metrics, active-session and monitoring panels read Cassandra's `system_views` virtual tables and ScyllaDB has no `system_views` keyspace at all - those five now degrade to empty rather than throwing, so Test Connection passes and the dialog saves the connection, which it could not do at all until that change - while the editor and the object browser work in full, every one of 18 CQL types reading back byte-identically to the Cassandra 5.0.9 probed in the same pass; ParadeDB and OrioleDB are both full and their costs are opposites: ParadeDB's nine extensions put 41 objects in the object browser for 2 user tables, though agent plan mode works there under a least-privilege role and is refused only as the `postgres` superuser, as on any PostgreSQL, while OrioleDB's browser is clean and its own storage is invisible to PostgreSQL's size functions, so every index reads 0 bytes and the cache hit ratio reads N/A. Materialize and RisingWave are partial: the object browser shows their tables, views and materialized views with their columns, while row counts, sizes and the monitoring statistics stay blank. Garnet behaves as Redis and is one of three relatives here (with Valkey and DragonflyDB) whose own version `INFO` carries beside the Redis compat level and the overview now labels ahead of it - `Garnet 2.1.5 (Redis 7.4.3)` - and two of its readings are absences wearing a value, every size showing 0 B because it publishes no `used_memory` and the cache hit ratio showing 100% because it publishes no keyspace counters. +> **Twenty-seven more engines have no driver of their own.** The forty-two above are the drivers this build ships. Twenty-seven further engines speak one of those wire protocols and connect through an existing driver unchanged, so forty-two drivers reach sixty-nine named engines in all. They are MariaDB, Percona Server for MySQL, TiDB, Vitess, StarRocks, Apache Doris, OceanBase, SingleStore, Citus, Percona Distribution for PostgreSQL, [ParadeDB](https://www.paradedb.com/), OrioleDB, TimescaleDB, YugabyteDB, AlloyDB Omni, Apache Cloudberry (incubating), CockroachDB, Materialize and RisingWave (as PostgreSQL or MySQL), Valkey, DragonflyDB, KeyDB and Garnet (as Redis), FerretDB (as MongoDB), ScyllaDB (as Cassandra), VictoriaMetrics (as Prometheus), and Redpanda (as Apache Kafka). Each was measured against a live instance, and how much of the product works differs per engine. MariaDB, both Percona distributions, TiDB, Vitess, AlloyDB Omni, Citus, TimescaleDB, YugabyteDB, ParadeDB, OrioleDB, Valkey, DragonflyDB, KeyDB and FerretDB behave as their driver's own engine, though three of them report statistics you should not trust: a Citus distributed table and a TimescaleDB hypertable report row counts and sizes that are wrong rather than missing, and YugabyteDB reports 0 until you run `ANALYZE`. Vitess is not one of those three, its row counts and sizes being exact to the byte, but a running query cannot be cancelled there: vtgate refuses `KILL QUERY` and the statement runs to completion. AlloyDB Omni is not one of them either, reporting 2000 rows for 2000 and 270336 bytes for 270336, but two things there surprise: `version()` names AlloyDB nowhere, so the version panel cannot be told apart from a stock PostgreSQL 17, and eight of AlloyDB's own `google_ml` tables list in the object browser, which any role that can connect at all may also read. StarRocks reports itself as MySQL 5.1 and loses its overview, health and session panels, its monitoring dashboard rendering six panels with the session one carrying the engine's own refusal; Apache Doris - the engine StarRocks is a fork of - loses only the overview and health panels, to one statement form its grammar rejects, and is the more trustworthy of the two where it counts: it reports 2000 rows and 10187 bytes for a table holding exactly that, where StarRocks reads zero at first too - its own background statistics collector is slower, measured 4.5 minutes against 3.3.22 where Doris's is about a minute - and, until a 2026-09-16 fix, read zero forever afterward for sizes specifically, because StarRocks' `INDEX_LENGTH` is NULL rather than Doris's real 0 and poisoned the sum the provider computed in SQL; no index is ever reported, and a foreign key is accepted, listed by `SHOW CONSTRAINTS`, invisible to the ER diagram and unenforced; Cloudberry loses the monitoring dashboard and its table and index statistics, all three to one MPP planner restriction, and reads a foreign key back as though it were enforced when it is not, though its row counts are correct; CockroachDB loses the object browser and the size panels; OceanBase answers fourteen of the fifteen surfaces but only twelve of them usefully, health failing outright because its tenant has no `performance_schema` database at all and every size reading 0 B, though its row counts are correct once `ANALYZE TABLE` has run; SingleStore lost five surfaces to a cause that was ours rather than its own - the provider sent every statement through the prepared-statement protocol, which SingleStore refuses for the `SHOW` and `EXPLAIN` statements four panels need - and four of those five are now recovered, its Explain panel being the one that is not, because there the grammar wants `EXPLAIN JSON` and the statement fails on either protocol; its numbers are still missing rather than wrong, a 2000-row table reading 0 rows and 0 B with no `ANALYZE` able to change it; ScyllaDB loses five surfaces and Test Connection with them, all six to one absent keyspace - the overview, health, performance-metrics, active-session and monitoring panels read Cassandra's `system_views` virtual tables and ScyllaDB has no `system_views` keyspace at all - those five now degrade to empty rather than throwing, so Test Connection passes and the dialog saves the connection, which it could not do at all until that change - while the editor and the object browser work in full, every one of 18 CQL types reading back byte-identically to the Cassandra 5.0.9 probed in the same pass; ParadeDB and OrioleDB are both full and their costs are opposites: ParadeDB's nine extensions put 41 objects in the object browser for 2 user tables, though agent plan mode works there under a least-privilege role and is refused only as the `postgres` superuser, as on any PostgreSQL, while OrioleDB's browser is clean and its own storage is invisible to PostgreSQL's size functions, so every index reads 0 bytes and the cache hit ratio reads N/A. Materialize and RisingWave are partial: the object browser shows their tables, views and materialized views with their columns, while row counts, sizes and the monitoring statistics stay blank. Garnet behaves as Redis and is one of three relatives here (with Valkey and DragonflyDB) whose own version `INFO` carries beside the Redis compat level and the overview now labels ahead of it - `Garnet 2.1.5 (Redis 7.4.3)` - and two of its readings are absences wearing a value, every size showing 0 B because it publishes no `used_memory` and the cache hit ratio showing 100% because it publishes no keyspace counters. > VictoriaMetrics runs PromQL through the Prometheus driver and lists its metrics with their label columns, its targets, and up to fifty of its metrics with the most series, but its rule folders are empty, because a single-node server evaluates no rules; the overview, the storage statistics and the scrape pool folder fail, because it does not serve three of the Prometheus endpoints they read; a metric's source shows no unit and a target's no scrape interval or timeout, because it sends none, and a target it has not scraped yet reads as down; and a string expression returns no rows, a subquery's points are counted back from its evaluation time, and no PromQL info or warning appears beside any result. > Redpanda answers every Kafka surface through the Apache Kafka driver, its topics, consumer groups with their lag, brokers and reads alike, but its overview reads max connections as 0 and its broker source lists nine configs, because a broker's config answer holds only those, its storage statistics carry no usage percentage, and every group reads as classic, which is right there, since Redpanda has no other group protocol. > The per-engine detail, with the exact version probed, is in [`docs/providers/README.md`](docs/providers/README.md#wire-compatible-engines): we publish a name only after connecting to it, so a name absent there is untested rather than unsupported. @@ -391,7 +394,7 @@ Standalone application only: the embedded `@libredb/studio` package carries no a | **Editor** | Monaco Editor (VS Code Engine) | Web | | **AI** | Multi-Model (Gemini, OpenAI, Ollama, Custom) | Web, Mobile | | **Auth** | JWT (`jose`) + OIDC (`openid-client`), PKCE, Role Mapping | Web, Mobile | -| **Database** | PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B | Web, Mobile | +| **Database** | PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B | Web, Mobile | | **Charts** | Recharts (Bar, Line, Pie, Area, Scatter, Histogram, Stacked) | Web, Mobile | | **ERD** | React Flow, ELK.js (auto-layout) | Web | | **State/Grid** | TanStack Table & Virtual | Web, Mobile | @@ -484,7 +487,7 @@ journalctl -u libredb-studio ### Prerequisites - [Bun](https://bun.sh/) (Recommended) or Node.js 24+ - - A target database to query (PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, or Sparkplug B) + - A target database to query (PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, or Sparkplug B) ### Quick Start (Local) 1. **Clone & Install** @@ -624,6 +627,7 @@ docker compose -f database-compose.yml --profile druid down -v | **Neo4j** | localhost | 7687 | neo4j | password123 | `neo4j` (the default database); load `docker/neo4j/seed.cypher` as `docker/neo4j/README.md` says | | **Milvus** | localhost | 19530 | root | the documented default, see `docs/providers/milvus.md` | `default` | | **Qdrant** | localhost | 6333 | none | none, or the read-only key from `docker/qdrant/README.md` for `qdrant-auth` on 6343 | none (one connection is one server) | +| **Weaviate** | localhost | 18280 | none | none, or the `viewer` key from `docker/weaviate/README.md` for `weaviate-auth` on 18283 | none (one connection is one server) | | **InfluxDB (InfluxQL)**, 1.13.1 | localhost | 8087 | reader (READ on `home`), or admin | readonly123, or password123 for admin | `home` | | **InfluxDB (InfluxQL)**, 2.9.1 | localhost | 8086 | none | the read-only token for bucket `home` (`docker/influxdb/README.md` says how to read it), or the all-access token `libredb-influxdb2-operator-token` | `home` (org `libredb`) | | **InfluxDB 3 (SQL)**, 3.12.0 Core | localhost | 8181 | none | the admin token `apiv3_libredb-influxdb3-admin-token` | `home`; the same server answers an InfluxDB (InfluxQL) connection, and the file-limit fixture `influxdb3-filelimit` (profile `influxdb-filelimit`) listens on 8182 | @@ -1005,7 +1009,7 @@ extraEnvFrom: | `defaults` | No | Default values merged into all connections | | `connections[].id` | Yes | Unique slug (`[a-z0-9-]+`, max 64 chars) | | `connections[].name` | Yes | Display name in UI | -| `connections[].type` | Yes | `postgres`, `mysql`, `sqlite`, `libsql`, `duckdb`, `oracle`, `db2`, `mssql`, `clickhouse`, `druid`, `trino`, `bigquery`, `databend`, `snowflake`, `spark`, `cassandra`, `elasticsearch`, `opensearch`, `mongodb`, `couchbase`, `firestore`, `redis`, `prometheus`, `kafka`, `mqtt`, `rabbitmq`, `etcd`, `neo4j`, `milvus`, `qdrant`, `influxdb`, `influxdb3`, `oxia`, `s3`, `kubernetes`, `opcua`, `mtconnect`, `modbus`, `netconf`, `snmp`, `sparkplug`, `libredb` | +| `connections[].type` | Yes | `postgres`, `mysql`, `sqlite`, `libsql`, `duckdb`, `oracle`, `db2`, `mssql`, `clickhouse`, `druid`, `trino`, `bigquery`, `databend`, `snowflake`, `spark`, `cassandra`, `elasticsearch`, `opensearch`, `mongodb`, `couchbase`, `firestore`, `redis`, `prometheus`, `kafka`, `mqtt`, `rabbitmq`, `etcd`, `neo4j`, `milvus`, `qdrant`, `weaviate`, `influxdb`, `influxdb3`, `oxia`, `s3`, `kubernetes`, `opcua`, `mtconnect`, `modbus`, `netconf`, `snmp`, `sparkplug`, `libredb` | | `connections[].roles` | Yes | `["*"]` (everyone), `["admin"]`, `["user"]`, or `["admin", "user"]` | | `connections[].managed` | No | `true` = admin-controlled, not editable in the UI (default), `false` = editable copy for user | | `connections[].readOnly` | No | `true` refuses every write on an engine that enforces it (etcd); refused on an unmanaged connection | diff --git a/README_es.md b/README_es.md index 9a2b01b43b..85f45b9981 100644 --- a/README_es.md +++ b/README_es.md @@ -132,9 +132,9 @@ Tomada en serio, esa frase deja de ser una preferencia y se vuelve una especific ## Capacidades principales -### Cuarenta y uno motores, una sola interfaz +### Cuarenta y dos motores, una sola interfaz -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B Todos los motores SQL comparten el mismo explorador de esquemas, los diagramas ER, la comparación de esquemas y los paneles de monitoreo. MongoDB y Redis no son motores SQL: no tienen diagrama ER ni comparación de esquemas. Druid, Elasticsearch, OpenSearch y Trino son doblemente excepcionales: sus interfaces SQL sobre HTTP no tienen una forma de URI que este build sepa interpretar, así que se configuran por host y puerto, y las migraciones que se generan explican la limitación en lugar de inventar DDL para un motor cuyo SQL no tiene sentencias de cambio de columna. Lo mismo pasa con las colecciones sin esquema de Couchbase. El diagrama ER de los clústeres de búsqueda tiene cajas pero no líneas: los índices no declaran claves foráneas, y en el modelo del motor no hay ninguna que declarar. @@ -166,7 +166,8 @@ Todos los motores SQL comparten el mismo explorador de esquemas, los diagramas E | **etcd** | `@grpc/grpc-js` (JavaScript puro, gRPC, puerto 2379) | Un subconjunto de etcdctl en el editor (`get`, `put`, `del`, `txn`, leases, un `watch` acotado, miembros, alarmas, usuarios y roles); grupos por prefijo de clave en el árbol y cada clave en el panel de claves; el valor de una clave editado en una transacción condicionada a su revisión; compactación, desfragmentación y desactivación de alarmas para administradores, cada una confirmada escribiendo el nombre de la conexión. Se rechaza toda escritura bajo un prefijo de Kubernetes o en `compact_rev_key`, y nunca se muestran los Secrets de Kubernetes ni los valores protobuf o cifrados. TLS con CA propia, certificados de cliente (su Common Name como usuario de etcd) e inicio de sesión con contraseña solo sobre TLS; túnel SSH; un modo de solo lectura declarado en la semilla | | **Neo4j** | `neo4j-driver-lite` (JavaScript puro, Bolt, puerto 7687) | Cypher de solo lectura en el editor, una sentencia por ejecución, contra Neo4j 5.26 LTS; etiquetas de nodo y tipos de relación con sus propiedades como columnas, índices y restricciones en el árbol; nodos, relaciones y caminos como celdas JSON etiquetadas en la grilla, con los enteros de 64 bits y los valores temporales exactos; los paneles de monitoreo que ofrece Community. Cada sentencia pasa una política de lectura sobre sus tokens, luego la clasificación del propio servidor mediante `EXPLAIN` (que una forma SHOW permitida omite), y corre en una sesión READ, así que una escritura tendría que vencer las tres. Sin vista de EXPLAIN ni PROFILE, sin mantenimiento, sin ejecución del agente y sin `run_read_query` de MCP. TLS con CA propia y túnel SSH; sin cadena de conexión | | **Milvus** | `@grpc/grpc-js` (JavaScript puro, gRPC, puerto 19530) | Las peticiones REST v2 propias de Milvus en el editor (`POST /v2/vectordb/` con un cuerpo JSON) para lecturas, conteos exactos y búsquedas vectoriales sobre todo tipo de vector, incluidas BM25 y la búsqueda híbrida; bases de datos y colecciones en el árbol con campos, particiones, índices y estado de carga; celdas vectoriales con su dimensión y copia del valor completo; Load y Release para administradores, con vista previa y confirmación. Studio no escribe datos, rechaza las peticiones que harían que el servidor llame a otro servicio y avisa de la contraseña `root` por defecto. TLS con CA propia y certificados de cliente; la contraseña solo sobre TLS, en loopback o por el túnel SSH; un modo de solo lectura declarado en la semilla | -| **Qdrant** | ninguno, HTTP (la API REST de Qdrant, puerto 6333) | Las peticiones REST propias de Qdrant en el editor (`MÉTODO /ruta` con un cuerpo JSON), diecisiete rutas de lectura: lecturas de puntos, scroll, conteos exactos, facetas, y consultas, lotes y consultas agrupadas sobre vectores densos, dispersos y multivector, incluido el modelo BM25 local; colecciones en el árbol con sus vectores, índices de payload y una vista muestreada de las claves del payload; celdas vectoriales con su dimensión y copia del valor completo. Studio no escribe nada, rechaza toda entrada de inferencia salvo BM25 local y avisa de un JWT sin caducidad o con acceso de gestión. TLS con CA propia y certificados de cliente; la clave solo sobre TLS, en loopback o por el túnel SSH; un modo de solo lectura declarado en la semilla | +| **Qdrant** | ninguno, HTTP (la API REST de Qdrant, Weaviate, puerto 6333) | Las peticiones REST propias de Qdrant en el editor (`MÉTODO /ruta` con un cuerpo JSON), diecisiete rutas de lectura: lecturas de puntos, scroll, conteos exactos, facetas, y consultas, lotes y consultas agrupadas sobre vectores densos, dispersos y multivector, incluido el modelo BM25 local; colecciones en el árbol con sus vectores, índices de payload y una vista muestreada de las claves del payload; celdas vectoriales con su dimensión y copia del valor completo. Studio no escribe nada, rechaza toda entrada de inferencia salvo BM25 local y avisa de un JWT sin caducidad o con acceso de gestión. TLS con CA propia y certificados de cliente; la clave solo sobre TLS, en loopback o por el túnel SSH; un modo de solo lectura declarado en la semilla | +| **Weaviate** | ninguno, HTTP (la API REST de Weaviate, y GraphQL para las búsquedas de un servidor anterior a 1.39.7, puerto 8080) | Las peticiones REST propias de Weaviate en el editor (`MÉTODO /v1/ruta` con un cuerpo JSON), diecisiete rutas de lectura: listas de objetos y lecturas por id, búsquedas BM25, híbridas con alpha 0, near-vector y near-object, filtros y conteos de agregación, escritas con la forma de la búsqueda REST en todo servidor y ejecutadas por GraphQL en uno anterior a 1.39.7; colecciones en el árbol con sus propiedades y vectores, tenants y alias en el Source de la colección, conteos exactos. Studio no escribe nada, rechaza toda petición que enviaría texto a un modelo y nunca despierta un tenant frío. TLS con CA propia; la clave de API o el token de acceso OIDC solo sobre TLS, en loopback o por el túnel SSH; probado en Weaviate 1.40.2, 1.38.22 y 1.37.4 | | **InfluxDB (InfluxQL)** | ninguno, HTTP (la API v1 de InfluxDB, puerto 8086) | InfluxQL de solo lectura en el editor contra InfluxDB 1.x, 2.x y 3 por la API v1 `/query`, un `SELECT`, `SHOW` o `EXPLAIN` por ejecución; bases de datos y measurements en el árbol, con los tags y fields de cada measurement como columnas, y enteros por encima de 2^53 y marcas de tiempo en nanosegundos exactos en la cuadrícula. Solo lectura diga lo que diga la conexión: en 1.x y 2.x la política de lectura propia de Studio es la única barrera antes de `DROP DATABASE`, así que toda otra sentencia se rechaza antes de cualquier petición, y no se llega a ningún endpoint de escritura. Usuario y contraseña, o un token en el campo de contraseña; una credencial por HTTP sin cifrar hacia un host que no es loopback ni va por túnel se rechaza salvo que la conexión lo consienta; `_internal` nunca se lee en un servidor InfluxDB 3 | | **InfluxDB 3 (SQL)** | ninguno, HTTP (la API SQL de InfluxDB 3, puerto 8181) | SQL de solo lectura en el editor contra InfluxDB 3 Core y Enterprise; las tablas de la base de datos de la conexión en el árbol, con sus columnas. Solo lectura diga lo que diga la conexión: la tabla de rutas no llega a ningún endpoint de escritura, tokens, caché o plugins, y de los de configuración solo al listado de bases de datos, un GET, toda sentencia que no empiece por una palabra clave de lectura se rechaza antes de cualquier petición, y el planificador del servidor rechaza además toda escritura. Un token y ningún usuario; un token por HTTP sin cifrar hacia un host que no es loopback ni va por túnel se rechaza salvo que la conexión lo consienta; apuntada a un servidor 1.x o 2.x, indica que se elija InfluxDB (InfluxQL) | | **Oxia** | `@grpc/grpc-js` (JavaScript puro, gRPC, puerto 6648) | Comandos `oxia client` de solo lectura (`get`, `list`, `range-scan`), shards en el árbol y cada clave en el panel de claves | diff --git a/README_hi.md b/README_hi.md index f740b212b5..3e4bff5a29 100644 --- a/README_hi.md +++ b/README_hi.md @@ -133,9 +133,9 @@ LibreDB Studio दूसरा रास्ता चुनता है: **tool ## मुख्य क्षमताएँ -### इकतालीस engines, एक interface +### बयालीस engines, एक interface -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B सभी SQL engines एक ही schema browser, ER diagram, schema diff और monitoring dashboard इस्तेमाल करते हैं। MongoDB और Redis SQL engines नहीं हैं, इसलिए उनमें ER diagram और schema diff नहीं है। Druid, Elasticsearch, OpenSearch और Trino दोहरे अपवाद हैं: उनके HTTP SQL interface का कोई ऐसा URI रूप नहीं है जिसे यह build पढ़ सके, इसलिए उन्हें सिर्फ़ host/port से configure किया जाता है। साथ ही, generated migration सीधे अपनी सीमा बताता है, बजाय ऐसे engine के लिए DDL बनाने के जिसकी SQL में column बदलने का कोई statement ही नहीं है। Couchbase के schemaless collections पर भी यही लागू है। Search clusters के ER diagram में सिर्फ़ boxes होते हैं, कोई line नहीं: indexes foreign keys declare नहीं करते, और engine के model में declare करने के लिए foreign key होती ही नहीं। @@ -168,6 +168,7 @@ PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · Du | **Neo4j** | `neo4j-driver-lite` (pure JavaScript, Bolt, port 7687) | Neo4j 5.26 LTS के लिए editor में read-only Cypher, हर run में एक statement; tree में node labels और relationship types (उनकी properties columns के रूप में), indexes और constraints; grid में nodes, relationships और paths tagged JSON cells के रूप में, 64-bit integers और temporal values बिना precision खोए; Community जो monitoring panels देता है। हर statement पहले उसके tokens पर read policy से, फिर `EXPLAIN` के ज़रिए server के अपने classification से (जिसे allowlisted SHOW form छोड़ देता है) गुज़रता है और READ session में चलता है, इसलिए किसी write को तीनों layers तोड़नी होंगी। EXPLAIN या PROFILE view, maintenance, agent execution और MCP `run_read_query` नहीं; Custom CA के साथ TLS और SSH tunnel; connection string नहीं | | **Milvus** | `@grpc/grpc-js` (pure JavaScript, gRPC, port 19530) | Editor में Milvus की अपनी REST v2 requests (एक JSON body के साथ `POST /v2/vectordb/`) से reads, exact counts और हर vector type पर vector search, BM25 और hybrid search सहित; tree में databases और collections, उनके fields, partitions, indexes और load state; dimension के साथ vector cells और पूरी value का copy; admins के लिए preview और confirmation के साथ Load और Release। Studio कोई data नहीं लिखता, server से किसी दूसरी service को call कराने वाली requests refuse करता है, और default `root` password पर warning देता है। Custom CA और client certificates के साथ TLS; password सिर्फ़ TLS पर, loopback पर या SSH tunnel से; seed में घोषित read-only mode | | **Qdrant** | कोई नहीं, HTTP (Qdrant का REST API, port 6333) | Editor में Qdrant की अपनी REST requests (एक JSON body के साथ `METHOD /path`), सत्रह read routes: points पढ़ना, scroll, exact counts, facets, और dense, sparse और multivector data पर queries, batches और grouped queries, local BM25 model सहित; tree में collections, उनके vectors, payload indexes और payload keys का sampled view; dimension के साथ vector cells और पूरी value का copy। Studio कुछ नहीं लिखता, local BM25 के सिवा हर inference input refuse करता है, और बिना expiry या manage access वाले JWT पर warning देता है। Custom CA और client certificates के साथ TLS; key सिर्फ़ TLS पर, loopback पर या SSH tunnel से; seed में घोषित read-only mode | +| **Weaviate** | कोई नहीं, HTTP (Weaviate का REST API, और 1.39.7 से पुराने server पर searches के लिए GraphQL, port 8080) | Editor में Weaviate की अपनी REST requests (एक JSON body के साथ `METHOD /v1/path`), सत्रह read routes: objects की list और id से read, BM25, alpha 0 वाला hybrid, near-vector और near-object searches, filters और aggregate counts, हर server पर REST search के रूप में लिखी जाती हैं और 1.39.7 से पुराने server पर GraphQL से चलती हैं; tree में collections, उनकी properties और vectors, tenants और aliases collection के Source में, exact counts। Studio कुछ नहीं लिखता, हर वह request refuse करता है जो text किसी model को भेजे, और किसी cold tenant को कभी नहीं जगाता। Custom CA के साथ TLS; API key या OIDC access token सिर्फ TLS पर, loopback पर या SSH tunnel से; Weaviate 1.40.2, 1.38.22 और 1.37.4 पर test किया गया | | **InfluxDB (InfluxQL)** | कोई नहीं, HTTP (InfluxDB का v1 API, port 8086) | Editor में read-only InfluxQL, v1 `/query` API पर InfluxDB 1.x, 2.x और 3 के लिए, हर run में एक `SELECT`, `SHOW` या `EXPLAIN`; tree में databases और measurements, हर measurement के tags और fields उसके columns के रूप में, और grid में 2^53 से बड़े integers और nanosecond timestamps सटीक। Connection में कुछ भी लिखा हो, read-only: 1.x और 2.x पर `DROP DATABASE` से पहले Studio की अपनी read policy ही अकेली रोक है, इसलिए हर दूसरा statement किसी भी request से पहले refuse होता है, और कोई write endpoint नहीं छुआ जाता। User और password, या password field में token; plain HTTP पर ऐसे host को credential, जो न loopback है न tunnel से, तब तक refuse होता है जब तक connection सहमति न दे; InfluxDB 3 server पर `_internal` कभी नहीं पढ़ा जाता | | **InfluxDB 3 (SQL)** | कोई नहीं, HTTP (InfluxDB 3 का SQL API, port 8181) | Editor में read-only SQL, InfluxDB 3 Core और Enterprise के लिए; tree में connection के database की tables, उनके columns के साथ। Connection में कुछ भी लिखा हो, read-only: route table किसी write, token, cache या plugin endpoint तक नहीं पहुँचती, और configure endpoints में से सिर्फ़ database listing तक, एक GET, जो statement read keyword से शुरू नहीं होता वह किसी भी request से पहले refuse होता है, और उसके ऊपर server का planner हर write refuse करता है। एक token, कोई user नाम नहीं; plain HTTP पर ऐसे host को token, जो न loopback है न tunnel से, तब तक refuse होता है जब तक connection सहमति न दे; 1.x या 2.x server पर लगाने पर InfluxDB (InfluxQL) चुनने को कहता है | | **Oxia** | `@grpc/grpc-js` (pure JavaScript, gRPC, port 6648) | Read-only `oxia client` commands (`get`, `list`, `range-scan`), tree में shards और Keys panel में हर key | diff --git a/README_ja.md b/README_ja.md index bf5955b2ac..ca33448642 100644 --- a/README_ja.md +++ b/README_ja.md @@ -131,9 +131,9 @@ LibreDB Studioは逆向きです。**データをツールのところへ持っ ## 主な機能 -### 41のエンジン、1つのインターフェース +### 42のエンジン、1つのインターフェース -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B スキーマエクスプローラ、ER図、スキーマ差分、モニタリングは全SQLエンジンで共通です。MongoDBとRedisはSQLエンジンではないため、ER図とスキーマ差分はありません。Druid、Elasticsearch、OpenSearch、TrinoはこのビルドがパースできるURI形式を持たないためhostとportで設定する二重の例外で、生成されるマイグレーションもDDLを出力せず制約を明示します(Couchbaseのスキーマレスなコレクションも同様)。検索クラスタのER図は箱だけで線がありません。インデックスは外部キーを宣言せず、エンジンのモデルにも宣言できる外部キーが存在しないためです。 @@ -166,6 +166,7 @@ PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · Du | **Neo4j** | `neo4j-driver-lite`(純粋なJavaScript、Bolt、7687) | Neo4j 5.26 LTSに対する読み取り専用のCypherエディタ(1回の実行で1ステートメント)。ツリーにはノードラベルとリレーションシップタイプ(プロパティを列として)、インデックスと制約。ノード、リレーションシップ、パスはタグ付きJSONセルとしてグリッドに表示され、64ビット整数と日時の値は正確に保たれます。Communityが提供する監視パネル。すべてのステートメントはトークン単位の読み取りポリシー、`EXPLAIN`によるサーバー自身の分類(許可されたSHOW形式はこれを省略)、READセッションを通るため、書き込みは3つの層をすべて破る必要があります。EXPLAIN・PROFILEビュー、メンテナンス、エージェント実行、MCPの`run_read_query`はありません。独自CAによるTLS、SSHトンネル。接続文字列なし | | **Milvus** | `@grpc/grpc-js`(純粋なJavaScript、gRPC、19530) | エディタでMilvus独自のREST v2リクエスト(1つのJSONボディを持つ`POST /v2/vectordb/<ルート>`)による読み取り、正確な件数、すべてのベクトル型でのベクトル検索(BM25とハイブリッド検索を含む)。ツリーにはデータベースとコレクション、そのフィールド、パーティション、インデックス、ロード状態。次元付きのベクトルセルと値全体のコピー。管理者向けのLoadとRelease(プレビューと確認付き)。Studioはデータを書き込まず、サーバーが別のサービスを呼び出すリクエストを拒否し、デフォルトの`root`パスワードを警告します。独自CAとクライアント証明書によるTLS。パスワードはTLS上、ループバック、またはSSHトンネル経由のみ。シードで宣言する読み取り専用モード | | **Qdrant** | なし、HTTP(QdrantのREST API、6333) | エディタでQdrant独自のRESTリクエスト(1つのJSONボディを持つ`メソッド /パス`)、17の読み取りルート:ポイントの取得、スクロール、正確な件数、ファセット、そして密・疎・マルチベクトルに対するクエリ、バッチ、グループ化クエリ(ローカルBM25モデルを含む)。ツリーにはコレクションとそのベクトル、payloadインデックス、payloadキーのサンプル表示。次元付きのベクトルセルと値全体のコピー。Studioは何も書き込まず、ローカルBM25以外の推論入力をすべて拒否し、有効期限のないJWTや管理権限を持つJWTを警告します。独自CAとクライアント証明書によるTLS。キーはTLS上、ループバック、またはSSHトンネル経由のみ。シードで宣言する読み取り専用モード | +| **Weaviate** | なし、HTTP(WeaviateのREST API、1.39.7より前のサーバーでは検索にGraphQL、8080) | エディタでWeaviate独自のRESTリクエスト(1つのJSONボディを持つ`メソッド /v1/パス`)、17の読み取りルート:オブジェクトの一覧とid指定の読み取り、BM25、alpha 0のハイブリッド、near-vectorとnear-objectの検索、フィルタ、集計件数。検索はどのサーバーでもREST検索の形で書き、1.39.7より前のサーバーではGraphQLで実行。ツリーにはコレクションとそのプロパティ、ベクトル。テナントとエイリアスはコレクションのSourceに表示し、件数は正確。Studioは何も書き込まず、テキストをモデルに送るリクエストをすべて拒否し、コールドテナントを起こしません。独自CAによるTLS。APIキーやOIDCアクセストークンはTLS上、ループバック、またはSSHトンネル経由のみ。Weaviate 1.40.2、1.38.22、1.37.4でテスト済み | | **InfluxDB (InfluxQL)** | なし、HTTP(InfluxDBのv1 API、8086) | エディタで読み取り専用のInfluxQL。v1 `/query` API経由でInfluxDB 1.x、2.x、3を対象に、1回の実行につき`SELECT`、`SHOW`、`EXPLAIN`のいずれか1文。ツリーにはデータベースとmeasurement、measurementのタグとフィールドを列として表示。2^53を超える整数とナノ秒のタイムスタンプはグリッドで正確なまま。接続の設定にかかわらず読み取り専用:1.xと2.xでは`DROP DATABASE`の手前にあるのはStudio自身の読み取りポリシーだけなので、それ以外の文はリクエストの前にすべて拒否し、書き込みエンドポイントには一切届きません。ユーザーとパスワード、またはパスワード欄にトークン。ループバックでもトンネル経由でもないホストへ平文HTTPで送る資格情報は、接続が同意しない限り拒否。InfluxDB 3サーバーの`_internal`は読みません | | **InfluxDB 3 (SQL)** | なし、HTTP(InfluxDB 3のSQL API、8181) | エディタで読み取り専用のSQL。InfluxDB 3 CoreとEnterpriseが対象。ツリーには接続先データベースのテーブルとその列。接続の設定にかかわらず読み取り専用:ルート表は書き込み、トークン、キャッシュ、プラグインのエンドポイントに届かず、設定のエンドポイントで届くのはデータベース一覧のGETだけで、読み取りキーワードで始まらない文はリクエストの前に拒否し、さらにサーバーのプランナーがあらゆる書き込みを拒否します。トークンのみでユーザー名なし。ループバックでもトンネル経由でもないホストへ平文HTTPで送るトークンは、接続が同意しない限り拒否。1.xや2.xのサーバーに向けるとInfluxDB (InfluxQL)を選ぶよう案内します | | **Oxia** | `@grpc/grpc-js`(純粋なJavaScript、gRPC、6648) | 読み取り専用の`oxia client`コマンド(`get`、`list`、`range-scan`)。ツリーにはシャード、キーパネルにはすべてのキー | diff --git a/README_ko.md b/README_ko.md index b29f61c66d..def7ad1f9a 100644 --- a/README_ko.md +++ b/README_ko.md @@ -151,7 +151,7 @@ LibreDB Studio는 다른 방식으로 접근합니다. **데이터를 도구가 LibreDB Studio는 데이터가 있는 환경에 직접 배포하는 방식을 지향합니다. Container, Helm chart, Operator, PaaS One-click template을 이용해 배포하거나, `npm i @libredb/studio`를 사용해 자신의 제품에 직접 임베드할 수도 있습니다. 데이터베이스를 외부에 노출할 필요도 없습니다. -41개의 엔진을 하나의 인터페이스에서 사용할 수 있습니다. PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B를 모두 동일한 브라우저 환경에서 다룰 수 있으며, 각 엔진이 제공하는 정보에 따라 ER 다이어그램, schema 비교, 모니터링 기능도 사용할 수 있습니다. 이 가운데 Druid, Elasticsearch, OpenSearch는 SQL 인터페이스에서 데이터 조회만 지원하므로 LibreDB Studio에서도 읽기 전용으로 제공됩니다. 이들 엔진에서는 `UPDATE`나 `CREATE TABLE` 같은 명령을 지원하지 않기 때문에, LibreDB Studio에서도 해당 기능을 사용할 수 없는 것으로 명확하게 표시합니다. Cassandra의 경우 제공하는 행 수와 용량 정보가 정확하지 않아 객체 브라우저에 해당 정보를 표시하지 않습니다. 부정확한 값을 보여주는 것보다 아예 표시하지 않는 방식을 택한 것입니다. Cassandra에서 제공하는 파티션 수 추정치는 디스크에 기록된 파일을 기반으로 하는데, 실제 테스트에서는 500개의 행이 있는 테이블이 143개로 추정되기도 했습니다. Trino는 데이터베이스가 아니라 쿼리 엔진이라는 점에서 또 다른 차이가 있습니다. 따라서 primary key나 index 정보를 제공하지 않으며, 표시되는 데이터 크기 역시 Trino 자체가 아닌 연결된 각 connector의 시스템을 기준으로 합니다. +42개의 엔진을 하나의 인터페이스에서 사용할 수 있습니다. PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B를 모두 동일한 브라우저 환경에서 다룰 수 있으며, 각 엔진이 제공하는 정보에 따라 ER 다이어그램, schema 비교, 모니터링 기능도 사용할 수 있습니다. 이 가운데 Druid, Elasticsearch, OpenSearch는 SQL 인터페이스에서 데이터 조회만 지원하므로 LibreDB Studio에서도 읽기 전용으로 제공됩니다. 이들 엔진에서는 `UPDATE`나 `CREATE TABLE` 같은 명령을 지원하지 않기 때문에, LibreDB Studio에서도 해당 기능을 사용할 수 없는 것으로 명확하게 표시합니다. Cassandra의 경우 제공하는 행 수와 용량 정보가 정확하지 않아 객체 브라우저에 해당 정보를 표시하지 않습니다. 부정확한 값을 보여주는 것보다 아예 표시하지 않는 방식을 택한 것입니다. Cassandra에서 제공하는 파티션 수 추정치는 디스크에 기록된 파일을 기반으로 하는데, 실제 테스트에서는 500개의 행이 있는 테이블이 143개로 추정되기도 했습니다. Trino는 데이터베이스가 아니라 쿼리 엔진이라는 점에서 또 다른 차이가 있습니다. 따라서 primary key나 index 정보를 제공하지 않으며, 표시되는 데이터 크기 역시 Trino 자체가 아닌 연결된 각 connector의 시스템을 기준으로 합니다. 가장 최근에 추가된 엔진은 Sparkplug B입니다. MQTT로 broker 하나를 읽고, 에지 노드의 출생 인증서가 선언한 metric과 그 뒤의 데이터 메시지가 실어 오는 값을 읽습니다. 구조적으로 읽기 전용입니다. 인코더에는 PUBLISH를 쓰는 함수가 없고, CONNECT는 will을 싣지 않습니다. 5.4가 에지 노드의 사망 인증서를 그 will로 등록하므로, will을 설정한 읽기 측은 자기 소켓이 끊길 때 사망을 발행하게 됩니다. 그룹과 에지 노드는 컨테이너이고, metric은 한 행으로서 그 값과 타임스탬프와 정의는 그것을 선언한 인증서에서 오며, 시퀀스 간격은 추측하지 않고 연속된 두 데이터 메시지에서 읽습니다. @@ -186,7 +186,7 @@ etcd는 etcd gRPC API를 통해 etcdctl의 일부 명령으로 key를 읽고 쓸 Apache Kafka는 JSON 읽기 요청을 통해 Kafka protocol로 partition, offset 또는 timestamp를 기준으로 topic의 message를 조회할 수 있습니다. 브라우저에서는 topic, lag가 포함된 consumer group, broker를 확인할 수 있습니다. Kafka는 읽기 전용으로 지원되며 Studio에서는 message를 produce하거나 offset을 commit하지 않고, consumer group에 join하거나 topic을 생성하지도 않습니다. -Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Neo4j, etcd, Apache Kafka, MQTT, RabbitMQ, Prometheus는 MongoDB나 Redis와 마찬가지로 SQL을 사용하지 않습니다. InfluxQL은 SQL과 비슷해 보이지만 별도의 query language이며 한 번에 하나의 `SELECT`, `SHOW`, `EXPLAIN`을 실행합니다. 반면 InfluxDB 3 (SQL)은 SQL을 사용합니다. Prometheus는 Prometheus HTTP API와 PromQL을 사용해 metric, rule, scrape target을 조회할 수 있으며, Studio에서 서버의 write 또는 관리 endpoint를 호출하지 않기 때문에 읽기 전용으로 지원됩니다. +Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Weaviate, Neo4j, etcd, Apache Kafka, MQTT, RabbitMQ, Prometheus는 MongoDB나 Redis와 마찬가지로 SQL을 사용하지 않습니다. InfluxQL은 SQL과 비슷해 보이지만 별도의 query language이며 한 번에 하나의 `SELECT`, `SHOW`, `EXPLAIN`을 실행합니다. 반면 InfluxDB 3 (SQL)은 SQL을 사용합니다. Prometheus는 Prometheus HTTP API와 PromQL을 사용해 metric, rule, scrape target을 조회할 수 있으며, Studio에서 서버의 write 또는 관리 endpoint를 호출하지 않기 때문에 읽기 전용으로 지원됩니다. 주요 기능을 별도의 유료 기능으로 제한하지도 않습니다. SSO, ER 다이어그램, AI 기능을 비롯한 모든 NoSQL 엔진이 MIT 라이선스로 제공되는 버전에 포함되어 있습니다. MIT 라이선스는 이러한 아키텍처를 가능하게 하기 위한 필수 조건입니다. 사용자 단위로 라이선스 비용을 부과하거나 요금제에 따라 기능을 제한한다면 필요한 모든 환경에 자유롭게 배포하기 어렵기 때문입니다. @@ -194,7 +194,7 @@ Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Neo4j, etcd, Apache Kafka, MQTT, Rabb * **데이터가 있는 환경에 직접 배포**: Container, Helm chart, Rancher, OpenShift Operator, PaaS One-click template을 사용하거나 npm으로 직접 임베드할 수 있습니다. -* **41개의 엔진, 하나의 인터페이스**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B. +* **42개의 엔진, 하나의 인터페이스**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B. * **어디서든 사용 가능**: 브라우저와 모바일은 물론 Windows, macOS, Linux 데스크톱에서도 사용할 수 있습니다. @@ -204,7 +204,7 @@ Oxia, InfluxDB (InfluxQL), Milvus, Qdrant, Neo4j, etcd, Apache Kafka, MQTT, Rabb

-다중 데이터베이스 Connection 관리
PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Redis, SQLite, DuckDB, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B에 연결할 수 있으며, SSL/TLS와 SSH 터널을 지원합니다. 단, Kafka는 TLS만 지원하며 SSH 터널은 지원하지 않고, OPC UA는 공용 패널 대신 자체 전송 계층 보안을 사용하며, SNMP는 둘 다 없습니다. 전송이 UDP라 공용 터널로 실어 나를 수 없고, v3의 보안은 메시지 안에 있습니다. +다중 데이터베이스 Connection 관리
PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Cassandra, Redis, SQLite, DuckDB, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage, Kubernetes, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B에 연결할 수 있으며, SSL/TLS와 SSH 터널을 지원합니다. 단, Kafka는 TLS만 지원하며 SSH 터널은 지원하지 않고, OPC UA는 공용 패널 대신 자체 전송 계층 보안을 사용하며, SNMP는 둘 다 없습니다. 전송이 UDP라 공용 터널로 실어 나를 수 없고, v3의 보안은 메시지 안에 있습니다.

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/libredb/libredb-studio) @@ -361,6 +361,7 @@ Standalone 애플리케이션에서만 사용할 수 있습니다. 임베드용 | **Neo4j** | `neo4j-driver-lite`(순수 JavaScript, Bolt, 포트 7687) | Neo4j 5.26 LTS용 읽기 전용 Cypher Editor로 한 번에 하나의 statement를 실행합니다. 트리에는 node label과 relationship type(property는 column으로 표시), index, constraint가 표시됩니다. node, relationship, path는 결과 Table에서 label이 포함된 JSON cell로 표시되며 64비트 integer와 시간 값의 정밀도를 유지합니다. Community Edition에서 제공하는 모니터링 Panel도 지원합니다. 각 statement는 token 기반 읽기 정책, 서버의 `EXPLAIN` 분류(허용된 SHOW 형식은 제외), READ session을 차례로 거쳐 실행됩니다. EXPLAIN/PROFILE View, 유지보수 작업, Agent 실행, MCP `run_read_query`는 지원하지 않습니다. custom CA TLS와 SSH 터널을 지원하며 Connection string은 지원하지 않습니다. | | **Milvus** | `@grpc/grpc-js`(순수 JavaScript, gRPC, 포트 19530) | 에디터에서 Milvus 자체 REST v2 요청(JSON body를 포함한 `POST /v2/vectordb/`)을 사용해 읽기, 정확한 count, BM25와 hybrid search를 포함한 모든 vector type의 vector search를 수행합니다. 트리에는 database, collection, field, partition, index, load 상태가 표시되며 vector cell에는 차원이 표시되고 전체 값을 복사할 수 있습니다. 관리자는 preview와 확인 절차를 거쳐 Load와 Release를 실행할 수 있습니다. Studio는 데이터를 쓰지 않으며 서버가 다른 서비스를 호출하도록 만드는 요청을 거부하고 기본 `root` 비밀번호 사용 시 경고합니다. custom CA와 client certificate를 사용하는 TLS를 지원하며 password는 TLS, loopback 주소 또는 SSH 터널을 통해서만 사용할 수 있습니다. Seed Connection으로 지정하는 읽기 전용 모드도 지원합니다. | | **Qdrant** | Driver 없음, HTTP 사용(Qdrant REST API, 포트 6333) | 에디터에서 Qdrant 자체 REST 요청(JSON body를 포함한 `METHOD /path`)을 사용합니다. point 조회, scroll, 정확한 count, facet, dense·sparse·multi-vector 데이터의 query, batch query, group query 등 17개의 읽기 전용 route를 지원하며 local BM25 model도 사용할 수 있습니다. 트리에는 collection과 vector, payload index, payload key의 sample view가 표시되며 vector cell에는 차원이 표시되고 전체 값을 복사할 수 있습니다. Studio는 데이터를 쓰지 않으며 local BM25 이외의 inference input을 거부하고, 만료 시간이 없거나 관리 권한이 있는 JWT 사용 시 경고합니다. custom CA와 client certificate를 사용하는 TLS를 지원하며 API key는 TLS, loopback 주소 또는 SSH 터널을 통해서만 사용할 수 있습니다. Seed Connection으로 지정하는 읽기 전용 모드도 지원합니다. | +| **Weaviate** | Driver 없음, HTTP 사용(Weaviate REST API, 1.39.7 이전 서버의 검색은 GraphQL, 포트 8080) | 에디터에서 Weaviate 자체 REST 요청(JSON body를 포함한 `METHOD /v1/path`)을 사용합니다. object 목록과 id 조회, BM25, alpha 0 hybrid, near-vector·near-object 검색, filter, aggregate count 등 17개의 읽기 전용 route를 지원하며, 검색은 모든 서버에서 REST search 형태로 작성하고 1.39.7 이전 서버에서는 GraphQL로 실행합니다. 트리에는 collection과 property, vector가 표시되고 tenant와 alias는 collection의 Source에 표시되며 count는 정확한 값입니다. Studio는 데이터를 쓰지 않으며 텍스트를 모델로 보내는 요청을 모두 거부하고 cold tenant를 깨우지 않습니다. custom CA를 사용하는 TLS를 지원하며 API key나 OIDC access token은 TLS, loopback 주소 또는 SSH 터널을 통해서만 사용합니다. Weaviate 1.40.2, 1.38.22, 1.37.4에서 테스트했습니다. | | **InfluxDB (InfluxQL)** | Driver 없음, HTTP 사용(InfluxDB v1 API, 포트 8086) | InfluxDB 1.x, 2.x, 3을 v1 `/query` API로 조회하는 읽기 전용 InfluxQL Editor입니다. 한 번에 하나의 `SELECT`, `SHOW`, `EXPLAIN`을 실행합니다. 트리에는 database와 measurement가 표시되고 measurement의 tag와 field가 column으로 표시됩니다. 2^53을 초과하는 integer와 nanosecond timestamp도 결과 Table에서 정확하게 유지됩니다. Connection 설정과 관계없이 읽기 전용이며, 읽기가 아닌 statement는 요청 전에 거부되고 write endpoint도 호출하지 않습니다. username/password 또는 password 필드의 token을 사용할 수 있습니다. loopback이나 터널을 사용하지 않는 host로 인증 정보를 평문 HTTP로 보내는 것은 해당 Connection에서 명시적으로 허용하지 않는 한 거부됩니다. InfluxDB 3 서버에서는 `_internal`을 읽지 않습니다. | | **InfluxDB 3 (SQL)** | Driver 없음, HTTP 사용(InfluxDB 3 SQL API, 포트 8181) | InfluxDB 3 Core와 Enterprise용 읽기 전용 SQL Editor입니다. 트리에는 Connection이 가리키는 database의 table과 column이 표시됩니다. Connection 설정과 관계없이 읽기 전용이며 write, token, cache, plugin endpoint를 호출하지 않습니다. 설정 endpoint 중에서는 database 목록을 조회하는 GET만 사용합니다. 읽기 keyword로 시작하지 않는 statement는 요청 전에 거부되며 서버의 query planner도 write를 거부합니다. 인증에는 token만 사용하며 username은 사용하지 않습니다. loopback이나 터널을 사용하지 않는 host로 token을 평문 HTTP로 보내는 것은 해당 Connection에서 명시적으로 허용하지 않는 한 거부됩니다. 1.x 또는 2.x 서버를 지정하면 InfluxDB (InfluxQL)를 대신 사용하도록 안내합니다. | | **Oxia** | `@grpc/grpc-js`(순수 JavaScript, gRPC, 포트 6648) | 읽기 전용 `oxia client` 명령(`get`, `list`, `range-scan`)을 지원합니다. 트리에는 shard가 표시되고 key browser에서는 각 key를 확인할 수 있습니다. | @@ -376,7 +377,7 @@ Standalone 애플리케이션에서만 사용할 수 있습니다. 임베드용 | **Kubernetes** | 드라이버 없음, HTTP (API 서버의 REST API, 포트 6443) | 읽기 전용: 에디터에서 kubectl 하위 집합(`get`, `describe`, `logs`, `top`, `events`, `explain`, `auth can-i`)을 지원합니다. 트리에는 네임스페이스와 리소스 종류, 각 객체의 YAML 보기가 표시되며, 연결 대화상자에서 kubeconfig를 가져올 수 있습니다. Secret 값은 표시되지 않습니다 | | **Redis** | `ioredis` | Command Editor, key 브라우저, INFO 기반 모니터링 | -> **자체 Driver가 없는 엔진도 27개 더 지원합니다.** 위의 40개 엔진은 이 빌드에 포함된 Driver를 직접 사용합니다. 이외에도 27개 엔진이 동일한 wire protocol을 사용하는 기존 Driver를 통해 연결되므로, 40개의 네이티브 엔진과 27개의 호환 엔진으로 총 67개의 엔진을 지원합니다. MariaDB, Percona Server for MySQL, TiDB, Vitess, StarRocks, Apache Doris, OceanBase, SingleStore, Citus, Percona Distribution for PostgreSQL, ParadeDB, OrioleDB, TimescaleDB, YugabyteDB, AlloyDB Omni, Apache Cloudberry(Incubating), CockroachDB, Materialize, RisingWave는 PostgreSQL 또는 MySQL 방식으로 연결됩니다. Valkey, DragonflyDB, KeyDB, Garnet은 Redis 방식으로, FerretDB는 MongoDB 방식으로, ScyllaDB는 Cassandra 방식으로, VictoriaMetrics는 Prometheus 방식으로, Redpanda는 Apache Kafka 방식으로 연결됩니다. 각 엔진은 실제 instance에 연결해 테스트했으며 사용할 수 있는 기능은 엔진에 따라 다릅니다. MariaDB, 두 Percona 배포판, TiDB, Vitess, AlloyDB Omni, Citus, TimescaleDB, YugabyteDB, ParadeDB, OrioleDB, Valkey, DragonflyDB, KeyDB, FerretDB는 기본적으로 해당 Driver의 원래 엔진과 동일하게 동작합니다. 다만 이 가운데 세 엔진은 신뢰하기 어려운 통계 값을 반환합니다. Citus의 distributed table과 TimescaleDB의 hypertable은 행 수와 용량을 누락하는 대신 잘못된 값을 반환하며, YugabyteDB는 `ANALYZE`를 실행하기 전까지 계속 0을 반환합니다. Vitess는 이 세 엔진에 포함되지 않습니다. 행 수와 용량을 byte 단위까지 정확하게 반환하지만 실행 중인 쿼리는 취소할 수 없습니다. vtgate가 `KILL QUERY`를 거부하므로 쿼리는 끝날 때까지 계속 실행됩니다. AlloyDB Omni 역시 이 세 엔진에 포함되지 않습니다. 2,000행은 정확히 2,000행으로, 270336 byte는 정확히 270336 byte로 표시합니다. 다만 두 가지 특이점이 있습니다. `version()` 결과 어디에도 AlloyDB라는 이름이 포함되지 않아 version Panel에서는 기본 PostgreSQL 17과 구분할 수 없습니다. 또한 AlloyDB의 `google_ml` 테이블 8개가 객체 브라우저에 표시되며 Connection 권한이 있는 모든 role에서 이를 읽을 수 있습니다. StarRocks는 자신을 MySQL 5.1로 표시하며 개요, health, session Panel을 사용할 수 없습니다. 모니터링 Panel은 6개만 표시되고 session Panel에는 해당 엔진에서 반환한 거부 사유가 표시됩니다. Apache Doris는 StarRocks에서 fork된 엔진으로 개요와 health Panel만 사용할 수 없습니다. Doris의 syntax에서 지원하지 않는 statement 형식이 원인입니다. 반면 실제 통계에서는 StarRocks보다 정확합니다. 실제로 해당 데이터가 있는 테이블에서 Doris는 2,000행과 10187 byte를 반환하지만 StarRocks는 처음에는 둘 다 0으로 표시합니다. StarRocks 자체의 background statistics collector가 더 느리기 때문이며, 3.3.22에서 실제 측정한 결과 StarRocks는 약 4.5분, Doris는 약 1분이 걸렸습니다. 또한 2026-09-16 수정 이전에는 StarRocks의 `INDEX_LENGTH`가 Doris처럼 실제 0이 아니라 NULL을 반환해 provider의 SQL에서 계산한 합계까지 NULL이 되면서 용량이 계속 0으로 표시되었습니다. index는 보고되지 않으며 foreign key는 생성할 수 있고 `SHOW CONSTRAINTS`에도 표시되지만 ER 다이어그램에서는 보이지 않고 실제로 강제되지도 않습니다. Cloudberry에서는 모니터링 Panel과 테이블/index 통계를 사용할 수 없습니다. 세 기능 모두 동일한 MPP planner 제한 때문입니다. 또한 foreign key가 실제로 강제되는 것처럼 읽히지만 실제로는 그렇지 않습니다. 다만 행 수는 정확합니다. CockroachDB에서는 객체 브라우저와 용량 Panel을 사용할 수 없습니다. OceanBase는 15개 화면 중 14개에서 응답하지만 실제로 유용한 화면은 12개입니다. health Panel은 tenant에 `performance_schema` 데이터베이스 자체가 없어 바로 실패하며 모든 용량 값은 0 B로 표시됩니다. 다만 `ANALYZE TABLE`을 실행한 이후에는 행 수가 정확하게 표시됩니다. SingleStore에서는 5개 화면을 사용할 수 없는데 원인은 SingleStore가 아니라 현재 provider 구현에 있습니다. provider가 모든 statement를 prepared statement protocol로 실행하지만 SingleStore는 4개 Panel에서 필요한 `SHOW`와 `EXPLAIN` statement에 이 protocol을 허용하지 않습니다. 현재 이 가운데 4개는 복구되었으며 아직 지원되지 않는 것은 Explain Panel입니다. 해당 syntax에는 `EXPLAIN JSON`이 필요하지만 이 statement는 두 protocol 모두에서 실패합니다. 통계 값은 잘못된 값이 아니라 누락된 상태로, 2,000행의 테이블도 0행과 0 B로 표시되며 `ANALYZE`를 실행해도 달라지지 않습니다. ScyllaDB에서는 Test Connection을 포함해 6개 화면을 사용할 수 없었으며 모두 동일하게 존재하지 않는 keyspace가 원인이었습니다. 개요, health, performance metric, active session, 모니터링 Panel이 Cassandra의 `system_views` virtual table을 읽지만 ScyllaDB에는 `system_views` keyspace가 없습니다. 현재는 이 다섯 화면이 오류를 발생시키는 대신 빈 상태로 처리되므로 Test Connection이 성공하고 Connection을 저장할 수 있습니다. 이 변경 전에는 Connection 자체를 저장할 수 없었습니다. Editor와 객체 브라우저는 정상적으로 사용할 수 있으며 18가지 CQL type 모두 같은 테스트에서 확인한 Cassandra 5.0.9와 동일한 byte를 반환합니다. ParadeDB와 OrioleDB는 모두 전체 기능을 사용할 수 있지만 서로 반대되는 특성이 있습니다. ParadeDB에서는 9개의 extension으로 인해 사용자 테이블이 2개뿐이어도 객체 브라우저에 41개의 객체가 표시되며 Agent Plan 모드는 최소 권한 역할에서는 정상적으로 동작하지만, 일반 PostgreSQL과 마찬가지로 `postgres` 슈퍼유저로 실행하면 거부됩니다. 반면 OrioleDB의 브라우저는 깔끔하지만 자체 storage가 PostgreSQL의 용량 함수에 표시되지 않기 때문에 모든 index가 0 byte로 표시되고 cache hit rate는 N/A로 표시됩니다. Materialize와 RisingWave는 일부 기능만 지원합니다. 객체 브라우저에서 table, view, materialized view와 해당 컬럼을 확인할 수 있지만 행 수, 크기, 모니터링 통계는 표시되지 않습니다. Garnet은 Redis와 동일하게 동작하며 Valkey, DragonflyDB와 함께 Redis와 유사한 세 엔진 중 하나입니다. 이들의 `INFO`에는 Redis compatibility level과 자체 version이 함께 표시되며, 개요에서는 자체 version을 먼저 표시합니다. 예를 들어 `Garnet 2.1.5 (Redis 7.4.3)`과 같이 표시됩니다. 다만 두 통계 값은 숫자로 표시되지만 실제로는 정보가 없는 경우입니다. `used_memory`를 제공하지 않아 모든 용량이 0 B로 표시되고 keyspace counter를 제공하지 않아 cache hit rate가 100%로 표시됩니다. VictoriaMetrics는 Prometheus Driver를 통해 PromQL을 실행하고 metric과 해당 label column, scrape target, series 수가 가장 많은 최대 50개의 metric을 표시합니다. 다만 single-node server에서는 rule을 평가하지 않으므로 rule folder는 비어 있습니다. 또한 Prometheus endpoint 가운데 필요한 세 가지를 제공하지 않아 개요, storage statistics, scrape pool folder는 동작하지 않습니다. metric source에는 unit이 표시되지 않고 target source에는 scrape interval과 timeout이 표시되지 않는데, VictoriaMetrics에서 해당 field를 보내지 않기 때문입니다. 아직 scrape되지 않은 target도 down으로 표시됩니다. 또한 string expression은 어떠한 행도 반환하지 않고 subquery의 data point는 evaluation time을 기준으로 이전 시점부터 계산되며, 결과 옆에는 PromQL의 info 또는 warning 메시지가 표시되지 않습니다. Redpanda는 Apache Kafka Driver를 통해 모든 Kafka 화면을 지원하며 topic, lag가 포함된 consumer group, broker, 데이터 읽기를 사용할 수 있습니다. 다만 개요에서는 최대 Connection 수가 0으로 표시되고 broker source에는 설정이 9개만 표시됩니다. Redpanda가 broker configuration 요청에 해당 항목만 반환하기 때문입니다. storage statistics에는 사용률이 표시되지 않습니다. 모든 consumer group은 classic으로 표시되며, Redpanda에서는 다른 group protocol을 지원하지 않으므로 이는 정상적인 결과입니다. +> **자체 Driver가 없는 엔진도 27개 더 지원합니다.** 위의 42개 엔진은 이 빌드에 포함된 Driver를 직접 사용합니다. 이외에도 27개 엔진이 동일한 wire protocol을 사용하는 기존 Driver를 통해 연결되므로, 40개의 네이티브 엔진과 27개의 호환 엔진으로 총 67개의 엔진을 지원합니다. MariaDB, Percona Server for MySQL, TiDB, Vitess, StarRocks, Apache Doris, OceanBase, SingleStore, Citus, Percona Distribution for PostgreSQL, ParadeDB, OrioleDB, TimescaleDB, YugabyteDB, AlloyDB Omni, Apache Cloudberry(Incubating), CockroachDB, Materialize, RisingWave는 PostgreSQL 또는 MySQL 방식으로 연결됩니다. Valkey, DragonflyDB, KeyDB, Garnet은 Redis 방식으로, FerretDB는 MongoDB 방식으로, ScyllaDB는 Cassandra 방식으로, VictoriaMetrics는 Prometheus 방식으로, Redpanda는 Apache Kafka 방식으로 연결됩니다. 각 엔진은 실제 instance에 연결해 테스트했으며 사용할 수 있는 기능은 엔진에 따라 다릅니다. MariaDB, 두 Percona 배포판, TiDB, Vitess, AlloyDB Omni, Citus, TimescaleDB, YugabyteDB, ParadeDB, OrioleDB, Valkey, DragonflyDB, KeyDB, FerretDB는 기본적으로 해당 Driver의 원래 엔진과 동일하게 동작합니다. 다만 이 가운데 세 엔진은 신뢰하기 어려운 통계 값을 반환합니다. Citus의 distributed table과 TimescaleDB의 hypertable은 행 수와 용량을 누락하는 대신 잘못된 값을 반환하며, YugabyteDB는 `ANALYZE`를 실행하기 전까지 계속 0을 반환합니다. Vitess는 이 세 엔진에 포함되지 않습니다. 행 수와 용량을 byte 단위까지 정확하게 반환하지만 실행 중인 쿼리는 취소할 수 없습니다. vtgate가 `KILL QUERY`를 거부하므로 쿼리는 끝날 때까지 계속 실행됩니다. AlloyDB Omni 역시 이 세 엔진에 포함되지 않습니다. 2,000행은 정확히 2,000행으로, 270336 byte는 정확히 270336 byte로 표시합니다. 다만 두 가지 특이점이 있습니다. `version()` 결과 어디에도 AlloyDB라는 이름이 포함되지 않아 version Panel에서는 기본 PostgreSQL 17과 구분할 수 없습니다. 또한 AlloyDB의 `google_ml` 테이블 8개가 객체 브라우저에 표시되며 Connection 권한이 있는 모든 role에서 이를 읽을 수 있습니다. StarRocks는 자신을 MySQL 5.1로 표시하며 개요, health, session Panel을 사용할 수 없습니다. 모니터링 Panel은 6개만 표시되고 session Panel에는 해당 엔진에서 반환한 거부 사유가 표시됩니다. Apache Doris는 StarRocks에서 fork된 엔진으로 개요와 health Panel만 사용할 수 없습니다. Doris의 syntax에서 지원하지 않는 statement 형식이 원인입니다. 반면 실제 통계에서는 StarRocks보다 정확합니다. 실제로 해당 데이터가 있는 테이블에서 Doris는 2,000행과 10187 byte를 반환하지만 StarRocks는 처음에는 둘 다 0으로 표시합니다. StarRocks 자체의 background statistics collector가 더 느리기 때문이며, 3.3.22에서 실제 측정한 결과 StarRocks는 약 4.5분, Doris는 약 1분이 걸렸습니다. 또한 2026-09-16 수정 이전에는 StarRocks의 `INDEX_LENGTH`가 Doris처럼 실제 0이 아니라 NULL을 반환해 provider의 SQL에서 계산한 합계까지 NULL이 되면서 용량이 계속 0으로 표시되었습니다. index는 보고되지 않으며 foreign key는 생성할 수 있고 `SHOW CONSTRAINTS`에도 표시되지만 ER 다이어그램에서는 보이지 않고 실제로 강제되지도 않습니다. Cloudberry에서는 모니터링 Panel과 테이블/index 통계를 사용할 수 없습니다. 세 기능 모두 동일한 MPP planner 제한 때문입니다. 또한 foreign key가 실제로 강제되는 것처럼 읽히지만 실제로는 그렇지 않습니다. 다만 행 수는 정확합니다. CockroachDB에서는 객체 브라우저와 용량 Panel을 사용할 수 없습니다. OceanBase는 15개 화면 중 14개에서 응답하지만 실제로 유용한 화면은 12개입니다. health Panel은 tenant에 `performance_schema` 데이터베이스 자체가 없어 바로 실패하며 모든 용량 값은 0 B로 표시됩니다. 다만 `ANALYZE TABLE`을 실행한 이후에는 행 수가 정확하게 표시됩니다. SingleStore에서는 5개 화면을 사용할 수 없는데 원인은 SingleStore가 아니라 현재 provider 구현에 있습니다. provider가 모든 statement를 prepared statement protocol로 실행하지만 SingleStore는 4개 Panel에서 필요한 `SHOW`와 `EXPLAIN` statement에 이 protocol을 허용하지 않습니다. 현재 이 가운데 4개는 복구되었으며 아직 지원되지 않는 것은 Explain Panel입니다. 해당 syntax에는 `EXPLAIN JSON`이 필요하지만 이 statement는 두 protocol 모두에서 실패합니다. 통계 값은 잘못된 값이 아니라 누락된 상태로, 2,000행의 테이블도 0행과 0 B로 표시되며 `ANALYZE`를 실행해도 달라지지 않습니다. ScyllaDB에서는 Test Connection을 포함해 6개 화면을 사용할 수 없었으며 모두 동일하게 존재하지 않는 keyspace가 원인이었습니다. 개요, health, performance metric, active session, 모니터링 Panel이 Cassandra의 `system_views` virtual table을 읽지만 ScyllaDB에는 `system_views` keyspace가 없습니다. 현재는 이 다섯 화면이 오류를 발생시키는 대신 빈 상태로 처리되므로 Test Connection이 성공하고 Connection을 저장할 수 있습니다. 이 변경 전에는 Connection 자체를 저장할 수 없었습니다. Editor와 객체 브라우저는 정상적으로 사용할 수 있으며 18가지 CQL type 모두 같은 테스트에서 확인한 Cassandra 5.0.9와 동일한 byte를 반환합니다. ParadeDB와 OrioleDB는 모두 전체 기능을 사용할 수 있지만 서로 반대되는 특성이 있습니다. ParadeDB에서는 9개의 extension으로 인해 사용자 테이블이 2개뿐이어도 객체 브라우저에 42개의 객체가 표시되며 Agent Plan 모드는 최소 권한 역할에서는 정상적으로 동작하지만, 일반 PostgreSQL과 마찬가지로 `postgres` 슈퍼유저로 실행하면 거부됩니다. 반면 OrioleDB의 브라우저는 깔끔하지만 자체 storage가 PostgreSQL의 용량 함수에 표시되지 않기 때문에 모든 index가 0 byte로 표시되고 cache hit rate는 N/A로 표시됩니다. Materialize와 RisingWave는 일부 기능만 지원합니다. 객체 브라우저에서 table, view, materialized view와 해당 컬럼을 확인할 수 있지만 행 수, 크기, 모니터링 통계는 표시되지 않습니다. Garnet은 Redis와 동일하게 동작하며 Valkey, DragonflyDB와 함께 Redis와 유사한 세 엔진 중 하나입니다. 이들의 `INFO`에는 Redis compatibility level과 자체 version이 함께 표시되며, 개요에서는 자체 version을 먼저 표시합니다. 예를 들어 `Garnet 2.1.5 (Redis 7.4.3)`과 같이 표시됩니다. 다만 두 통계 값은 숫자로 표시되지만 실제로는 정보가 없는 경우입니다. `used_memory`를 제공하지 않아 모든 용량이 0 B로 표시되고 keyspace counter를 제공하지 않아 cache hit rate가 100%로 표시됩니다. VictoriaMetrics는 Prometheus Driver를 통해 PromQL을 실행하고 metric과 해당 label column, scrape target, series 수가 가장 많은 최대 50개의 metric을 표시합니다. 다만 single-node server에서는 rule을 평가하지 않으므로 rule folder는 비어 있습니다. 또한 Prometheus endpoint 가운데 필요한 세 가지를 제공하지 않아 개요, storage statistics, scrape pool folder는 동작하지 않습니다. metric source에는 unit이 표시되지 않고 target source에는 scrape interval과 timeout이 표시되지 않는데, VictoriaMetrics에서 해당 field를 보내지 않기 때문입니다. 아직 scrape되지 않은 target도 down으로 표시됩니다. 또한 string expression은 어떠한 행도 반환하지 않고 subquery의 data point는 evaluation time을 기준으로 이전 시점부터 계산되며, 결과 옆에는 PromQL의 info 또는 warning 메시지가 표시되지 않습니다. Redpanda는 Apache Kafka Driver를 통해 모든 Kafka 화면을 지원하며 topic, lag가 포함된 consumer group, broker, 데이터 읽기를 사용할 수 있습니다. 다만 개요에서는 최대 Connection 수가 0으로 표시되고 broker source에는 설정이 9개만 표시됩니다. Redpanda가 broker configuration 요청에 해당 항목만 반환하기 때문입니다. storage statistics에는 사용률이 표시되지 않습니다. 모든 consumer group은 classic으로 표시되며, Redpanda에서는 다른 group protocol을 지원하지 않으므로 이는 정상적인 결과입니다. > 각 엔진의 세부 정보와 테스트에 사용한 정확한 version은 [`docs/providers/README.md`](docs/providers/README.md#wire-compatible-engines)에서 확인할 수 있습니다. 실제 엔진에 연결해 테스트한 경우에만 해당 엔진의 이름을 문서에 추가하므로, 이 문서에 없는 엔진은 지원하지 않는다는 의미가 아니라 아직 테스트하지 않았다는 의미입니다. @@ -396,7 +397,7 @@ Standalone 애플리케이션에서만 사용할 수 있습니다. 임베드용 | **Editor** | Monaco Editor(VS Code 엔진) | Web | | **AI** | 멀티 모델(Gemini, OpenAI, Ollama, custom) | Web, 모바일 | | **인증** | JWT(`jose`) + OIDC(`openid-client`), PKCE, 역할 매핑 | Web, 모바일 | -| **데이터베이스** | PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, Databend, BigQuery, Snowflake, Apache Spark, Firestore, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B | Web, 모바일 | +| **데이터베이스** | PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, Databend, BigQuery, Snowflake, Apache Spark, Firestore, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B | Web, 모바일 | | **Chart** | Recharts(Bar, Line, Pie, Area, Scatter, Histogram, Stacked Chart) | Web, 모바일 | | **ERD** | React Flow, ELK.js(자동 layout) | Web | | **상태 및 Table** | TanStack Table 및 Virtual | Web, 모바일 | @@ -479,7 +480,7 @@ journalctl -u libredb-studio ### 사전 요구 사항 * [Bun](https://bun.sh/)(권장) 또는 Node.js 24+ -* 쿼리를 실행할 수 있는 대상 데이터베이스(PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, Databend, BigQuery, Snowflake, Apache Spark, Firestore, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP 또는 Sparkplug B) +* 쿼리를 실행할 수 있는 대상 데이터베이스(PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Apache Cassandra, Redis, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, Databend, BigQuery, Snowflake, Apache Spark, Firestore, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP 또는 Sparkplug B) ### 빠른 시작 (로컬) diff --git a/README_pt.md b/README_pt.md index 0caa876bd1..6fe90ec093 100644 --- a/README_pt.md +++ b/README_pt.md @@ -132,9 +132,9 @@ Levada a sério, essa frase deixa de ser preferência e vira especificação. ## Capacidades principais -### Quarenta e um motores, uma única interface +### Quarenta e dois motores, uma única interface -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B Todos os motores SQL compartilham o mesmo explorador de esquema, diagramas ER, comparação de esquema e painéis de monitoramento. MongoDB e Redis não são motores SQL: não têm diagrama ER nem comparação de esquema. Druid, Elasticsearch, OpenSearch e Trino são exceções duplas: suas interfaces SQL sobre HTTP não têm uma forma de URI que este build saiba interpretar, então se configuram por host e porta, e as migrações geradas explicam a limitação em vez de inventar DDL para um motor cujo SQL não tem comandos de alteração de coluna. O mesmo vale para coleções sem esquema no Couchbase. O diagrama ER dos clusters de busca tem caixas, mas não linhas: os índices não declaram chaves estrangeiras — e no modelo do motor não há nenhuma para declarar. @@ -166,7 +166,8 @@ Todos os motores SQL compartilham o mesmo explorador de esquema, diagramas ER, c | **etcd** | `@grpc/grpc-js` (JavaScript puro, gRPC, porta 2379) | Um subconjunto do etcdctl no editor (`get`, `put`, `del`, `txn`, leases, um `watch` limitado, membros, alarmes, usuários e papéis); grupos por prefixo de chave na árvore e cada chave no painel de chaves; o valor de uma chave editado em uma transação condicionada à sua revisão; compactação, desfragmentação e desarme de alarmes para administradores, cada um confirmado digitando o nome da conexão. Toda escrita sob um prefixo do Kubernetes ou em `compact_rev_key` é recusada, e Secrets do Kubernetes e valores protobuf ou criptografados nunca são exibidos. TLS com CA personalizada, certificados de cliente (o Common Name como usuário do etcd) e login com senha somente sobre TLS; túnel SSH; um modo somente leitura declarado no seed | | **Neo4j** | `neo4j-driver-lite` (JavaScript puro, Bolt, porta 7687) | Cypher somente leitura no editor, uma instrução por execução, contra o Neo4j 5.26 LTS; rótulos de nó e tipos de relacionamento com suas propriedades como colunas, índices e restrições na árvore; nós, relacionamentos e caminhos como células JSON marcadas na grade, com inteiros de 64 bits e valores temporais exatos; os painéis de monitoramento que o Community oferece. Toda instrução passa por uma política de leitura sobre seus tokens, depois pela classificação do próprio servidor via `EXPLAIN` (que uma forma SHOW permitida pula), e roda em uma sessão READ, então uma escrita teria de vencer as três camadas. Sem visão de EXPLAIN ou PROFILE, sem manutenção, sem execução pelo agente e sem `run_read_query` do MCP. TLS com CA personalizada e túnel SSH; sem string de conexão | | **Milvus** | `@grpc/grpc-js` (JavaScript puro, gRPC, porta 19530) | As requisições REST v2 do próprio Milvus no editor (`POST /v2/vectordb/` com um corpo JSON) para leituras, contagens exatas e buscas vetoriais em todo tipo de vetor, incluindo BM25 e busca híbrida; bancos de dados e coleções na árvore com campos, partições, índices e estado de carga; células vetoriais com sua dimensão e cópia do valor completo; Load e Release para administradores, com prévia e confirmação. O Studio não escreve dados, recusa requisições que fariam o servidor chamar outro serviço e alerta sobre a senha `root` padrão. TLS com CA personalizada e certificados de cliente; senha somente sobre TLS, em loopback ou pelo túnel SSH; um modo somente leitura declarado no seed | -| **Qdrant** | nenhum, HTTP (a API REST do Qdrant, porta 6333) | As requisições REST do próprio Qdrant no editor (`MÉTODO /caminho` com um corpo JSON), dezessete rotas de leitura: leituras de pontos, scroll, contagens exatas, facetas, e consultas, lotes e consultas agrupadas sobre vetores densos, esparsos e multivetor, incluindo o modelo BM25 local; coleções na árvore com seus vetores, índices de payload e uma visão amostrada das chaves do payload; células vetoriais com sua dimensão e cópia do valor completo. O Studio não escreve nada, recusa toda entrada de inferência exceto o BM25 local e alerta sobre um JWT sem expiração ou com acesso de gerenciamento. TLS com CA personalizada e certificados de cliente; a chave somente sobre TLS, em loopback ou pelo túnel SSH; um modo somente leitura declarado no seed | +| **Qdrant** | nenhum, HTTP (a API REST do Qdrant, Weaviate, porta 6333) | As requisições REST do próprio Qdrant no editor (`MÉTODO /caminho` com um corpo JSON), dezessete rotas de leitura: leituras de pontos, scroll, contagens exatas, facetas, e consultas, lotes e consultas agrupadas sobre vetores densos, esparsos e multivetor, incluindo o modelo BM25 local; coleções na árvore com seus vetores, índices de payload e uma visão amostrada das chaves do payload; células vetoriais com sua dimensão e cópia do valor completo. O Studio não escreve nada, recusa toda entrada de inferência exceto o BM25 local e alerta sobre um JWT sem expiração ou com acesso de gerenciamento. TLS com CA personalizada e certificados de cliente; a chave somente sobre TLS, em loopback ou pelo túnel SSH; um modo somente leitura declarado no seed | +| **Weaviate** | nenhum, HTTP (a API REST do Weaviate, e GraphQL para as buscas de um servidor anterior a 1.39.7, porta 8080) | As requisições REST do próprio Weaviate no editor (`MÉTODO /v1/caminho` com um corpo JSON), dezessete rotas de leitura: listas de objetos e leituras por id, buscas BM25, híbridas com alpha 0, near-vector e near-object, filtros e contagens de agregação, escritas no formato da busca REST em todo servidor e executadas por GraphQL num anterior a 1.39.7; coleções na árvore com suas propriedades e vetores, tenants e aliases no Source da coleção, contagens exatas. O Studio não escreve nada, recusa toda requisição que enviaria texto a um modelo e nunca acorda um tenant frio. TLS com CA personalizada; a chave de API ou o token de acesso OIDC somente sobre TLS, em loopback ou pelo túnel SSH; testado no Weaviate 1.40.2, 1.38.22 e 1.37.4 | | **InfluxDB (InfluxQL)** | nenhum, HTTP (a API v1 do InfluxDB, porta 8086) | InfluxQL somente leitura no editor contra InfluxDB 1.x, 2.x e 3 pela API v1 `/query`, um `SELECT`, `SHOW` ou `EXPLAIN` por execução; bancos de dados e measurements na árvore, com os tags e fields de cada measurement como colunas, e inteiros acima de 2^53 e timestamps em nanossegundos exatos na grade. Somente leitura não importa o que a conexão diga: no 1.x e no 2.x a política de leitura do próprio Studio é a única barreira antes de `DROP DATABASE`, então toda outra instrução é recusada antes de qualquer requisição, e nenhum endpoint de escrita é alcançado. Usuário e senha, ou um token no campo de senha; uma credencial por HTTP sem criptografia para um host que não é loopback nem passa por túnel é recusada, a menos que a conexão consinta; `_internal` nunca é lido num servidor InfluxDB 3 | | **InfluxDB 3 (SQL)** | nenhum, HTTP (a API SQL do InfluxDB 3, porta 8181) | SQL somente leitura no editor contra InfluxDB 3 Core e Enterprise; as tabelas do banco de dados da conexão na árvore, com suas colunas. Somente leitura não importa o que a conexão diga: a tabela de rotas não alcança nenhum endpoint de escrita, tokens, cache ou plugins, e dos de configuração só a listagem de bancos de dados, um GET, toda instrução que não comece por uma palavra-chave de leitura é recusada antes de qualquer requisição, e o planejador do servidor recusa ainda toda escrita. Um token e nenhum usuário; um token por HTTP sem criptografia para um host que não é loopback nem passa por túnel é recusado, a menos que a conexão consinta; apontada para um servidor 1.x ou 2.x, indica escolher InfluxDB (InfluxQL) | | **Oxia** | `@grpc/grpc-js` (JavaScript puro, gRPC, porta 6648) | Comandos `oxia client` somente leitura (`get`, `list`, `range-scan`), shards na árvore e cada chave no painel de chaves | diff --git a/README_ru.md b/README_ru.md index 377ed18aa5..f843fd02b6 100644 --- a/README_ru.md +++ b/README_ru.md @@ -132,9 +132,9 @@ LibreDB Studio устроен наоборот: **инструмент прих ## Основные возможности -### Сорок один СУБД, один интерфейс +### Сорок две СУБД, один интерфейс -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B Для всех SQL-СУБД доступен одинаковый набор инструментов: дерево объектов базы (схемы, таблицы, столбцы), ER-диаграммы, сравнение схем и панели мониторинга. MongoDB и Redis работают не на SQL, поэтому ER-диаграмм и сравнения схем для них нет. @@ -170,7 +170,8 @@ ER-диаграмма для Elasticsearch и OpenSearch показывает и | **etcd** | `@grpc/grpc-js` (чистый JavaScript, gRPC, порт 2379) | Подмножество etcdctl в редакторе (`get`, `put`, `del`, `txn`, аренды (leases), ограниченный `watch`, участники кластера, тревоги (alarms), пользователи и роли); группы по префиксу ключа в дереве и каждый ключ в панели ключей; значение ключа меняется одной транзакцией с проверкой его ревизии; сжатие истории, дефрагментация и снятие тревог для администраторов, каждое с подтверждением вводом имени подключения. Любая запись под префиксом Kubernetes или в `compact_rev_key` отклоняется, а секреты Kubernetes и значения в protobuf или зашифрованные никогда не показываются. TLS с собственным CA, клиентские сертификаты (их Common Name как пользователь etcd) и вход по паролю только поверх TLS; SSH-туннель; режим только для чтения, заданный в seed-файле | | **Neo4j** | `neo4j-driver-lite` (чистый JavaScript, Bolt, порт 7687) | Cypher только для чтения в редакторе, один оператор за запуск, для Neo4j 5.26 LTS; метки узлов и типы связей с их свойствами в качестве столбцов, индексы и ограничения в дереве; узлы, связи и пути в таблице как помеченные JSON-ячейки, 64-битные целые и значения даты и времени без потери точности; панели мониторинга, доступные в Community. Каждый оператор проходит политику чтения по его токенам, затем собственную классификацию сервера через `EXPLAIN` (разрешённая форма SHOW её пропускает) и выполняется в сеансе READ, так что запись должна преодолеть все три уровня. Нет просмотра EXPLAIN и PROFILE, нет обслуживания, нет выполнения агентом и нет `run_read_query` в MCP. TLS с собственным CA и SSH-туннель; без строки подключения | | **Milvus** | `@grpc/grpc-js` (чистый JavaScript, gRPC, порт 19530) | Собственные запросы REST v2 Milvus в редакторе (`POST /v2/vectordb/<маршрут>` с одним телом JSON) для чтения, точного подсчёта и векторного поиска по всем типам векторов, включая BM25 и гибридный поиск; базы данных и коллекции в дереве с полями, разделами, индексами и состоянием загрузки; векторные ячейки с размерностью и копированием полного значения; Load и Release для администраторов, с предпросмотром и подтверждением. Studio не записывает данные, отклоняет запросы, из-за которых сервер обратился бы к другому сервису, и предупреждает о пароле `root` по умолчанию. TLS с собственным CA и клиентскими сертификатами; пароль только поверх TLS, на loopback или через SSH-туннель; режим только для чтения, заданный в seed-файле | -| **Qdrant** | нет, HTTP (REST API Qdrant, порт 6333) | Собственные REST-запросы Qdrant в редакторе (`МЕТОД /путь` с одним телом JSON), семнадцать маршрутов чтения: чтение точек, прокрутка, точный подсчёт, фасеты, а также запросы, пакеты и сгруппированные запросы по плотным, разреженным и мультивекторным данным, включая локальную модель BM25; коллекции в дереве с векторами, индексами payload и выборочным видом ключей payload; векторные ячейки с размерностью и копированием полного значения. Studio ничего не записывает, отклоняет любой ввод для инференса, кроме локальной BM25, и предупреждает о JWT без срока действия или с правами управления. TLS с собственным CA и клиентскими сертификатами; ключ только поверх TLS, на loopback или через SSH-туннель; режим только для чтения, заданный в seed-файле | +| **Qdrant** | нет, HTTP (REST API Qdrant, Weaviate, порт 6333) | Собственные REST-запросы Qdrant в редакторе (`МЕТОД /путь` с одним телом JSON), семнадцать маршрутов чтения: чтение точек, прокрутка, точный подсчёт, фасеты, а также запросы, пакеты и сгруппированные запросы по плотным, разреженным и мультивекторным данным, включая локальную модель BM25; коллекции в дереве с векторами, индексами payload и выборочным видом ключей payload; векторные ячейки с размерностью и копированием полного значения. Studio ничего не записывает, отклоняет любой ввод для инференса, кроме локальной BM25, и предупреждает о JWT без срока действия или с правами управления. TLS с собственным CA и клиентскими сертификатами; ключ только поверх TLS, на loopback или через SSH-туннель; режим только для чтения, заданный в seed-файле | +| **Weaviate** | нет, HTTP (REST API Weaviate, а для поиска на сервере старше 1.39.7 GraphQL, порт 8080) | Собственные REST-запросы Weaviate в редакторе (`МЕТОД /v1/путь` с одним телом JSON), семнадцать маршрутов чтения: списки объектов и чтение по id, поиск BM25, гибридный с alpha 0, near-vector и near-object, фильтры и агрегатные подсчёты; поиск пишется в форме REST-поиска на любом сервере и выполняется через GraphQL на сервере старше 1.39.7; коллекции в дереве со свойствами и векторами, тенанты и алиасы в Source коллекции, точные подсчёты. Studio ничего не записывает, отклоняет любой запрос, который отправил бы текст модели, и никогда не будит холодный тенант. TLS с собственным CA; API-ключ или токен доступа OIDC только по TLS, через loopback или SSH-туннель; проверено на Weaviate 1.40.2, 1.38.22 и 1.37.4 | | **InfluxDB (InfluxQL)** | нет, HTTP (API v1 InfluxDB, порт 8086) | InfluxQL только для чтения в редакторе для InfluxDB 1.x, 2.x и 3 через API v1 `/query`, один `SELECT`, `SHOW` или `EXPLAIN` за запуск; базы данных и measurements в дереве, теги и поля measurement как его столбцы, а целые числа больше 2^53 и наносекундные метки времени в таблице результатов точны. Только чтение, что бы ни было указано в подключении: на 1.x и 2.x собственная политика чтения Studio единственный барьер перед `DROP DATABASE`, поэтому любой другой оператор отклоняется до отправки запроса, и ни один endpoint записи не вызывается. Пользователь и пароль либо токен в поле пароля; учётные данные по незашифрованному HTTP к хосту, который не loopback и не за туннелем, отклоняются, если подключение не дало на это согласия; `_internal` на сервере InfluxDB 3 никогда не читается | | **InfluxDB 3 (SQL)** | нет, HTTP (SQL API InfluxDB 3, порт 8181) | SQL только для чтения в редакторе для InfluxDB 3 Core и Enterprise; таблицы базы данных подключения в дереве со столбцами. Только чтение, что бы ни было указано в подключении: таблица маршрутов не достигает ни одного endpoint записи, токенов, кэша или плагинов, а из endpoint настройки только списка баз данных, GET-запроса, любой оператор, который не начинается с ключевого слова чтения, отклоняется до отправки запроса, а планировщик сервера отклоняет любую запись сверх того. Токен и без имени пользователя; токен по незашифрованному HTTP к хосту, который не loopback и не за туннелем, отклоняется, если подключение не дало на это согласия; при подключении к серверу 1.x или 2.x предлагает выбрать InfluxDB (InfluxQL) | | **Oxia** | `@grpc/grpc-js` (чистый JavaScript, gRPC, порт 6648) | Команды `oxia client` только для чтения (`get`, `list`, `range-scan`), шарды в дереве и каждый ключ в панели ключей | diff --git a/README_ur.md b/README_ur.md index fc0a3b1b36..2f9651270a 100644 --- a/README_ur.md +++ b/README_ur.md @@ -141,11 +141,11 @@ npx @libredb/studio ## بنیادی صلاحیتیں -### اکتالیس engines، ایک interface +### بیالیس engines، ایک interface -PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B +PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · DuckDB · MongoDB · Redis · Couchbase · Firestore · ClickHouse · Apache Druid · Elasticsearch · OpenSearch · Trino · BigQuery · Databend · Snowflake · Apache Spark · Apache Cassandra · Prometheus · Apache Kafka · etcd · Neo4j · Milvus · Qdrant · Weaviate · InfluxDB (InfluxQL) · InfluxDB 3 (SQL) · Oxia · S3-compatible object storage · Kubernetes · MQTT · RabbitMQ · OPC UA · MTConnect · Modbus · NETCONF · SNMP · Sparkplug B
@@ -182,6 +182,7 @@ PostgreSQL · MySQL · Oracle · Db2 LUW · SQL Server · SQLite · libSQL · Du | **Neo4j** | `neo4j-driver-lite` (pure JavaScript، Bolt، port 7687) | Neo4j 5.26 LTS کے لیے editor میں read-only Cypher، ہر run میں ایک statement؛ tree میں node labels اور relationship types (ان کی properties بطور columns)، indexes اور constraints؛ grid میں nodes، relationships اور paths بطور tagged JSON cells، 64-bit integers اور temporal values بغیر precision کھوئے؛ Community کے فراہم کردہ monitoring panels۔ ہر statement پہلے اپنے tokens پر read policy سے، پھر `EXPLAIN` کے ذریعے server کی اپنی classification سے (جسے allowlisted SHOW form چھوڑ دیتا ہے) گزرتا ہے اور READ session میں چلتا ہے، اس لیے کسی write کو تینوں layers توڑنی ہوں گی۔ EXPLAIN یا PROFILE view، maintenance، agent execution اور MCP `run_read_query` نہیں؛ Custom CA کے ساتھ TLS اور SSH tunnel؛ connection string نہیں | | **Milvus** | `@grpc/grpc-js` (pure JavaScript، gRPC، port 19530) | Editor میں Milvus کی اپنی REST v2 requests (ایک JSON body کے ساتھ `POST /v2/vectordb/`) سے reads، exact counts اور ہر vector type پر vector search، BM25 اور hybrid search سمیت؛ tree میں databases اور collections، ان کے fields، partitions، indexes اور load state؛ dimension کے ساتھ vector cells اور پوری value کی copy؛ admins کے لیے preview اور confirmation کے ساتھ Load اور Release۔ Studio کوئی data نہیں لکھتا، server سے کسی دوسری service کو call کروانے والی requests refuse کرتا ہے، اور default `root` password پر warning دیتا ہے۔ Custom CA اور client certificates کے ساتھ TLS؛ password صرف TLS پر، loopback پر یا SSH tunnel سے؛ seed میں اعلان کردہ read-only mode | | **Qdrant** | کوئی نہیں، HTTP (Qdrant کا REST API، port 6333) | Editor میں Qdrant کی اپنی REST requests (ایک JSON body کے ساتھ `METHOD /path`)، سترہ read routes: points پڑھنا، scroll، exact counts، facets، اور dense، sparse اور multivector data پر queries، batches اور grouped queries، local BM25 model سمیت؛ tree میں collections، ان کے vectors، payload indexes اور payload keys کا sampled view؛ dimension کے ساتھ vector cells اور پوری value کی copy۔ Studio کچھ نہیں لکھتا، local BM25 کے سوا ہر inference input refuse کرتا ہے، اور بغیر expiry یا manage access والے JWT پر warning دیتا ہے۔ Custom CA اور client certificates کے ساتھ TLS؛ key صرف TLS پر، loopback پر یا SSH tunnel سے؛ seed میں اعلان کردہ read-only mode | +| **Weaviate** | کوئی نہیں، HTTP (Weaviate کا REST API، اور 1.39.7 سے پرانے server پر searches کے لیے GraphQL، port 8080) | Editor میں Weaviate کی اپنی REST requests (ایک JSON body کے ساتھ `METHOD /v1/path`)، سترہ read routes: objects کی list اور id سے read، BM25، alpha 0 والا hybrid، near-vector اور near-object searches، filters اور aggregate counts، ہر server پر REST search کی شکل میں لکھی جاتی ہیں اور 1.39.7 سے پرانے server پر GraphQL سے چلتی ہیں؛ tree میں collections، ان کی properties اور vectors، tenants اور aliases collection کے Source میں، exact counts۔ Studio کچھ نہیں لکھتا، ہر وہ request refuse کرتا ہے جو text کسی model کو بھیجے، اور کسی cold tenant کو کبھی نہیں جگاتا۔ Custom CA کے ساتھ TLS؛ API key یا OIDC access token صرف TLS پر، loopback پر یا SSH tunnel سے؛ Weaviate 1.40.2، 1.38.22 اور 1.37.4 پر test کیا گیا | | **InfluxDB (InfluxQL)** | کوئی نہیں، HTTP (InfluxDB کا v1 API، port 8086) | Editor میں read-only InfluxQL، v1 `/query` API پر InfluxDB 1.x، 2.x اور 3 کے لیے، ہر run میں ایک `SELECT`، `SHOW` یا `EXPLAIN`؛ tree میں databases اور measurements، ہر measurement کے tags اور fields اس کے columns کے طور پر، اور grid میں 2^53 سے بڑے integers اور nanosecond timestamps بالکل درست۔ Connection میں کچھ بھی لکھا ہو، read-only: 1.x اور 2.x پر `DROP DATABASE` سے پہلے Studio کی اپنی read policy ہی واحد رکاوٹ ہے، اس لیے ہر دوسرا statement کسی بھی request سے پہلے refuse ہوتا ہے، اور کوئی write endpoint نہیں چھوا جاتا۔ User اور password، یا password field میں token؛ plain HTTP پر ایسے host کو credential، جو نہ loopback ہے نہ tunnel سے، تب تک refuse ہوتا ہے جب تک connection رضامندی نہ دے؛ InfluxDB 3 server پر `_internal` کبھی نہیں پڑھا جاتا | | **InfluxDB 3 (SQL)** | کوئی نہیں، HTTP (InfluxDB 3 کا SQL API، port 8181) | Editor میں read-only SQL، InfluxDB 3 Core اور Enterprise کے لیے؛ tree میں connection کے database کی tables، ان کے columns کے ساتھ۔ Connection میں کچھ بھی لکھا ہو، read-only: route table کسی write، token، cache یا plugin endpoint تک نہیں پہنچتی، اور configure endpoints میں سے صرف database listing تک، ایک GET، جو statement read keyword سے شروع نہیں ہوتا وہ کسی بھی request سے پہلے refuse ہوتا ہے، اور اس کے اوپر server کا planner ہر write refuse کرتا ہے۔ ایک token، کوئی user نام نہیں؛ plain HTTP پر ایسے host کو token، جو نہ loopback ہے نہ tunnel سے، تب تک refuse ہوتا ہے جب تک connection رضامندی نہ دے؛ 1.x یا 2.x server پر لگانے سے InfluxDB (InfluxQL) چننے کو کہتا ہے | | **Oxia** | `@grpc/grpc-js` (pure JavaScript، gRPC، port 6648) | Read-only `oxia client` commands (`get`، `list`، `range-scan`)، tree میں shards اور Keys panel میں ہر key | diff --git a/README_zh.md b/README_zh.md index 2abe553aa6..fa946c1868 100644 --- a/README_zh.md +++ b/README_zh.md @@ -146,7 +146,7 @@ LibreDB Studio 走另一条路:**工具去找数据,而不是把数据搬来 LibreDB Studio 走的是另一条路。它部署在数据旁边:一个容器、一个 Helm chart、一个 operator、一份 PaaS 一键模板,或者用 `npm i @libredb/studio` 嵌进你自己的产品。没有任何东西需要朝外暴露。 -四十一种引擎共用一个界面,PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Redis、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Prometheus、Apache Kafka、etcd、Neo4j、Milvus、Qdrant、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MQTT、RabbitMQ 和 OPC UA、MTConnect、Modbus、NETCONF、SNMP 和 Sparkplug B,处处是同一套浏览器,凡是引擎有东西可报的地方都有 ER 图、schema 对比和监控。四十种里有三种是只读的,因为它们自己的 SQL 就是只读的:Druid、Elasticsearch 和 OpenSearch 的文法里根本没有 `UPDATE`,也没有 `CREATE TABLE`,所以那些控件被如实报告为不支持,而不是等到用的时候才失败。Cassandra 是其中刻意报告得最少的一个:它给出的任何行数和容量都不真实,所以对象浏览器索性两者都不显示,而不是显示一个错的数字;它确实会发布的分区估算来自已刷盘的文件,实测一张 500 行的表被读作 143。Trino 是另一个异类:它是查询引擎而不是数据库,所以不声明任何主键和索引,报告的字节数属于它背后那些连接器所在的系统。 +四十二种引擎共用一个界面,PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Redis、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Prometheus、Apache Kafka、etcd、Neo4j、Milvus、Qdrant、Weaviate、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MQTT、RabbitMQ 和 OPC UA、MTConnect、Modbus、NETCONF、SNMP 和 Sparkplug B,处处是同一套浏览器,凡是引擎有东西可报的地方都有 ER 图、schema 对比和监控。四十种里有三种是只读的,因为它们自己的 SQL 就是只读的:Druid、Elasticsearch 和 OpenSearch 的文法里根本没有 `UPDATE`,也没有 `CREATE TABLE`,所以那些控件被如实报告为不支持,而不是等到用的时候才失败。Cassandra 是其中刻意报告得最少的一个:它给出的任何行数和容量都不真实,所以对象浏览器索性两者都不显示,而不是显示一个错的数字;它确实会发布的分区估算来自已刷盘的文件,实测一张 500 行的表被读作 143。Trino 是另一个异类:它是查询引擎而不是数据库,所以不声明任何主键和索引,报告的字节数属于它背后那些连接器所在的系统。 Sparkplug B 是最新的一个:通过 MQTT 读取一台 broker,metric 来自边缘节点出生证书的声明,值来自其后的数据消息;它从构造上就是只读的,因为 encoder 没有任何写 PUBLISH 的函数,CONNECT 也不带遗嘱(will):5.4 把边缘节点的死亡证书注册为它的遗嘱,读取方若设置了遗嘱,自己断开时就会发布一条死亡消息。组和边缘节点是容器,每个 metric 是一行,它的值、时间戳和定义都来自声明它的出生证书,序号缺口从两条相邻的数据消息读出而不是猜出。 @@ -169,21 +169,21 @@ Qdrant 在 Milvus 之前:在编辑器中输入的 Qdrant 自己的 REST 请求 Neo4j 在 Qdrant 之前:在编辑器中输入的 Cypher 通过 Bolt 读取 Neo4j 5.26 数据库,浏览器显示节点标签、关系类型、索引和约束,节点、关系和路径以 JSON 单元格进入结果表格,并且按构造只读,因为每条语句在运行前都要经过读取策略、服务器自身的分类和 READ 会话。 etcd 是在它之前的一个:通过 etcd 的 gRPC API 以 etcdctl 子集读写键,浏览器显示键前缀分组和键浏览器,键值在一个以修订号为条件的事务中编辑,管理员可以压缩、碎片整理和解除告警;任何写入 Kubernetes 前缀的操作都会被拒绝,Kubernetes Secret 从不显示。 Apache Kafka 在 etcd 之前:JSON 读取请求通过 Kafka 协议按分区、偏移量或时间戳读取主题中的消息,浏览器显示主题、带延迟的消费者组和 broker,并且按构造只读,因为 Studio 从不生产消息、提交偏移量、加入消费者组或创建主题。 -Oxia、InfluxDB (InfluxQL)、Milvus、Qdrant、Neo4j、etcd、Apache Kafka、MQTT、RabbitMQ 和 Prometheus 都和 MongoDB、Redis 一样完全不是 SQL:InfluxQL 看起来像 SQL,却是另一种语言,这里每次运行一条 `SELECT`、`SHOW` 或 `EXPLAIN`,而 InfluxDB 3 (SQL) 是 SQL;Prometheus 通过 Prometheus HTTP API 使用 PromQL,浏览指标、规则和抓取目标,并且是只读的,因为 Studio 不调用服务器的任何写入或管理端点。 +Oxia、InfluxDB (InfluxQL)、Milvus、Qdrant、Weaviate、Neo4j、etcd、Apache Kafka、MQTT、RabbitMQ 和 Prometheus 都和 MongoDB、Redis 一样完全不是 SQL:InfluxQL 看起来像 SQL,却是另一种语言,这里每次运行一条 `SELECT`、`SHOW` 或 `EXPLAIN`,而 InfluxDB 3 (SQL) 是 SQL;Prometheus 通过 Prometheus HTTP API 使用 PromQL,浏览指标、规则和抓取目标,并且是只读的,因为 Studio 不调用服务器的任何写入或管理端点。 而且没有任何东西被留在门后。单点登录、ER 图、AI 功能和全部 NoSQL 引擎都在 MIT 构建里。MIT 在这里不是慷慨,而是这套架构的要求:你没法把一个按席位授权、功能分级的工具,放进你拥有的每一个环境。 ### 为什么选择 LibreDB Studio? - **部署在数据旁边**:容器、Helm chart、Rancher、OpenShift operator、PaaS 一键模板,或用 npm 嵌入。 -- **四十一种引擎,一个界面**:PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Redis、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Cassandra、Prometheus、Apache Kafka、etcd、Neo4j、Milvus、Qdrant、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MQTT、RabbitMQ、OPC UA、MTConnect、Modbus、NETCONF、SNMP、Sparkplug B。 +- **四十二种引擎,一个界面**:PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Redis、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Cassandra、Prometheus、Apache Kafka、etcd、Neo4j、Milvus、Qdrant、Weaviate、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MQTT、RabbitMQ、OPC UA、MTConnect、Modbus、NETCONF、SNMP、Sparkplug B。 - **你人在哪它就在哪跑**:浏览器、手机、Windows、MacOS、Linux 桌面。 - **一个只读的 Agent,配你自己的模型**:说一个问题,这次运行就会起草 SQL、读取结果,并写出一份每条结论都引用来源的报告。Gemini、OpenAI,或者跑开源模型的本地 Ollama。 - **没有东西被锁在墙后**:RBAC、OIDC 单点登录、审计日志和 ER 图,全部以 MIT 发布。

多数据库连接管理器 -
连接 PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、MongoDB、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Cassandra、Redis、SQLite、DuckDB、libSQL、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MTConnect、Modbus、NETCONF、Sparkplug B,支持 SSL/TLS 与 SSH 隧道(Kafka 支持 TLS,不支持隧道;OPC UA 自带传输层安全,不走共用面板;NETCONF 通过 SSH 连接,固定设备自身的主机密钥,两者都不走;SNMP 两者都没有:它走 UDP,共用隧道载不了,v3 的安全在报文内部)。 +
连接 PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、MongoDB、Couchbase、Firestore、ClickHouse、Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Cassandra、Redis、SQLite、DuckDB、libSQL、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、Weaviate、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、MTConnect、Modbus、NETCONF、Sparkplug B,支持 SSL/TLS 与 SSH 隧道(Kafka 支持 TLS,不支持隧道;OPC UA 自带传输层安全,不走共用面板;NETCONF 通过 SSH 连接,固定设备自身的主机密钥,两者都不走;SNMP 两者都没有:它走 UDP,共用隧道载不了,v3 的安全在报文内部)。

[![Ask DeepWiki](.github/assets/deepwiki-badge.svg)](https://deepwiki.com/libredb/libredb-studio) @@ -318,6 +318,7 @@ Studio 最主要的 AI 界面是编辑器旁边的 **Agent 侧栏**,下面列 | **Neo4j** | `neo4j-driver-lite`(纯 JavaScript,Bolt,7687 端口) | 针对 Neo4j 5.26 LTS 的只读 Cypher 编辑器,每次运行一条语句;树中显示节点标签和关系类型(属性作为列)、索引和约束;节点、关系和路径在结果表格中显示为带标签的 JSON 单元格,64 位整数和时间值保持精确;Community 版提供的监控面板。每条语句先经过基于词法单元的读取策略,再经过服务器通过 `EXPLAIN` 做出的分类(允许的 SHOW 形式跳过此分类),并在 READ 会话中运行,因此一次写入必须同时突破这三层。没有 EXPLAIN 或 PROFILE 视图,没有维护操作,没有智能体执行,也没有 MCP `run_read_query`。支持自定义 CA 的 TLS 和 SSH 隧道;不支持连接字符串 | | **Milvus** | `@grpc/grpc-js`(纯 JavaScript,gRPC,19530 端口) | 编辑器中使用 Milvus 自己的 REST v2 请求(带一个 JSON 请求体的 `POST /v2/vectordb/<路由>`)进行读取、精确计数,以及覆盖所有向量类型的向量搜索(包括 BM25 和混合搜索);树中列出数据库和集合,以及字段、分区、索引和加载状态;向量单元格显示维度并可复制完整值;管理员可执行带预览和确认的 Load 与 Release。Studio 不写入数据,拒绝会让服务器调用其他服务的请求,并对默认的 `root` 密码发出警告。支持自定义 CA 和客户端证书的 TLS;密码只能走 TLS、回环地址或 SSH 隧道;支持由种子配置声明的只读模式 | | **Qdrant** | 无,HTTP(Qdrant 的 REST API,6333 端口) | 编辑器中使用 Qdrant 自己的 REST 请求(带一个 JSON 请求体的 `方法 /路径`),共十七条只读路由:读取点、滚动、精确计数、分面,以及对稠密、稀疏和多向量数据的查询、批量查询和分组查询(包括本地 BM25 模型);树中列出集合及其向量、payload 索引和 payload 键的采样视图;向量单元格显示维度并可复制完整值。Studio 不写入任何内容,拒绝除本地 BM25 之外的所有推理输入,并对没有过期时间或带管理权限的 JWT 发出警告。支持自定义 CA 和客户端证书的 TLS;密钥只能走 TLS、回环地址或 SSH 隧道;支持由种子配置声明的只读模式 | +| **Weaviate** | 无,HTTP(Weaviate 的 REST API,1.39.7 之前的服务器的搜索走 GraphQL,8080 端口) | 编辑器中使用 Weaviate 自己的 REST 请求(带一个 JSON 请求体的 `方法 /v1/路径`),共十七条只读路由:对象列表和按 id 读取、BM25、alpha 为 0 的混合搜索、near-vector 和 near-object 搜索、过滤和聚合计数;搜索在所有服务器上都按 REST 搜索的写法书写,在 1.39.7 之前的服务器上通过 GraphQL 执行;树中列出集合及其属性和向量,租户和别名在集合的 Source 中,计数为精确值。Studio 不写入任何内容,拒绝任何会把文本发给模型的请求,也从不唤醒冷租户。支持自定义 CA 的 TLS;API 密钥或 OIDC 访问令牌只能走 TLS、回环地址或 SSH 隧道;在 Weaviate 1.40.2、1.38.22 和 1.37.4 上测试 | | **InfluxDB (InfluxQL)** | 无,HTTP(InfluxDB 的 v1 API,8086 端口) | 编辑器中的只读 InfluxQL,通过 v1 `/query` API 读取 InfluxDB 1.x、2.x 和 3,每次运行一条 `SELECT`、`SHOW` 或 `EXPLAIN`;树中列出数据库和 measurement,measurement 的 tag 和 field 作为其列,超过 2^53 的整数和纳秒时间戳在结果表格中保持精确。无论连接如何设置都是只读:在 1.x 和 2.x 上,Studio 自己的读取策略是 `DROP DATABASE` 之前唯一的屏障,所以其他任何语句都在发出请求之前被拒绝,也不会触及任何写入端点。用户名和密码,或在密码字段中填写 token;凭据经明文 HTTP 发往既不是本机回环也不经隧道的主机时会被拒绝,除非该连接明确同意;在 InfluxDB 3 服务器上从不读取 `_internal` | | **InfluxDB 3 (SQL)** | 无,HTTP(InfluxDB 3 的 SQL API,8181 端口) | 编辑器中的只读 SQL,面向 InfluxDB 3 Core 和 Enterprise;树中列出连接所指数据库的表及其列。无论连接如何设置都是只读:路由表不触及任何写入、token、缓存或插件端点,配置端点中只触及数据库列表这一个 GET,任何不以读取关键字开头的语句都在发出请求之前被拒绝,服务器的查询规划器还会拒绝一切写入。只用 token,没有用户名;token 经明文 HTTP 发往既不是本机回环也不经隧道的主机时会被拒绝,除非该连接明确同意;指向 1.x 或 2.x 服务器时会提示改选 InfluxDB (InfluxQL) | | **Oxia** | `@grpc/grpc-js`(纯 JavaScript,gRPC,6648 端口) | 只读的 `oxia client` 命令(`get`、`list`、`range-scan`),树中显示分片,键浏览器列出每个键 | @@ -333,7 +334,7 @@ Studio 最主要的 AI 界面是编辑器旁边的 **Agent 侧栏**,下面列 | **Sparkplug B** | 无:本仓库自己的受限 MQTT 会话,走共用的 `node:net` 与 `node:tls` 传输层(端口 1883,启用 SSL / TLS 面板后为 8883) | 结构上只读:编码器没有任何写 PUBLISH 的函数,CONNECT 也不带遗嘱(will),因为 5.4 把边缘节点的死亡证书注册为它的遗嘱,读取方若设置了遗嘱,自己断开时就会发布一条死亡消息。组和边缘节点是容器,每个 metric 是一行,它的值、时间戳和定义都来自声明它的出生证书 | | **Redis** | `ioredis` | 命令编辑器、键浏览器、基于 INFO 的监控 | -> **另有二十七种引擎没有自己的驱动。** 上面四十一种是这个构建自带的驱动。另有二十七种引擎使用其中某一种线协议,通过已有驱动原样接入,所以四十个驱动一共覆盖六十七个具名引擎所以四十个驱动一共覆盖六十六个具名引擎。它们是 MariaDB、Percona Server for MySQL、TiDB、Vitess、StarRocks、Apache Doris、OceanBase、SingleStore、Citus、Percona Distribution for PostgreSQL、[ParadeDB](https://www.paradedb.com/)、OrioleDB、TimescaleDB、YugabyteDB、AlloyDB Omni、Apache Cloudberry(孵化中)、CockroachDB、Materialize 和 RisingWave(按 PostgreSQL 或 MySQL 接入),Valkey、DragonflyDB、KeyDB 和 Garnet(按 Redis 接入),FerretDB(按 MongoDB 接入),ScyllaDB(按 Cassandra 接入),VictoriaMetrics(按 Prometheus 接入),以及 Redpanda(按 Apache Kafka 接入)。每一种都对着一个真实实例测过,而产品能用的部分因引擎而异。MariaDB、两个 Percona 发行版、TiDB、Vitess、AlloyDB Omni、Citus、TimescaleDB、YugabyteDB、ParadeDB、OrioleDB、Valkey、DragonflyDB、KeyDB 和 FerretDB 的表现与它们所借驱动自身的引擎一致,不过其中三种会报告不该信任的统计值:Citus 的分布式表和 TimescaleDB 的 hypertable 报告的行数与容量是错的而不是缺的,YugabyteDB 则在你跑 `ANALYZE` 之前一直报 0。Vitess 不属于那三种,它的行数与容量精确到字节,但在那里无法取消正在运行的查询:vtgate 拒绝 `KILL QUERY`,语句会一直跑到结束。AlloyDB Omni 也不属于那三种,2000 行就报 2000 行、270336 字节就报 270336 字节,但那里有两件事出人意料:`version()` 在任何地方都不提 AlloyDB,所以版本面板与一个原生 PostgreSQL 17 无法区分;而 AlloyDB 自己的八个 `google_ml` 表会出现在对象浏览器里,任何能连上的角色也都能读它们。StarRocks 自称 MySQL 5.1,并失去了概览、健康和会话面板,它的监控面板只渲染出六个,其中会话面板带着引擎自己的拒绝理由;Apache Doris 是 StarRocks 所 fork 的引擎,只失去概览和健康面板,原因是一种它的文法拒绝的语句形式,而在真正要紧的地方它比 StarRocks 更可信:一张确实有那么多数据的表,它报 2000 行和 10187 字节,而 StarRocks 起初也读作零(它自己的后台统计收集器更慢,实测 4.5 分钟对 3.3.22,而 Doris 大约一分钟),并且在 2026-09-16 的一次修复之前,单就容量而言此后会永远读作零,因为 StarRocks 的 `INDEX_LENGTH` 是 NULL 而不是 Doris 那样的真实 0,把 provider 在 SQL 里算的那个和值毒化了;索引从不被报告,外键会被接受、被 `SHOW CONSTRAINTS` 列出、对 ER 图不可见且不被强制执行;Cloudberry 失去监控面板及其表和索引统计,三者都源于同一条 MPP 计划器限制,并且会把外键读成似乎被强制执行的样子,实际并没有,尽管它的行数是正确的;CockroachDB 失去对象浏览器和容量面板;OceanBase 能应答十五个界面中的十四个,但只有十二个有用,健康面板直接失败,因为它的租户根本没有 `performance_schema` 库,而每一处容量都读作 0 B,不过一旦跑过 `ANALYZE TABLE`,它的行数就是正确的;SingleStore 失去五个界面,原因在我们这边而不在它那边,provider 把每条语句都走预处理语句协议,而 SingleStore 对四个面板所需的 `SHOW` 和 `EXPLAIN` 语句拒绝该协议,这五个里现在已有四个恢复,未恢复的是它的 Explain 面板,因为那里的文法要 `EXPLAIN JSON`,而该语句在两种协议下都失败;它的数字仍然是缺的而不是错的,一张 2000 行的表读作 0 行和 0 B,且任何 `ANALYZE` 都改不了;ScyllaDB 失去五个界面,连 Test Connection 一起,六个全都源于同一个缺失的 keyspace,概览、健康、性能指标、活动会话和监控面板都读 Cassandra 的 `system_views` 虚拟表,而 ScyllaDB 根本没有 `system_views` keyspace,这五个现在降级为空而不是抛错,于是 Test Connection 能通过、对话框能保存连接,而在那次改动之前它完全做不到,同时编辑器与对象浏览器完好可用,18 种 CQL 类型每一种读回来的字节都与同一轮里探测的 Cassandra 5.0.9 一致;ParadeDB 和 OrioleDB 都是完整的,代价却正好相反:ParadeDB 的九个扩展为 2 张用户表在对象浏览器里放进 41 个对象,不过 Agent Plan 模式在最小权限角色下可以正常工作,只有以 `postgres` 超级用户身份时才会被拒绝,这与任何 PostgreSQL 上的情况相同,而 OrioleDB 的浏览器很干净,但它自己的存储对 PostgreSQL 的容量函数不可见,所以每个索引都读作 0 字节,缓存命中率读作 N/A。Materialize 和 RisingWave 为部分支持:对象浏览器能显示它们的表、视图和物化视图及其列,但行数、大小和监控统计仍为空。Garnet 的表现与 Redis 一致,并且是这里三个近亲之一(另外两个是 Valkey 和 DragonflyDB),它们的 `INFO` 里会在 Redis 兼容级别旁边带上自己的版本,概览现在把后者标在前面,即 `Garnet 2.1.5 (Redis 7.4.3)`,而它有两处读数是以数值面目出现的空缺:每处容量都显示 0 B,因为它不发布 `used_memory`,缓存命中率显示 100%,因为它不发布 keyspace 计数器。 +> **另有二十七种引擎没有自己的驱动。** 上面四十二种是这个构建自带的驱动。另有二十七种引擎使用其中某一种线协议,通过已有驱动原样接入,所以四十个驱动一共覆盖六十七个具名引擎所以四十个驱动一共覆盖六十六个具名引擎。它们是 MariaDB、Percona Server for MySQL、TiDB、Vitess、StarRocks、Apache Doris、OceanBase、SingleStore、Citus、Percona Distribution for PostgreSQL、[ParadeDB](https://www.paradedb.com/)、OrioleDB、TimescaleDB、YugabyteDB、AlloyDB Omni、Apache Cloudberry(孵化中)、CockroachDB、Materialize 和 RisingWave(按 PostgreSQL 或 MySQL 接入),Valkey、DragonflyDB、KeyDB 和 Garnet(按 Redis 接入),FerretDB(按 MongoDB 接入),ScyllaDB(按 Cassandra 接入),VictoriaMetrics(按 Prometheus 接入),以及 Redpanda(按 Apache Kafka 接入)。每一种都对着一个真实实例测过,而产品能用的部分因引擎而异。MariaDB、两个 Percona 发行版、TiDB、Vitess、AlloyDB Omni、Citus、TimescaleDB、YugabyteDB、ParadeDB、OrioleDB、Valkey、DragonflyDB、KeyDB 和 FerretDB 的表现与它们所借驱动自身的引擎一致,不过其中三种会报告不该信任的统计值:Citus 的分布式表和 TimescaleDB 的 hypertable 报告的行数与容量是错的而不是缺的,YugabyteDB 则在你跑 `ANALYZE` 之前一直报 0。Vitess 不属于那三种,它的行数与容量精确到字节,但在那里无法取消正在运行的查询:vtgate 拒绝 `KILL QUERY`,语句会一直跑到结束。AlloyDB Omni 也不属于那三种,2000 行就报 2000 行、270336 字节就报 270336 字节,但那里有两件事出人意料:`version()` 在任何地方都不提 AlloyDB,所以版本面板与一个原生 PostgreSQL 17 无法区分;而 AlloyDB 自己的八个 `google_ml` 表会出现在对象浏览器里,任何能连上的角色也都能读它们。StarRocks 自称 MySQL 5.1,并失去了概览、健康和会话面板,它的监控面板只渲染出六个,其中会话面板带着引擎自己的拒绝理由;Apache Doris 是 StarRocks 所 fork 的引擎,只失去概览和健康面板,原因是一种它的文法拒绝的语句形式,而在真正要紧的地方它比 StarRocks 更可信:一张确实有那么多数据的表,它报 2000 行和 10187 字节,而 StarRocks 起初也读作零(它自己的后台统计收集器更慢,实测 4.5 分钟对 3.3.22,而 Doris 大约一分钟),并且在 2026-09-16 的一次修复之前,单就容量而言此后会永远读作零,因为 StarRocks 的 `INDEX_LENGTH` 是 NULL 而不是 Doris 那样的真实 0,把 provider 在 SQL 里算的那个和值毒化了;索引从不被报告,外键会被接受、被 `SHOW CONSTRAINTS` 列出、对 ER 图不可见且不被强制执行;Cloudberry 失去监控面板及其表和索引统计,三者都源于同一条 MPP 计划器限制,并且会把外键读成似乎被强制执行的样子,实际并没有,尽管它的行数是正确的;CockroachDB 失去对象浏览器和容量面板;OceanBase 能应答十五个界面中的十四个,但只有十二个有用,健康面板直接失败,因为它的租户根本没有 `performance_schema` 库,而每一处容量都读作 0 B,不过一旦跑过 `ANALYZE TABLE`,它的行数就是正确的;SingleStore 失去五个界面,原因在我们这边而不在它那边,provider 把每条语句都走预处理语句协议,而 SingleStore 对四个面板所需的 `SHOW` 和 `EXPLAIN` 语句拒绝该协议,这五个里现在已有四个恢复,未恢复的是它的 Explain 面板,因为那里的文法要 `EXPLAIN JSON`,而该语句在两种协议下都失败;它的数字仍然是缺的而不是错的,一张 2000 行的表读作 0 行和 0 B,且任何 `ANALYZE` 都改不了;ScyllaDB 失去五个界面,连 Test Connection 一起,六个全都源于同一个缺失的 keyspace,概览、健康、性能指标、活动会话和监控面板都读 Cassandra 的 `system_views` 虚拟表,而 ScyllaDB 根本没有 `system_views` keyspace,这五个现在降级为空而不是抛错,于是 Test Connection 能通过、对话框能保存连接,而在那次改动之前它完全做不到,同时编辑器与对象浏览器完好可用,18 种 CQL 类型每一种读回来的字节都与同一轮里探测的 Cassandra 5.0.9 一致;ParadeDB 和 OrioleDB 都是完整的,代价却正好相反:ParadeDB 的九个扩展为 2 张用户表在对象浏览器里放进 41 个对象,不过 Agent Plan 模式在最小权限角色下可以正常工作,只有以 `postgres` 超级用户身份时才会被拒绝,这与任何 PostgreSQL 上的情况相同,而 OrioleDB 的浏览器很干净,但它自己的存储对 PostgreSQL 的容量函数不可见,所以每个索引都读作 0 字节,缓存命中率读作 N/A。Materialize 和 RisingWave 为部分支持:对象浏览器能显示它们的表、视图和物化视图及其列,但行数、大小和监控统计仍为空。Garnet 的表现与 Redis 一致,并且是这里三个近亲之一(另外两个是 Valkey 和 DragonflyDB),它们的 `INFO` 里会在 Redis 兼容级别旁边带上自己的版本,概览现在把后者标在前面,即 `Garnet 2.1.5 (Redis 7.4.3)`,而它有两处读数是以数值面目出现的空缺:每处容量都显示 0 B,因为它不发布 `used_memory`,缓存命中率显示 100%,因为它不发布 keyspace 计数器。 > VictoriaMetrics 通过 Prometheus 驱动运行 PromQL,并列出它的指标及其标签列、它的抓取目标,以及序列数最多的至多五十个指标,但它的规则文件夹是空的,因为单节点服务器不评估任何规则;概览、存储统计和抓取池文件夹都会失败,因为它们读取的 Prometheus 端点中有三个它根本不提供;指标的源不显示单位,目标的源不显示抓取间隔和超时,因为它不发送这些字段,它尚未抓取过的目标也会显示为 down;此外,字符串表达式不返回任何行,子查询的数据点从求值时间往回计算,任何结果旁边也不会出现 PromQL 的 info 或 warning 提示。 > Redpanda 通过 Apache Kafka 驱动应答每一个 Kafka 界面,主题、带延迟的消费者组、broker 和读取都可用,但它的概览把最大连接数读作 0,broker 的源只列出九项配置,因为它对 broker 配置的应答只有这些;它的存储统计没有使用百分比;每个消费者组都读作 classic,这在 Redpanda 上是对的,因为它没有别的组协议。 > 每个引擎的细节,连同探测所用的确切版本,都在 [`docs/providers/README.md`](docs/providers/README.md#wire-compatible-engines) 里:我们只有在连上某个引擎之后才会写出它的名字,所以那里没有的名字是尚未测试,而不是不受支持。 @@ -354,7 +355,7 @@ Studio 最主要的 AI 界面是编辑器旁边的 **Agent 侧栏**,下面列 | **编辑器** | Monaco Editor(VS Code 内核) | Web | | **AI** | 多模型(Gemini、OpenAI、Ollama、自定义) | Web、移动端 | | **认证** | JWT(`jose`)+ OIDC(`openid-client`)、PKCE、角色映射 | Web、移动端 | -| **数据库** | PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Couchbase、Firestore、ClickHouse、Apache Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Redis、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、OPC UA、MTConnect、Modbus、NETCONF、SNMP、Sparkplug B | Web、移动端 | +| **数据库** | PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Couchbase、Firestore、ClickHouse、Apache Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Redis、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、Weaviate、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、OPC UA、MTConnect、Modbus、NETCONF、SNMP、Sparkplug B | Web、移动端 | | **图表** | Recharts(柱状图、折线图、饼图、面积图、散点图、直方图、堆叠图) | Web、移动端 | | **ERD** | React Flow、ELK.js(自动布局) | Web | | **状态与表格** | TanStack Table 与 Virtual | Web、移动端 | @@ -441,7 +442,7 @@ journalctl -u libredb-studio ### 前置条件 - [Bun](https://bun.sh/)(推荐)或 Node.js 24+ -- 一个可查询的目标数据库(PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Couchbase、Firestore、ClickHouse、Apache Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Redis、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、OPC UA、MTConnect、Modbus、NETCONF、SNMP 或 Sparkplug B) +- 一个可查询的目标数据库(PostgreSQL、MySQL、Oracle、Db2 LUW、SQL Server、SQLite、libSQL、DuckDB、MongoDB、Couchbase、Firestore、ClickHouse、Apache Druid、Elasticsearch、OpenSearch、Trino、BigQuery、Databend、Snowflake、Apache Spark、Apache Cassandra、Redis、Prometheus、Apache Kafka、MQTT、RabbitMQ、etcd、Neo4j、Milvus、Qdrant、Weaviate、InfluxDB (InfluxQL)、InfluxDB 3 (SQL)、Oxia、S3-compatible object storage、Kubernetes、OPC UA、MTConnect、Modbus、NETCONF、SNMP 或 Sparkplug B) ### 快速开始(本地) 1. **克隆并安装** @@ -939,7 +940,7 @@ extraEnvFrom: | `defaults` | 否 | 合并进所有连接的默认值 | | `connections[].id` | 是 | 唯一 slug(`[a-z0-9-]+`,最多 64 字符) | | `connections[].name` | 是 | UI 中显示的名称 | -| `connections[].type` | 是 | `postgres`、`mysql`、`sqlite`、`libsql`、`duckdb`、`oracle`、`db2`、`mssql`、`clickhouse`、`druid`、`trino`、`bigquery`、`databend`、`snowflake`、`spark`、`cassandra`、`elasticsearch`、`opensearch`、`mongodb`、`couchbase`、`firestore`、`redis`、`prometheus`、`kafka`、`mqtt`、`rabbitmq`、`etcd`、`neo4j`、`milvus`、`qdrant`、`influxdb`、`influxdb3`、`oxia`、`s3`、`kubernetes`、`opcua`、`mtconnect`、`modbus`、`netconf`、`snmp`、`sparkplug`、`libredb` | +| `connections[].type` | 是 | `postgres`、`mysql`、`sqlite`、`libsql`、`duckdb`、`oracle`、`db2`、`mssql`、`clickhouse`、`druid`、`trino`、`bigquery`、`databend`、`snowflake`、`spark`、`cassandra`、`elasticsearch`、`opensearch`、`mongodb`、`couchbase`、`firestore`、`redis`、`prometheus`、`kafka`、`mqtt`、`rabbitmq`、`etcd`、`neo4j`、`milvus`、`qdrant`、`weaviate`、`influxdb`、`influxdb3`、`oxia`、`s3`、`kubernetes`、`opcua`、`mtconnect`、`modbus`、`netconf`、`snmp`、`sparkplug`、`libredb` | | `connections[].roles` | 是 | `["*"]`(所有人)、`["admin"]`、`["user"]` 或 `["admin", "user"]` | | `connections[].managed` | 否 | `true` = 由管理员控制,界面中不可编辑(默认),`false` = 给用户一份可编辑的副本 | | `connections[].readOnly` | 否 | `true` 时拒绝该连接上的所有写入(仅在执行该模式的引擎上,即 etcd);在非托管连接上会被拒绝 | diff --git a/charts/libredb-studio/Chart.yaml b/charts/libredb-studio/Chart.yaml index 9714f8971b..c7190b2873 100644 --- a/charts/libredb-studio/Chart.yaml +++ b/charts/libredb-studio/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 name: libredb-studio -description: Web-based SQL IDE for cloud-native teams supporting forty-one engines - PostgreSQL, MySQL, SQLite, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B +description: Web-based SQL IDE for cloud-native teams supporting forty-two engines - PostgreSQL, MySQL, SQLite, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B type: application -version: 0.1.102 +version: 0.1.103 appVersion: "1.0.0" kubeVersion: ">=1.26.0-0" home: https://github.com/libredb/libredb-studio @@ -69,6 +69,8 @@ keywords: # evaluator looking for a Milvus or Qdrant client types, so there is no second spelling to catch. - milvus - qdrant + # Weaviate (#1566): the type-id is also the word an evaluator looking for a Weaviate client types. + - weaviate # Three keywords, like the prometheus pair above with one more: `influxdb` and `influxdb3` are # the two type-ids and the products, and `influxql` is what an evaluator looking for an # InfluxQL client types. @@ -314,7 +316,7 @@ annotations: - name: Source url: https://github.com/libredb/libredb-studio artifacthub.io/changes: | - - "Add config.oidcRolePrefix, written as OIDC_ROLE_PREFIX: prefix filter for custom seed roles from the OIDC role claim" + - "Name Weaviate, read-only over its REST API, in the description and the keywords" dependencies: - name: postgresql version: "16.x.x" diff --git a/charts/libredb-studio/README.md b/charts/libredb-studio/README.md index 06b50742e8..16663b44cf 100644 --- a/charts/libredb-studio/README.md +++ b/charts/libredb-studio/README.md @@ -2,7 +2,7 @@ [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/libredb-studio)](https://artifacthub.io/packages/search?repo=libredb-studio) -Web-based SQL IDE for cloud-native teams supporting forty-one engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. +Web-based SQL IDE for cloud-native teams supporting forty-two engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. ## Prerequisites @@ -40,7 +40,7 @@ helm install libredb libredb/libredb-studio \ ```bash helm install libredb oci://ghcr.io/libredb/charts/libredb-studio \ - --version 0.1.102 \ + --version 0.1.103 \ --set secrets.jwtSecret=$(openssl rand -base64 32) \ --set secrets.adminPassword=MyAdmin123 ``` diff --git a/database-compose.yml b/database-compose.yml index 404d296daa..3e7c498b80 100644 --- a/database-compose.yml +++ b/database-compose.yml @@ -2575,6 +2575,243 @@ services: healthcheck: *qdrant-tcp-health <<: *qdrant-limits + # --------------------------------------------------------------------------------------- + # Weaviate (the weaviate provider, #1566). The default fixture is one 1.40 server, which + # serves every REST search route. Three more sit behind the `weaviate-matrix` profile, one per + # server shape the provider must read: 1.37.4, the version DigitalOcean Managed Weaviate + # runs, which has no REST search and is searched over GraphQL; 1.38.22, whose REST search + # sits behind a flag left off; and 1.40 with GraphQL disabled, the setting new Weaviate + # Cloud clusters are created with. Every server runs with + # no vectorizer and API_BASED_MODULES_DISABLED, so /v1/meta lists no module and no request + # can reach a model provider: an empty ENABLE_MODULES alone still loads every API-based + # module. Each server is seeded by a one-shot Python sidecar (docker/weaviate/seed.py, stdlib + # only). gRPC 50051, which the provider never dials, is not published, and no server has a + # data volume: removing its container resets it. docker/weaviate/README.md describes the + # servers and the seeded collections. + # --------------------------------------------------------------------------------------- + weaviate: + image: cr.weaviate.io/semitechnologies/weaviate:1.40.2@sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a + container_name: libredb-weaviate + restart: unless-stopped + environment: &weaviate-env + AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "true" + PERSISTENCE_DATA_PATH: /var/lib/weaviate + DEFAULT_VECTORIZER_MODULE: none + API_BASED_MODULES_DISABLED: "true" + DISABLE_TELEMETRY: "true" + CLUSTER_HOSTNAME: node1 + ports: + - "127.0.0.1:18280:8080" + healthcheck: &weaviate-health + # The image is Alpine with busybox wget and no curl; /v1/.well-known/ready needs no key. + test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:8080/v1/.well-known/ready"] + start_period: 30s + start_interval: 1s + interval: 30s + timeout: 5s + retries: 3 + <<: &weaviate-limits + deploy: + resources: + limits: + cpus: "2" + memory: 1G + memswap_limit: 1G + + weaviate-seed: + # The Qdrant seed's pinned Python image; the Weaviate seed is stdlib only, so it installs + # nothing. It creates what is missing and leaves what exists. + image: python:3.14-slim@sha256:0741d101873c12ab927e6f8653feb8862b9bd58771177acb1b885b95141f91b4 + container_name: libredb-weaviate-seed + restart: "no" + depends_on: + weaviate: + condition: service_healthy + volumes: + - ./docker/weaviate:/seed:ro + environment: *seed-env + entrypoint: ["python", "/seed/seed.py"] + command: ["--url", "http://weaviate:8080"] + <<: *vector-seed-limits + + weaviate-1-37: + # DigitalOcean's version (docs.digitalocean.com, "How to Create Weaviate Clusters"). 1.37 + # left Weaviate's three-minor support window when 1.40 shipped; it stays here because a + # managed service still runs it. + image: cr.weaviate.io/semitechnologies/weaviate:1.37.4@sha256:fcd0d4dfe70ed38feb2c12df58f991f3437bdf34ac022d978a48844c3ac86ea0 + container_name: libredb-weaviate-1-37 + profiles: ["weaviate-matrix"] + restart: unless-stopped + environment: *weaviate-env + ports: + - "127.0.0.1:18281:8080" + healthcheck: *weaviate-health + <<: *weaviate-limits + + weaviate-1-38: + # The one line that carries the REST search routes behind EXPERIMENTAL_REST_SEARCH_ENABLED, left + # off as its default; the provider searches it over GraphQL, as every server below 1.39.7. + image: cr.weaviate.io/semitechnologies/weaviate:1.38.22@sha256:3b114db3992b8b4a62b623112b21a3d18c589e084dd9954b87b8d2ef08c6645c + container_name: libredb-weaviate-1-38 + profiles: ["weaviate-matrix"] + restart: unless-stopped + environment: *weaviate-env + ports: + - "127.0.0.1:18285:8080" + healthcheck: *weaviate-health + <<: *weaviate-limits + + weaviate-nographql: + image: cr.weaviate.io/semitechnologies/weaviate:1.40.2@sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a + container_name: libredb-weaviate-nographql + profiles: ["weaviate-matrix"] + restart: unless-stopped + environment: + <<: *weaviate-env + DISABLE_GRAPHQL: "true" + ports: + - "127.0.0.1:18282:8080" + healthcheck: *weaviate-health + <<: *weaviate-limits + + weaviate-matrix-seed: + image: python:3.14-slim@sha256:0741d101873c12ab927e6f8653feb8862b9bd58771177acb1b885b95141f91b4 + container_name: libredb-weaviate-matrix-seed + profiles: ["weaviate-matrix"] + restart: "no" + depends_on: + weaviate-1-37: + condition: service_healthy + weaviate-1-38: + condition: service_healthy + weaviate-nographql: + condition: service_healthy + volumes: + - ./docker/weaviate:/seed:ro + environment: *seed-env + entrypoint: + - sh + - -c + - >- + python /seed/seed.py --url http://weaviate-1-37:8080 && + python /seed/seed.py --url http://weaviate-1-38:8080 && + python /seed/seed.py --url http://weaviate-nographql:8080 + <<: *vector-seed-limits + + # -- Weaviate, API keys, RBAC and TLS ---------------------------------------------- + + weaviate-keys: + # Generates the root key and the TLS material into a named volume at first start + # (docker/weaviate/keys.sh), so no key and no private key is ever committed. + image: alpine/openssl:3.5.8@sha256:3f25da71f70eba788067daac3f3df03bd1de7a7c52ed89fa93b94ad2c92d986b + container_name: libredb-weaviate-keys + profiles: ["weaviate-secure"] + restart: "no" + volumes: + - weaviate-keys:/keys + - ./docker/weaviate:/weaviate-scripts:ro + entrypoint: ["sh", "/weaviate-scripts/keys.sh", "/keys"] + <<: *vector-one-shot-limits + + weaviate-auth: + # API keys and RBAC, anonymous access off; root is the one root user. Weaviate reads its + # keys from the environment alone, so the image's own sh exports the generated key and + # execs the server: the key never appears in this file. + image: cr.weaviate.io/semitechnologies/weaviate:1.40.2@sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a + container_name: libredb-weaviate-auth + profiles: ["weaviate-secure"] + restart: unless-stopped + depends_on: + weaviate-keys: + condition: service_completed_successfully + entrypoint: + - sh + - -c + - AUTHENTICATION_APIKEY_ALLOWED_KEYS="$$(cat /keys/root.key)" exec /bin/weaviate "$$@" + - weaviate + command: ["--host", "0.0.0.0", "--port", "8080", "--scheme", "http"] + environment: &weaviate-rbac-env + <<: *weaviate-env + AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "false" + AUTHENTICATION_APIKEY_ENABLED: "true" + AUTHENTICATION_APIKEY_USERS: root + AUTHENTICATION_DB_USERS_ENABLED: "true" + AUTHORIZATION_RBAC_ENABLED: "true" + AUTHORIZATION_RBAC_ROOT_USERS: root + volumes: + - weaviate-keys:/keys:ro + ports: + - "127.0.0.1:18283:8080" + healthcheck: *weaviate-health + <<: *weaviate-limits + + weaviate-tls: + # The same RBAC server on Weaviate's own TLS listener; no reverse proxy is needed. Only + # 8443 is published. The plain listener stays inside the container for the health probe, + # because busybox wget verifies the certificate and has no option for the fixture's CA. + image: cr.weaviate.io/semitechnologies/weaviate:1.40.2@sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a + container_name: libredb-weaviate-tls + profiles: ["weaviate-secure"] + restart: unless-stopped + depends_on: + weaviate-keys: + condition: service_completed_successfully + entrypoint: + - sh + - -c + - AUTHENTICATION_APIKEY_ALLOWED_KEYS="$$(cat /keys/root.key)" exec /bin/weaviate "$$@" + - weaviate + command: + - --scheme + - http + - --scheme + - https + - --host + - 0.0.0.0 + - --port + - "8080" + - --tls-host + - 0.0.0.0 + - --tls-port + - "8443" + - --tls-certificate + - /keys/server.pem + - --tls-key + - /keys/server.key + environment: *weaviate-rbac-env + volumes: + - weaviate-keys:/keys:ro + ports: + - "127.0.0.1:18284:8443" + healthcheck: *weaviate-health + <<: *weaviate-limits + + weaviate-secure-seed: + # Seeds both keyed servers as root and creates db user reader with the built-in viewer + # role on each, keeping its key in the volume (auth/reader.key, tls/reader.key). + image: python:3.14-slim@sha256:0741d101873c12ab927e6f8653feb8862b9bd58771177acb1b885b95141f91b4 + container_name: libredb-weaviate-secure-seed + profiles: ["weaviate-secure"] + restart: "no" + depends_on: + weaviate-auth: + condition: service_healthy + weaviate-tls: + condition: service_healthy + volumes: + - ./docker/weaviate:/seed:ro + - weaviate-keys:/keys + environment: *seed-env + entrypoint: + - sh + - -c + - >- + python /seed/seed.py --url http://weaviate-auth:8080 --api-key-file /keys/root.key + --reader-key-out /keys/auth/reader.key && + python /seed/seed.py --url https://weaviate-tls:8443 --api-key-file /keys/root.key + --cacert /keys/ca.pem --reader-key-out /keys/tls/reader.key + <<: *vector-seed-limits + # --------------------------------------------------------------------------------------- # InfluxDB (the influxdb and influxdb3 providers). Three servers, one per line the providers # are verified against: 1.13.1 and 2.9.1, which the influxdb type reads over the v1 /query @@ -3901,7 +4138,8 @@ volumes: # the two etcd auth servers and their init one-shots. Each Milvus server keeps its data in a # volume of its own, because the image runs as uid 999 and a bind mount crashed it; # milvus-certs and milvus-credentials hold the generated certificates and the seeded users' - # passwords, and qdrant-keys the generated Qdrant keys, local.yaml files and certificates. + # passwords, and qdrant-keys the generated Qdrant keys, local.yaml files and certificates; + # weaviate-keys holds the generated Weaviate root key, certificate and the seeded viewer keys. # influxdb2-read-token keeps the InfluxDB 2.x read-only token influxdb-seed created, whose # value the server shows only once. oxia-auth-material carries the generated certificates, JWT # keys and tokens from oxia-auth-certs to the Oxia auth server. s3-garage-keys keeps Garage's @@ -3925,6 +4163,7 @@ volumes: milvus-certs: {} milvus-credentials: {} qdrant-keys: {} + weaviate-keys: {} influxdb2-read-token: {} s3-garage-keys: {} s3-certs: {} diff --git a/deploy/aws/listing/description.md b/deploy/aws/listing/description.md index 6a96090422..cf5cd6404f 100644 --- a/deploy/aws/listing/description.md +++ b/deploy/aws/listing/description.md @@ -1,2 +1,2 @@ -Open-source SQL IDE for cloud-native teams. One interface for 41 engines, among them PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse and Trino. Browse schemas, run queries with schema-aware autocomplete, compare schemas, and generate SQL with AI assistance. Runs on your own instance; no data leaves your account. +Open-source SQL IDE for cloud-native teams. One interface for 42 engines, among them PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse and Trino. Browse schemas, run queries with schema-aware autocomplete, compare schemas, and generate SQL with AI assistance. Runs on your own instance; no data leaves your account. diff --git a/deploy/aws/listing/listing-fields.md b/deploy/aws/listing/listing-fields.md index f78930c01d..3d3fdfdd12 100644 --- a/deploy/aws/listing/listing-fields.md +++ b/deploy/aws/listing/listing-fields.md @@ -10,7 +10,7 @@ enforces them, along with the character set the portal accepts (ASCII 0-126 plus (R), (C), (TM) and currency symbols). The engine count is checked against the code by the repo-wide catalog gate, not by a number kept here. - + ## Product title @@ -27,7 +27,7 @@ sentence verbatim, which is what the AMI product checklist asks for. -- Forty-one engines behind one interface, among them PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse and Trino. +- Forty-two engines behind one interface, among them PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse and Trino. - AI query assistance using your own model key, or run it with no AI at all. - Self-hosted on a single instance: connections, query history and results stay in your account. diff --git a/deploy/azure/listing/description.html b/deploy/azure/listing/description.html index 35ff0197b2..4f95f92ec4 100644 --- a/deploy/azure/listing/description.html +++ b/deploy/azure/listing/description.html @@ -4,10 +4,10 @@

What you get

    -
  • One workspace for forty-one engines - PostgreSQL, MySQL/MariaDB/TiDB, Microsoft SQL Server +
  • One workspace for forty-two engines - PostgreSQL, MySQL/MariaDB/TiDB, Microsoft SQL Server (including Azure SQL), Oracle, Db2 LUW, SQLite, libSQL/Turso, DuckDB, MongoDB/FerretDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, - InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B.
  • + InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B.
  • A real editor - Monaco-based SQL editing with schema-aware autocomplete, formatting, query history and virtualized result grids that stay fast on large result sets.
  • Optional, read-only AI - an agent that investigates a question you state and diff --git a/deploy/azure/listing/listing-fields.md b/deploy/azure/listing/listing-fields.md index 8d70e056b8..1dc5a4b24e 100644 --- a/deploy/azure/listing/listing-fields.md +++ b/deploy/azure/listing/listing-fields.md @@ -31,12 +31,12 @@ LibreDB Studio **Search results summary** (limit 100): -Open-source SQL IDE for 41 engines: PostgreSQL, MySQL, SQL Server, Oracle, MongoDB, Redis and more +Open-source SQL IDE for 42 engines: PostgreSQL, MySQL, SQL Server, Oracle, MongoDB, Redis and more **Short description** (limit 256): -SQL IDE for 41 engines, among them PostgreSQL, MySQL, SQL Server, Oracle, Db2 LUW, SQLite, DuckDB, MongoDB, Redis, ClickHouse, Trino, Cassandra, Prometheus, InfluxDB, Kafka, Neo4j and Qdrant, with read-only AI. +SQL IDE for 42 engines, among them PostgreSQL, MySQL, SQL Server, Oracle, Db2 LUW, SQLite, DuckDB, MongoDB, Redis, ClickHouse, Trino, Cassandra, Prometheus, InfluxDB, Kafka, Neo4j and Qdrant, Weaviate, with read-only AI. **Description** (limit 5000, HTML): see [description.html](description.html) — the limit is asserted by the unit test. @@ -75,7 +75,7 @@ Planned captions: 1. `hero-editor` — "Write and run SQL with schema-aware autocomplete and a virtualized result grid." 2. `agent-rail` — "Ask the read-only agent a question; every claim in its answer cites the result it came from." 3. `erd-diagram` — "Explore relationships with an automatically generated ERD." -4. `connection-modal`: "Connect to forty-one engines, from PostgreSQL and SQL Server to Apache Cassandra." +4. `connection-modal`: "Connect to forty-two engines, from PostgreSQL and SQL Server to Apache Cassandra." 5. `data-profiler` — "Profile table data: distributions, null ratios and outliers at a glance." ## Plan (§7.6) diff --git a/deploy/caprover/libredb-studio.yml b/deploy/caprover/libredb-studio.yml index 5f18bbfe0f..a77c1a2078 100644 --- a/deploy/caprover/libredb-studio.yml +++ b/deploy/caprover/libredb-studio.yml @@ -84,10 +84,10 @@ caproverOneClickApp: instructions: start: |- LibreDB Studio is a modern, open-source, web-based SQL IDE for the cloud era. - Query forty-one engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, + Query forty-two engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, - InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - from your browser, with an ERD viewer, schema diff and optional + InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - from your browser, with an ERD viewer, schema diff and optional read-only AI on your own model key. What you can set below (defaults are sensible - you can usually just click Deploy): @@ -173,5 +173,5 @@ caproverOneClickApp: See https://github.com/libredb/libredb-studio displayName: LibreDB Studio isOfficial: false - description: Open-source SQL IDE. Query forty-one engines - PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis and more - from your browser, with an ERD viewer, schema diff and optional read-only AI. + description: Open-source SQL IDE. Query forty-two engines - PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis and more - from your browser, with an ERD viewer, schema diff and optional read-only AI. documentation: Image and docs - https://github.com/libredb/libredb-studio . Uses ghcr.io/libredb/libredb-studio. Deploys with SQLite persistence; supports OIDC SSO and multiple AI providers via extra env vars. diff --git a/deploy/digitalocean/assets/description-long.md b/deploy/digitalocean/assets/description-long.md index 23aa5ca63b..c327270a22 100644 --- a/deploy/digitalocean/assets/description-long.md +++ b/deploy/digitalocean/assets/description-long.md @@ -2,11 +2,11 @@ **The open-source SQL IDE built for cloud-native teams.** -LibreDB Studio gives you a full-featured database workspace in your browser: connect to PostgreSQL, MySQL, MongoDB, Redis and thirty-seven more engines, write and run queries, have the optional AI explain them wherever the engine returns a query plan, and share results with your team. +LibreDB Studio gives you a full-featured database workspace in your browser: connect to PostgreSQL, MySQL, MongoDB, Redis and thirty-eight more engines, write and run queries, have the optional AI explain them wherever the engine returns a query plan, and share results with your team. ## Features -- **Forty-one engines, one interface**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B +- **Forty-two engines, one interface**: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - **Read-only AI agent**: state a question and the agent investigates it, and every claim in its report cites the result it came from; it runs statements on PostgreSQL, SQLite, DuckDB, SQL Server, MySQL, Kubernetes and MongoDB only, under the read-only boundary documented for each engine. On every other engine it drafts the statement and you run it, and nothing reaches your editor unless you consent to the hand-over when the run opens - **AI query explanation** — one click turns an unfamiliar query into plain English, with your own schema as context, on PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Couchbase, ClickHouse, Apache Druid, Trino, Databend, BigQuery, Snowflake and Apache Spark: the write-up is derived from the engine's own `EXPLAIN` plan, so it is offered where an engine returns one (bring your own key: Gemini, OpenAI, Ollama or any OpenAI-compatible endpoint; off unless configured) - **Modern editor** — autocomplete, syntax highlighting, query history diff --git a/deploy/koyeb/CATALOG_SUBMISSION.md b/deploy/koyeb/CATALOG_SUBMISSION.md index 475c52e8e9..69c6389594 100644 --- a/deploy/koyeb/CATALOG_SUBMISSION.md +++ b/deploy/koyeb/CATALOG_SUBMISSION.md @@ -53,7 +53,7 @@ a backup. > We maintain **LibreDB Studio**, an open-source, web-based SQL IDE for > cloud-native teams (PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, > MongoDB, Redis, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, -> Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, with AI-assisted querying). It's free and MIT licensed: +> Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, with AI-assisted querying). It's free and MIT licensed: > https://github.com/libredb/libredb-studio > > We already ship a working **Deploy to Koyeb** button (prebuilt GHCR image diff --git a/deploy/railway/TEMPLATE_OVERVIEW.md b/deploy/railway/TEMPLATE_OVERVIEW.md index 6857c00b76..a97ab3cd83 100644 --- a/deploy/railway/TEMPLATE_OVERVIEW.md +++ b/deploy/railway/TEMPLATE_OVERVIEW.md @@ -1,6 +1,6 @@ # Deploy and Host libredb-studio on Railway -LibreDB Studio is an open-source, web-based SQL IDE for cloud-native teams. Query PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B from your browser, with an ERD viewer, schema diff, a data profiler, and optional AI on your own model key: a read-only agent that investigates a question and cites the result each claim came from, plus one-click explanation of a query on the engines that return an `EXPLAIN` plan. No desktop client required. +LibreDB Studio is an open-source, web-based SQL IDE for cloud-native teams. Query PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B from your browser, with an ERD viewer, schema diff, a data profiler, and optional AI on your own model key: a read-only agent that investigates a question and cites the result each claim came from, plus one-click explanation of a query on the engines that return an `EXPLAIN` plan. No desktop client required. ## About Hosting libredb-studio @@ -16,7 +16,7 @@ Hosting LibreDB Studio means running a single stateless Next.js container that s ## Dependencies for libredb-studio Hosting -- A database to connect to: any of the forty-one engines above (bring your own, or add a Railway database to the project). +- A database to connect to: any of the forty-two engines above (bring your own, or add a Railway database to the project). - A persistent volume mounted at `/app/data` for the SQLite-backed store of saved connections and settings (included in this template). ### Deployment Dependencies diff --git a/deploy/railway/template.json b/deploy/railway/template.json index 42a0d52985..281e88a0e5 100644 --- a/deploy/railway/template.json +++ b/deploy/railway/template.json @@ -1,7 +1,7 @@ { "$comment": "Reviewable serialization of the LibreDB Studio Railway template. Railway does not ingest this file directly — the marketplace template is built in Railway's template editor (Workspace -> Templates -> New Template, at https://railway.com/workspace/templates). This file is the single source of truth for what to enter there (see PUBLISH.md) and what a future API automation would consume. Mirrors deploy/caprover/libredb-studio.yml.", "name": "LibreDB Studio", - "description": "Open-source web-based SQL IDE. Query forty-one engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - from your browser, with optional read-only AI on your own model key.", + "description": "Open-source web-based SQL IDE. Query forty-two engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - from your browser, with optional read-only AI on your own model key.", "tags": ["database", "sql", "ide", "postgres", "mysql", "mongodb", "redis"], "services": [ { diff --git a/deploy/rancher/CATALOG_LISTING.md b/deploy/rancher/CATALOG_LISTING.md index c5956958bb..d318fcea55 100644 --- a/deploy/rancher/CATALOG_LISTING.md +++ b/deploy/rancher/CATALOG_LISTING.md @@ -15,26 +15,26 @@ The import takes the page title from `appVersion` and the chart version from `ve Edits here do not propagate automatically — SUSE owns the page, so any change has to be mailed to the partner contact. What gets mailed is `pcsc-listing.html` beside this file, not the sections below: the page template holds at most 1494 characters including the list markup, and `tests/unit/pcsc-listing.test.ts` keeps that file under it. -> **Accuracy gate: engine count.** The wording below says forty-one engines. That is true only -> from the release that carries **Sparkplug B** ([#1720](https://github.com/libredb/libredb-studio/issues/1720)), which followed SNMP; forty is true of a release that carries **SNMP** ([#1721](https://github.com/libredb/libredb-studio/issues/1721)) and not Sparkplug B, which followed NETCONF; thirty-nine is true of a release that carries **NETCONF** ([#1724](https://github.com/libredb/libredb-studio/issues/1724)) and not SNMP, which followed Modbus; thirty-eight is true of a release that carries **Modbus** ([#1723](https://github.com/libredb/libredb-studio/issues/1723)) and not NETCONF, which followed MTConnect; thirty-seven is true of a release that carries **MTConnect** ([#1722](https://github.com/libredb/libredb-studio/issues/1722)) and not Modbus, which followed Apache Spark; thirty-six is true of a release that carries **Apache Spark** and not MTConnect, which followed OPC UA; thirty-five is true of a release that carries **OPC UA** and not Apache Spark, which followed Snowflake; thirty-four is true of a release that carries **Snowflake** and not OPC UA, which followed RabbitMQ; thirty-three is true of a release that carries **RabbitMQ** and not Snowflake, which followed Firestore; thirty-two is true of a release that carries **Firestore** and not RabbitMQ, which followed BigQuery; thirty-one is true of a release that carries **BigQuery** and not Firestore, which followed MQTT; thirty is true of a release that carries **MQTT** and not BigQuery, which followed Kubernetes; twenty-nine is true of a release that carries **Kubernetes** and not MQTT, which followed S3-compatible object storage; twenty-eight is true of a release that carries **S3-compatible object storage** and not Kubernetes, which followed Databend; twenty-seven is true of a release that carries **Databend** and not S3, which followed Oxia; twenty-six is true of a release that carries **Oxia** and not Databend, 0.18.0 among them, which followed InfluxDB; twenty-five is true of a release that carries **InfluxDB** (two connection types, InfluxQL and InfluxDB 3 SQL, so the count moves by two) and not Oxia, if one is cut, which followed Milvus; twenty-three is true of a release that carries **Milvus** (the vector-family release, [#424](https://github.com/libredb/libredb-studio/issues/424)) and not InfluxDB, if one is cut, which followed Qdrant; twenty-two is true of a release that carries **Qdrant** and not Milvus, if one is cut, which followed Db2 LUW; twenty-one is true of a release that carries **Db2 LUW** ([#786](https://github.com/libredb/libredb-studio/issues/786)) and not Qdrant, if one is cut, which followed Neo4j; twenty is true of a release that carries **Neo4j** and not Db2 LUW, if one is cut, which followed etcd; nineteen is true of a release that carries **etcd** ([#1089](https://github.com/libredb/libredb-studio/issues/1089)) and not Neo4j, if one is cut, which followed Apache Kafka; eighteen is true of a release that carries **Apache Kafka** ([#1088](https://github.com/libredb/libredb-studio/issues/1088)) and not etcd, if one is cut, which followed Prometheus; seventeen is true of a release that carries **Prometheus** ([#1085](https://github.com/libredb/libredb-studio/issues/1085)) and not Kafka, if one is cut, +> **Accuracy gate: engine count.** The wording below says forty-two engines. That is true only +> from the release that carries **Weaviate** ([#1566](https://github.com/libredb/libredb-studio/issues/1566)), which followed Sparkplug B; forty-one is true of a release that carries **Sparkplug B** ([#1720](https://github.com/libredb/libredb-studio/issues/1720)) and not Weaviate, which followed SNMP; forty is true of a release that carries **SNMP** ([#1721](https://github.com/libredb/libredb-studio/issues/1721)) and not Sparkplug B, which followed NETCONF; thirty-nine is true of a release that carries **NETCONF** ([#1724](https://github.com/libredb/libredb-studio/issues/1724)) and not SNMP, which followed Modbus; thirty-eight is true of a release that carries **Modbus** ([#1723](https://github.com/libredb/libredb-studio/issues/1723)) and not NETCONF, which followed MTConnect; thirty-seven is true of a release that carries **MTConnect** ([#1722](https://github.com/libredb/libredb-studio/issues/1722)) and not Modbus, which followed Apache Spark; thirty-six is true of a release that carries **Apache Spark** and not MTConnect, which followed OPC UA; thirty-five is true of a release that carries **OPC UA** and not Apache Spark, which followed Snowflake; thirty-four is true of a release that carries **Snowflake** and not OPC UA, which followed RabbitMQ; thirty-three is true of a release that carries **RabbitMQ** and not Snowflake, which followed Firestore; thirty-two is true of a release that carries **Firestore** and not RabbitMQ, which followed BigQuery; thirty-one is true of a release that carries **BigQuery** and not Firestore, which followed MQTT; thirty is true of a release that carries **MQTT** and not BigQuery, which followed Kubernetes; twenty-nine is true of a release that carries **Kubernetes** and not MQTT, which followed S3-compatible object storage; twenty-eight is true of a release that carries **S3-compatible object storage** and not Kubernetes, which followed Databend; twenty-seven is true of a release that carries **Databend** and not S3, which followed Oxia; twenty-six is true of a release that carries **Oxia** and not Databend, 0.18.0 among them, which followed InfluxDB; twenty-five is true of a release that carries **InfluxDB** (two connection types, InfluxQL and InfluxDB 3 SQL, so the count moves by two) and not Oxia, if one is cut, which followed Milvus; twenty-three is true of a release that carries **Milvus** (the vector-family release, [#424](https://github.com/libredb/libredb-studio/issues/424)) and not InfluxDB, if one is cut, which followed Qdrant; twenty-two is true of a release that carries **Qdrant** and not Milvus, if one is cut, which followed Db2 LUW; twenty-one is true of a release that carries **Db2 LUW** ([#786](https://github.com/libredb/libredb-studio/issues/786)) and not Qdrant, if one is cut, which followed Neo4j; twenty is true of a release that carries **Neo4j** and not Db2 LUW, if one is cut, which followed etcd; nineteen is true of a release that carries **etcd** ([#1089](https://github.com/libredb/libredb-studio/issues/1089)) and not Neo4j, if one is cut, which followed Apache Kafka; eighteen is true of a release that carries **Apache Kafka** ([#1088](https://github.com/libredb/libredb-studio/issues/1088)) and not etcd, if one is cut, which followed Prometheus; seventeen is true of a release that carries **Prometheus** ([#1085](https://github.com/libredb/libredb-studio/issues/1085)) and not Kafka, if one is cut, > which followed DuckDB; sixteen was true from the release that carried **DuckDB** > ([#424](https://github.com/libredb/libredb-studio/issues/424)), which followed libSQL, and fourteen from **0.13.0** onwards, the release that carried > Elasticsearch, OpenSearch, Trino and Apache Cassandra alongside the ten of 0.11.0. > The number is the `SHIPPED` record in > `src/lib/db/compatibility.ts` minus the embedded `libredb`, which `EXTERNAL` in the same > file already splits out; read it from there rather than from this file. The catalog entry -> is version-scoped, so do not publish the forty-one-engine wording against a version that -> predates Sparkplug B: send the forty-engine variant for a release with SNMP and not Sparkplug B (its size-cut body is `pcsc-listing.html` at 4c953c352), the thirty-nine-engine variant for a release with NETCONF and not SNMP (its size-cut body is `pcsc-listing.html` at ee8e4c796), the thirty-eight-engine variant for a release with Modbus and not NETCONF (its size-cut body is `pcsc-listing.html` at 198990832), the thirty-seven-engine variant for a release with MTConnect and not Modbus (its size-cut body is `pcsc-listing.html` at eab62f513), the thirty-six-engine variant for a release with Apache Spark and not MTConnect (its size-cut body is `pcsc-listing.html` at d7ec5b1b7), the thirty-five-engine variant for a release with OPC UA and not Apache Spark (its size-cut body is `pcsc-listing.html` at f447c9b7d), the thirty-four-engine variant for a release with Snowflake and not OPC UA (its size-cut body is `pcsc-listing.html` at 31c3ca8c), the thirty-three-engine variant for a release with RabbitMQ and not Snowflake (its size-cut body is `pcsc-listing.html` at ef21d3f60), the thirty-two-engine variant for a release with Firestore and not RabbitMQ (its size-cut body is `pcsc-listing.html` at 60f691d29), the thirty-one-engine variant for a release with BigQuery and not Firestore (its size-cut body is `pcsc-listing.html` at d28cd1e42), the thirty-engine variant for a release with MQTT and not BigQuery, the twenty-nine-engine variant for a release with Kubernetes and not MQTT (its size-cut body is `pcsc-listing.html` at c23f3890), the twenty-eight-engine variant for a release with S3-compatible object storage and not Kubernetes (its size-cut body is `pcsc-listing.html` at 11717b7e5), the twenty-seven-engine variant for a release with Databend and not S3 (its size-cut body is `pcsc-listing.html` at d5e5a9aff), the twenty-six-engine variant for a release with Oxia and not Databend (its size-cut body is `pcsc-listing.html` at a7f06def), the twenty-five-engine variant for a release with InfluxDB and not Oxia (its size-cut body is `pcsc-listing.html` at eacf73a3), the twenty-three-engine variant for a release with Milvus and not InfluxDB (its size-cut body is `pcsc-listing.html` at 046f0ee9), the twenty-two-engine variant for a release with Qdrant and not Milvus (its size-cut body is `pcsc-listing.html` at d8070ec6), the twenty-one-engine variant for a release with Db2 LUW and not Qdrant (its size-cut body is `pcsc-listing.html` at 214f6537), the twenty-engine variant for a release with Neo4j and not Db2 LUW (its size-cut body is `pcsc-listing.html` at 23f5c859), the nineteen-engine variant for a release with etcd and not Neo4j (its size-cut body is `pcsc-listing.html` at 42050550), the eighteen-engine variant for a release with Apache Kafka and not etcd (its size-cut body is `pcsc-listing.html` at 2ddb99c9), the seventeen-engine variant for a release with Prometheus and not Kafka (its size-cut body is `pcsc-listing.html` at 8dfdfcce), the sixteen-engine variant (the DuckDB release onwards; its size-cut body is `pcsc-listing.html` at 06a4cb11), the fourteen-engine one (0.13.0 onwards), the ten-engine one +> is version-scoped, so do not publish the forty-two-engine wording against a version that +> predates Weaviate: send the forty-one-engine variant for a release with Sparkplug B and not Weaviate (its size-cut body is `pcsc-listing.html` at a52724fee), the forty-engine variant for a release with SNMP and not Sparkplug B (its size-cut body is `pcsc-listing.html` at 4c953c352), the thirty-nine-engine variant for a release with NETCONF and not SNMP (its size-cut body is `pcsc-listing.html` at ee8e4c796), the thirty-eight-engine variant for a release with Modbus and not NETCONF (its size-cut body is `pcsc-listing.html` at 198990832), the thirty-seven-engine variant for a release with MTConnect and not Modbus (its size-cut body is `pcsc-listing.html` at eab62f513), the thirty-six-engine variant for a release with Apache Spark and not MTConnect (its size-cut body is `pcsc-listing.html` at d7ec5b1b7), the thirty-five-engine variant for a release with OPC UA and not Apache Spark (its size-cut body is `pcsc-listing.html` at f447c9b7d), the thirty-four-engine variant for a release with Snowflake and not OPC UA (its size-cut body is `pcsc-listing.html` at 31c3ca8c), the thirty-three-engine variant for a release with RabbitMQ and not Snowflake (its size-cut body is `pcsc-listing.html` at ef21d3f60), the thirty-two-engine variant for a release with Firestore and not RabbitMQ (its size-cut body is `pcsc-listing.html` at 60f691d29), the thirty-one-engine variant for a release with BigQuery and not Firestore (its size-cut body is `pcsc-listing.html` at d28cd1e42), the thirty-engine variant for a release with MQTT and not BigQuery, the twenty-nine-engine variant for a release with Kubernetes and not MQTT (its size-cut body is `pcsc-listing.html` at c23f3890), the twenty-eight-engine variant for a release with S3-compatible object storage and not Kubernetes (its size-cut body is `pcsc-listing.html` at 11717b7e5), the twenty-seven-engine variant for a release with Databend and not S3 (its size-cut body is `pcsc-listing.html` at d5e5a9aff), the twenty-six-engine variant for a release with Oxia and not Databend (its size-cut body is `pcsc-listing.html` at a7f06def), the twenty-five-engine variant for a release with InfluxDB and not Oxia (its size-cut body is `pcsc-listing.html` at eacf73a3), the twenty-three-engine variant for a release with Milvus and not InfluxDB (its size-cut body is `pcsc-listing.html` at 046f0ee9), the twenty-two-engine variant for a release with Qdrant and not Milvus (its size-cut body is `pcsc-listing.html` at d8070ec6), the twenty-one-engine variant for a release with Db2 LUW and not Qdrant (its size-cut body is `pcsc-listing.html` at 214f6537), the twenty-engine variant for a release with Neo4j and not Db2 LUW (its size-cut body is `pcsc-listing.html` at 23f5c859), the nineteen-engine variant for a release with etcd and not Neo4j (its size-cut body is `pcsc-listing.html` at 42050550), the eighteen-engine variant for a release with Apache Kafka and not etcd (its size-cut body is `pcsc-listing.html` at 2ddb99c9), the seventeen-engine variant for a release with Prometheus and not Kafka (its size-cut body is `pcsc-listing.html` at 8dfdfcce), the sixteen-engine variant (the DuckDB release onwards; its size-cut body is `pcsc-listing.html` at 06a4cb11), the fourteen-engine one (0.13.0 onwards), the ten-engine one > (0.11.0 onwards) or the eight-engine one instead. > -> **The scope goes with the count.** Browsing and querying reach all forty-one; editing data does +> **The scope goes with the count.** Browsing and querying reach all forty-two; editing data does > not, so "manage data across …" must never be written over the whole list. Read the split from > the providers: `supportsInlineRowEdit` defaults to `true` in `src/lib/db/base-provider.ts` and > each provider that cannot turns it off, while only a provider that declares a `createTable` > grammar offers table creation, which leaves inline > row editing on PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL and DuckDB, and table > creation on the same engines except Db2 LUW, plus Trino. Every other engine (BigQuery, Cassandra, ClickHouse, Couchbase, Databend, Druid, -> Elasticsearch, Firestore, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, Kubernetes, Milvus, MongoDB, MQTT, Neo4j, OPC UA, OpenSearch, Oxia, Prometheus, Qdrant, RabbitMQ, Redis, S3-compatible object storage, Snowflake, Apache Spark and etcd) reports those controls as unsupported. The +> Elasticsearch, Firestore, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, Kubernetes, Milvus, MongoDB, MQTT, Neo4j, OPC UA, OpenSearch, Oxia, Prometheus, Qdrant, RabbitMQ, Redis, S3-compatible object storage, Snowflake, Apache Spark, Weaviate and etcd) reports those controls as unsupported. The > reason differs per engine and the copy must not flatten it: on Elasticsearch no mutation is in > the SQL grammar at all, while OpenSearch's grammar carries exactly one — `DELETE`, off by > default on the cluster (`docs/providers/opensearch.md` §5.6, and `SEARCH_SCHEMA_REFRESH_PATTERN` @@ -122,7 +122,7 @@ What gets mailed is `pcsc-listing.html` beside this file, not the sections below > were read again when MTConnect landed (#1722) and all three ended at OPC UA, so the warning > holds twice over: nothing fails when they go stale, and they went stale again. > `packaging/linux/nfpm.yaml` and the operator CSVs are consumed at release time from `main`, -> so `nfpm.yaml` and the operator CSVs name forty-one now, and the next tag publishes both. +> so `nfpm.yaml` and the operator CSVs name forty-two now, and the next tag publishes both. ## Listing facts @@ -148,14 +148,14 @@ What gets mailed is `pcsc-listing.html` beside this file, not the sections below LibreDB Studio is an MIT-licensed, AI-assisted open source SQL IDE that connects to PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, -Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ and OPC UA directly from the browser. +Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ and OPC UA directly from the browser. ## Long description LibreDB Studio brings a full SQL IDE to Rancher-managed Kubernetes clusters: browse schemas and run queries across PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, -Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ and OPC UA from a single web interface, with no desktop +Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ and OPC UA from a single web interface, with no desktop client to install. Editing data follows the engine rather than the IDE: inline row editing on PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL and DuckDB, table creation on the same engines @@ -181,9 +181,9 @@ versions are documented and validated for every release. ## Key features (bullet form, if the catalog template asks for them) -- Forty-one database engines in one browser-based IDE: PostgreSQL, MySQL, Oracle, +- Forty-two database engines in one browser-based IDE: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, - Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B + Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - One-click install from the Rancher Apps catalog — deployable with default values, zero configuration required - Optional AI assistance (Gemini, OpenAI, or a self-hosted model; off by default): diff --git a/deploy/rancher/app-readme.md b/deploy/rancher/app-readme.md index 2ce3fb5449..574fccb0a6 100644 --- a/deploy/rancher/app-readme.md +++ b/deploy/rancher/app-readme.md @@ -1,11 +1,11 @@ # LibreDB Studio -LibreDB Studio is an MIT-licensed, AI-assisted open source SQL IDE that connects to forty-one database engines directly from the browser. +LibreDB Studio is an MIT-licensed, AI-assisted open source SQL IDE that connects to forty-two database engines directly from the browser. Use cases: * Browser-based database management - * Browse schemas and run queries across forty-one engines: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. Editing data follows the engine rather than the IDE: inline row editing on PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL and DuckDB, and everywhere else the controls are reported as unsupported rather than offered and then failed. + * Browse schemas and run queries across forty-two engines: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. Editing data follows the engine rather than the IDE: inline row editing on PostgreSQL, MySQL, Oracle, SQL Server, SQLite, libSQL and DuckDB, and everywhere else the controls are reported as unsupported rather than offered and then failed. * AI-assisted querying * An optional AI assistant (bring your own key: Gemini, OpenAI, or a local model) explains a query in plain English from the engine's own EXPLAIN plan, on PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Couchbase, ClickHouse, Apache Druid, Trino, Databend, BigQuery, Snowflake and Apache Spark. It also runs a read-only investigation agent on PostgreSQL, SQLite, DuckDB, SQL Server, MySQL, Kubernetes and MongoDB that never writes, under the read-only boundary documented for each engine. It stays off unless you configure a provider. * Self-hosted data diff --git a/deploy/rancher/pcsc-listing.html b/deploy/rancher/pcsc-listing.html index c07d5154a5..a63833531e 100644 --- a/deploy/rancher/pcsc-listing.html +++ b/deploy/rancher/pcsc-listing.html @@ -1,8 +1,8 @@ -LibreDB Studio brings a SQL IDE to Rancher-managed Kubernetes clusters: browse schemas, run queries across forty-one engines with no desktop app. Where an engine cannot edit data, the controls say so. +LibreDB Studio brings a SQL IDE to Rancher-managed Kubernetes clusters: browse schemas, run queries across forty-two engines with no desktop app. Where an engine cannot edit data, the controls say so. Installs from the Rancher Apps catalog: first-run admin credentials are generated and logged; production can supply its own secrets. Developed and commercially supported by LibreDB.
      -
    • Forty-one engines: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B
    • +
    • Forty-two engines: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP, Sparkplug B
    • Optional AI, off by default (bring your own key): plain-English explanation of the EXPLAIN plan on PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Couchbase, ClickHouse, Apache Druid, Trino, Databend, BigQuery, Snowflake and Apache Spark. A read-only agent on PostgreSQL, SQLite, DuckDB, SQL Server, MySQL, Kubernetes and MongoDB never writes
    • Hardened defaults: non-root, read-only root filesystem, NetworkPolicy, PDB, HPA, Ingress/TLS
    • Self-hosted, air-gap friendly: no external services
    • diff --git a/desktop/src-tauri/desktop-entry.hbs b/desktop/src-tauri/desktop-entry.hbs index 9d887d2579..ac76b197bb 100644 --- a/desktop/src-tauri/desktop-entry.hbs +++ b/desktop/src-tauri/desktop-entry.hbs @@ -7,6 +7,6 @@ Exec={{exec}} Icon={{icon}} Terminal=false Categories={{categories}} -Keywords=SQL;Database;PostgreSQL;MySQL;SQLite;libSQL;Turso;DuckDB;MongoDB;Redis;Oracle;Db2;SQLServer;ClickHouse;Couchbase;Druid;Elasticsearch;OpenSearch;Trino;Databend;Spark;Cassandra;Prometheus;PromQL;InfluxDB;InfluxQL;Kafka;MQTT;RabbitMQ;AMQP;OPCUA;OPC-UA;etcd;Neo4j;Cypher;Milvus;Qdrant;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;Query; +Keywords=SQL;Database;PostgreSQL;MySQL;SQLite;libSQL;Turso;DuckDB;MongoDB;Redis;Oracle;Db2;SQLServer;ClickHouse;Couchbase;Druid;Elasticsearch;OpenSearch;Trino;Databend;Spark;Cassandra;Prometheus;PromQL;InfluxDB;InfluxQL;Kafka;MQTT;RabbitMQ;AMQP;OPCUA;OPC-UA;etcd;Neo4j;Cypher;Milvus;Qdrant;Weaviate;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;Query; StartupNotify=true StartupWMClass=libredb-studio-desktop diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index 75119ec130..4e63c53f0e 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -30,7 +30,7 @@ "targets": ["appimage", "deb"], "category": "DeveloperTool", "shortDescription": "The open-source SQL IDE for cloud-native teams", - "longDescription": "LibreDB Studio is an open-source SQL IDE for PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect and Modbus, with AI query assistance. The desktop build runs the same server LibreDB Studio ships everywhere else as a local sidecar and keeps all data on this machine.", + "longDescription": "LibreDB Studio is an open-source SQL IDE for PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect and Modbus, with AI query assistance. The desktop build runs the same server LibreDB Studio ships everywhere else as a local sidecar and keeps all data on this machine.", "homepage": "https://libredb.org", "publisher": "LibreDB", "license": "MIT", diff --git a/docker/weaviate/README.md b/docker/weaviate/README.md new file mode 100644 index 0000000000..edc816499e --- /dev/null +++ b/docker/weaviate/README.md @@ -0,0 +1,100 @@ +# Weaviate fixtures + +The live Weaviate servers of `database-compose.yml`, the one-shots that seed them and generate their keys, and the scripts those one-shots run. +They were built for the Weaviate provider's design measurements (#1566), so each server and each seeded collection below exists for a measured rule and says which. + +## The servers + +| Service | Profile | From the host | Version | Transport and authentication | +|---|---|---|---|---| +| `weaviate` | none | `127.0.0.1:18280` | 1.40.2 | Plaintext, anonymous; every REST search route served | +| `weaviate-1-37` | `weaviate-matrix` | `127.0.0.1:18281` | 1.37.4 | Plaintext, anonymous; no REST search, GraphQL only | +| `weaviate-1-38` | `weaviate-matrix` | `127.0.0.1:18285` | 1.38.22 | Plaintext, anonymous; REST search behind its flag, left off; GraphQL | +| `weaviate-nographql` | `weaviate-matrix` | `127.0.0.1:18282` | 1.40.2 | Plaintext, anonymous, `DISABLE_GRAPHQL=true` | +| `weaviate-auth` | `weaviate-secure` | `127.0.0.1:18283` | 1.40.2 | Plaintext, API keys and RBAC, anonymous access off | +| `weaviate-tls` | `weaviate-secure` | `127.0.0.1:18284` | 1.40.2 | TLS on Weaviate's own listener, API keys and RBAC | + +The three shapes a provider must read are one per row of the matrix: +1.40 serves REST search for every route, 1.37.4 is the version DigitalOcean Managed Weaviate runs and has no REST search at all, 1.38.22 carries REST search behind `EXPERIMENTAL_REST_SEARCH_ENABLED` (off, its default), and 1.40 with GraphQL disabled is how new Weaviate Cloud clusters are created. +1.37 left Weaviate's support window (the three most recent minors) when 1.40 shipped; it is here because a managed service still runs it. + +The one-shots are `weaviate-seed` (seeds `weaviate`), `weaviate-matrix-seed` (seeds the three matrix servers), `weaviate-keys` (generates the root key and the certificate) and `weaviate-secure-seed` (seeds both keyed servers and creates their viewer user). + +Every server runs `cr.weaviate.io/semitechnologies/weaviate`, pinned by tag and digest in the compose file. +The one-shots run `python:3.14-slim` and `alpine/openssl:3.5.8`, each pinned by digest. +Every server sets `DEFAULT_VECTORIZER_MODULE=none` and `API_BASED_MODULES_DISABLED=true`, so `/v1/meta` lists no module and no request can reach a model provider. +An empty `ENABLE_MODULES` is not enough: a server without `API_BASED_MODULES_DISABLED` loads every API-based module (45 on 1.40.2, from `generative-openai` to `text2vec-digitalocean`). +Every server sets `DISABLE_TELEMETRY`. +No server publishes gRPC 50051, which the provider never dials, and no server has a data volume: removing a container resets it, and the seed fills it again. +Every port is bound to a loopback address only, and each server is bounded to 2 CPUs and 1 GiB. + +The keyed servers read their root key from the `weaviate-keys` volume: Weaviate takes keys from the environment alone, so the image's own `sh` exports the key and execs the server, and the key never appears in the compose file. +`weaviate-tls` keeps its plain listener inside the container for the health probe, because busybox `wget` verifies the certificate and has no option for the fixture's CA; only 8443 is published. + +## Bringing them up + +```sh +docker compose -p libredb-studio -f database-compose.yml up -d --wait weaviate +docker compose -p libredb-studio -f database-compose.yml up -d weaviate-seed +docker wait libredb-weaviate-seed + +docker compose -p libredb-studio -f database-compose.yml --profile weaviate-matrix up -d --wait \ + weaviate-1-37 weaviate-1-38 weaviate-nographql +docker compose -p libredb-studio -f database-compose.yml --profile weaviate-matrix up -d weaviate-matrix-seed +docker wait libredb-weaviate-matrix-seed + +docker compose -p libredb-studio -f database-compose.yml --profile weaviate-secure up -d weaviate-keys +docker wait libredb-weaviate-keys +docker compose -p libredb-studio -f database-compose.yml --profile weaviate-secure up -d --wait \ + weaviate-auth weaviate-tls +docker compose -p libredb-studio -f database-compose.yml --profile weaviate-secure up -d weaviate-secure-seed +docker wait libredb-weaviate-secure-seed +``` + +Each `docker wait` must print `0`. +A second run of any seed writes nothing. + +## The keys + +```sh +docker cp libredb-weaviate-auth:/keys/root.key - # root, the RBAC root user +docker cp libredb-weaviate-auth:/keys/auth/reader.key - # reader on weaviate-auth, built-in role viewer +docker cp libredb-weaviate-auth:/keys/tls/reader.key - # reader on weaviate-tls +docker cp libredb-weaviate-auth:/keys/ca.pem - # the CA weaviate-tls's certificate chains to +``` + +The certificate names `localhost`, `127.0.0.1` and `weaviate-tls`. +To start over, remove the keyed containers and the `weaviate-keys` volume together. + +## The seeded collections + +Every vector comes from `random.Random` with a fixed seed, every id is a `uuid5` of a fixed namespace and every date is fixed, so the same objects exist on every server. +The seed uses only schema fields the 1.37 line accepts, so one corpus seeds the whole matrix. + +| Collection | Objects | Exists for | +|---|---|---| +| `Article` | 500 | one unnamed 16-dimension cosine vector, every common property type (text, text[], int, number, boolean, date, geoCoordinates, a nested object) and a cross-reference to `Author`; more than one cursor page | +| `Author` | 12 | objects with no vector at all | +| `Product` | 200 | two named vectors with different dimensions, distances and index types (`image` 8-d cosine HNSW, `text` 16-d dot flat) | +| `TenantNotes` | 20 per tenant | multi-tenancy with `autoTenantActivation` off: `acme` and `globex` HOT, `initech` COLD | +| `TenantNotesAuto` | 20 per tenant | `autoTenantActivation` on: `hooli` HOT, `umbrella` COLD | +| `EdgeValues` | 8 | int values at and past 2^53 and at the int64 bounds | +| `Empty` | 0 | a collection with no objects | + +Alias `Articles` points at `Article`. +Each COLD tenant is written while HOT and set COLD last, so it holds objects a read could try to wake. + +`EdgeValues` shows what the server keeps, not what the seed sent: Weaviate stores an `int` property as a float64 (`intVal` in `usecases/objects/validation/properties_validation.go`), so 2^53 + 1 reads back as 2^53 on every path, and 2^63 - 1 is refused when written through gRPC. +The seed writes through REST, where the JSON value is rounded the same way. + +`seed.py --verify` reads every collection back, counts its objects with cursor pages, checks each tenant's activity status and the alias, and exits 1 on a difference. + +## Reading a cold tenant wakes it + +On a collection with `autoTenantActivation` on, any data read of a COLD tenant (an object list or read by id, GraphQL `Get` or `Aggregate`, a REST search or aggregate, `/v1/schema/{collection}/shards?tenant=`) sets it HOT, also for a user with only the built-in `viewer` role. +Reading a tenant's own record (`GET` or `HEAD /v1/schema/{collection}/tenants/{tenant}`), the tenant list and `/v1/nodes` does not. +Re-run the seed's last step by hand, or remove the container, to make a tenant COLD again. + +On the 1.37 line (measured on 1.37.4 and 1.37.17), `/v1/schema/TenantNotesAuto/shards?tenant=umbrella` with `umbrella` COLD wakes the tenant and then does not answer (one wait was cut at 312 s), and from then on that collection's `/shards` answers for no tenant, HOT ones included, until the server restarts; other routes and collections keep working. +1.38.22 and later answer the same request in milliseconds. +Do not send it to `weaviate-1-37` unless that is the test. diff --git a/docker/weaviate/keys.sh b/docker/weaviate/keys.sh new file mode 100644 index 0000000000..2fe44498d8 --- /dev/null +++ b/docker/weaviate/keys.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Generates the keyed Weaviate fixtures' root key and the TLS material into a named volume at first start, so no key +# and no private key is ever committed (the Secret Scan's default rules). +# keys.sh +# Runs once: a second start finds the marker and leaves everything as it is; to start over, remove the weaviate-keys +# volume with the containers that use it. Every file is world-readable, because the host-side harnesses copy them +# out with `docker cp` (README.md); they protect nothing but a loopback-only fixture. +# root.key the key of user root, the one RBAC root user on weaviate-auth and weaviate-tls +# ca.pem, server.pem, server.key the certificate weaviate-tls serves +# auth/reader.key, tls/reader.key are written later by the seed, which creates db user reader with role viewer +set -eu +cd "$1" +[ -f .complete ] && { echo "keys already in $1"; exit 0; } +rm -rf -- auth tls ./*.pem ./*.key ./*.srl + +openssl req -x509 -newkey rsa:2048 -nodes -keyout ca.key -out ca.pem -days 3650 -subj "/CN=libredb-weaviate-ca" \ + -addext "basicConstraints=critical,CA:TRUE" -addext "keyUsage=critical,keyCertSign,cRLSign" 2>/dev/null +openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=localhost" 2>/dev/null +printf '%s\n' "basicConstraints=critical,CA:FALSE +keyUsage=critical,digitalSignature,keyEncipherment +extendedKeyUsage=serverAuth +subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:weaviate-tls" >server.ext +openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem -days 3650 \ + -extfile server.ext 2>/dev/null +rm -f server.csr server.ext ca.key ca.srl + +openssl rand -hex 32 >root.key +mkdir auth tls +chmod -R a+rX . +chmod a+r ./*.pem ./*.key +# The seed writes reader.key into these as another user. +chmod a+w auth tls +touch .complete +echo "keys written to $1" diff --git a/docker/weaviate/seed.py b/docker/weaviate/seed.py new file mode 100644 index 0000000000..c0185481a4 --- /dev/null +++ b/docker/weaviate/seed.py @@ -0,0 +1,354 @@ +#!/usr/bin/env python3 +"""Seeds a Weaviate service of database-compose.yml for the vector fixtures (docker/weaviate/README.md). + + seed.py --url URL [--api-key-file FILE] [--cacert FILE] [--reader-key-out FILE] + create what is missing; a second run does no work + seed.py --url URL [--api-key-file FILE] [--cacert FILE] --verify + read every seeded collection back, print a report, exit 1 on a difference + +--reader-key-out, on an RBAC server, also creates db user reader with the built-in viewer role and writes its key to +FILE; a user that exists while FILE does not has its key rotated, since the server shows a key only once. + +Standard library only, so the seed installs nothing. Every vector comes from random.Random with a fixed seed per +collection, ids are uuid5 of a fixed namespace and dates are fixed, so every object is byte-identical across servers +and resets. The same corpus seeds every version of the matrix, from the 1.37 line up, so it uses only schema fields +that line accepts. Progress goes to stderr. +""" + +import argparse +import json +import os +import random +import ssl +import sys +import time +import urllib.error +import urllib.request +import uuid + +UUID_NS = uuid.UUID("3d1b7a40-5b0e-4f7e-9a51-000000000000") +TWO_53 = 2**53 +# 2^53 - 1 is the largest integer a JS number holds exactly, 2^53 + 1 the first it cannot; then the int64 bounds. +EDGE_INTS = [0, 42, -42, TWO_53 - 1, TWO_53 + 1, 2**62 + 7, 2**63 - 1, -(2**63)] +DIM_ARTICLE = 16 +DIM_IMAGE = 8 +DIM_TEXT = 16 +N_ARTICLE = 500 +N_AUTHOR = 12 +N_PRODUCT = 200 +N_NOTES = 20 +DATE = "2026-10-01T12:00:00Z" +CATEGORIES = ["alpha", "beta", "gamma", "delta", "epsilon"] +WORDS = ["vector", "search", "engine", "filter", "index", "graph", "cosine", "shard", "tenant", "alias", + "collection", "replica", "quantize", "hybrid", "keyword", "recall", "object", "property", "schema", "node"] + +# Tenant activity is set after the data is written, so a COLD tenant holds objects a read could try to wake. +TENANTS = { + "TenantNotes": {"acme": "HOT", "globex": "HOT", "initech": "COLD"}, + "TenantNotesAuto": {"umbrella": "COLD", "hooli": "HOT"}, +} +ALIASES = {"Articles": "Article"} + +SCHEMA = [ + { + "class": "Author", + "description": "objects with no vector at all", + "vectorizer": "none", + "properties": [ + {"name": "name", "dataType": ["text"]}, + {"name": "country", "dataType": ["text"], "tokenization": "field"}, + ], + }, + { + "class": "Article", + "description": "one unnamed vector, a cross-reference and the common property types", + "vectorizer": "none", + "vectorIndexConfig": {"distance": "cosine"}, + "invertedIndexConfig": {"indexTimestamps": True}, + "properties": [ + {"name": "title", "dataType": ["text"]}, + {"name": "body", "dataType": ["text"]}, + {"name": "category", "dataType": ["text"], "tokenization": "field"}, + {"name": "tags", "dataType": ["text[]"]}, + {"name": "wordCount", "dataType": ["int"]}, + {"name": "rating", "dataType": ["number"]}, + {"name": "published", "dataType": ["boolean"]}, + {"name": "publishedAt", "dataType": ["date"]}, + {"name": "location", "dataType": ["geoCoordinates"]}, + {"name": "meta", "dataType": ["object"], "nestedProperties": [ + {"name": "source", "dataType": ["text"]}, + {"name": "revision", "dataType": ["int"]}, + ]}, + {"name": "writtenBy", "dataType": ["Author"]}, + ], + }, + { + "class": "Product", + "description": "two named vectors with different dimensions and distances", + "vectorConfig": { + "image": {"vectorizer": {"none": {}}, "vectorIndexType": "hnsw", + "vectorIndexConfig": {"distance": "cosine"}}, + "text": {"vectorizer": {"none": {}}, "vectorIndexType": "flat", + "vectorIndexConfig": {"distance": "dot"}}, + }, + "properties": [ + {"name": "name", "dataType": ["text"]}, + {"name": "price", "dataType": ["number"]}, + {"name": "sku", "dataType": ["uuid"]}, + ], + }, + { + "class": "TenantNotes", + "description": "multi-tenant, a read does not activate a tenant", + "vectorizer": "none", + "multiTenancyConfig": {"enabled": True, "autoTenantCreation": False, "autoTenantActivation": False}, + "properties": [{"name": "note", "dataType": ["text"]}, {"name": "seq", "dataType": ["int"]}], + }, + { + "class": "TenantNotesAuto", + "description": "multi-tenant with autoTenantActivation on", + "vectorizer": "none", + "multiTenancyConfig": {"enabled": True, "autoTenantCreation": False, "autoTenantActivation": True}, + "properties": [{"name": "note", "dataType": ["text"]}, {"name": "seq", "dataType": ["int"]}], + }, + { + "class": "EdgeValues", + "description": "int64 values a float64 cannot hold, one object per value", + "vectorizer": "none", + "properties": [ + {"name": "label", "dataType": ["text"]}, + {"name": "big", "dataType": ["int"]}, + {"name": "bigs", "dataType": ["int[]"]}, + ], + }, + {"class": "Empty", "description": "no objects", "vectorizer": "none", + "properties": [{"name": "label", "dataType": ["text"]}]}, +] + + +def oid(collection, n, tenant=""): + return str(uuid.uuid5(UUID_NS, f"{collection}/{tenant}/{n}")) + + +def vec(rng, dim): + return [round(rng.uniform(-1, 1), 6) for _ in range(dim)] + + +def words(rng, n): + return " ".join(rng.choice(WORDS) for _ in range(n)) + + +class Client: + def __init__(self, url, api_key, cacert=None): + self.url = url.rstrip("/") + self.headers = {"Content-Type": "application/json"} + if api_key: + self.headers["Authorization"] = f"Bearer {api_key}" + self.context = ssl.create_default_context(cafile=cacert) if cacert else None + + def call(self, method, path, body=None, ok=(200,)): + data = None if body is None else json.dumps(body).encode() + req = urllib.request.Request(self.url + path, data=data, method=method, headers=self.headers) + try: + with urllib.request.urlopen(req, timeout=60, context=self.context) as resp: + status, raw = resp.status, resp.read() + except urllib.error.HTTPError as err: + status, raw = err.code, err.read() + if status not in ok: + raise RuntimeError(f"{method} {path}: HTTP {status}: {raw[:400].decode(errors='replace')}") + return status, (json.loads(raw) if raw.strip() else None) + + def wait_ready(self, seconds=120): + deadline = time.time() + seconds + while time.time() < deadline: + try: + if self.call("GET", "/v1/.well-known/ready", ok=(200, 503))[0] == 200: + return + except (urllib.error.URLError, ConnectionError, OSError): + pass + time.sleep(1) + raise RuntimeError(f"{self.url} not ready after {seconds}s") + + +def log(msg): + print(msg, file=sys.stderr, flush=True) + + +def article_objects(): + rng = random.Random(20261023) + out = [] + for i in range(N_ARTICLE): + props = { + "title": f"article {i:03d} {words(rng, 2)}", + "body": words(rng, 12), + "category": CATEGORIES[i % len(CATEGORIES)], + "tags": sorted({rng.choice(WORDS) for _ in range(3)}), + "wordCount": 100 + i, + "rating": round(i / 100, 2), + "published": i % 3 != 0, + "publishedAt": DATE, + "location": {"latitude": 59.437 + i / 1000, "longitude": 24.7536}, + "meta": {"source": "seed", "revision": i % 4}, + "writtenBy": [{"beacon": f"weaviate://localhost/Author/{oid('Author', i % N_AUTHOR)}"}], + } + out.append({"class": "Article", "id": oid("Article", i), "properties": props, "vector": vec(rng, DIM_ARTICLE)}) + return out + + +def author_objects(): + return [{"class": "Author", "id": oid("Author", i), + "properties": {"name": f"author {i:02d}", "country": ["EE", "TR", "DE", "BR"][i % 4]}} + for i in range(N_AUTHOR)] + + +def product_objects(): + rng = random.Random(7) + return [{"class": "Product", "id": oid("Product", i), + "properties": {"name": f"product {i:03d}", "price": round(1 + i * 0.25, 2), + "sku": str(uuid.uuid5(UUID_NS, f"sku/{i}"))}, + "vectors": {"image": vec(rng, DIM_IMAGE), "text": vec(rng, DIM_TEXT)}} + for i in range(N_PRODUCT)] + + +def note_objects(collection): + out = [] + for tenant in TENANTS[collection]: + for i in range(N_NOTES): + out.append({"class": collection, "tenant": tenant, "id": oid(collection, i, tenant), + "properties": {"note": f"{tenant} note {i:02d}", "seq": i}}) + return out + + +def edge_objects(): + return [{"class": "EdgeValues", "id": oid("EdgeValues", i), + "properties": {"label": str(v), "big": v, "bigs": [v, 1]}} + for i, v in enumerate(EDGE_INTS)] + + +def batch(client, objects, size=100): + for start in range(0, len(objects), size): + _, result = client.call("POST", "/v1/batch/objects", {"objects": objects[start:start + size]}) + # A batch answers 200 with per-object errors, so each result is read. + errors = [r["result"]["errors"] for r in result if r.get("result", {}).get("errors")] + if errors: + raise RuntimeError(f"batch errors: {json.dumps(errors[:3])}") + + +def seed(client): + _, schema = client.call("GET", "/v1/schema") + existing = {c["class"] for c in schema.get("classes") or []} + created = [] + for cls in SCHEMA: + if cls["class"] not in existing: + client.call("POST", "/v1/schema", cls) + created.append(cls["class"]) + log(f"collections created: {created or 'none'}") + + for collection, tenants in TENANTS.items(): + _, have = client.call("GET", f"/v1/schema/{collection}/tenants") + missing = [{"name": t, "activityStatus": "HOT"} for t in tenants if t not in {x["name"] for x in have}] + if missing: + client.call("POST", f"/v1/schema/{collection}/tenants", missing) + + _, aliases = client.call("GET", "/v1/aliases") + have_aliases = {a["alias"] for a in aliases.get("aliases") or []} + for alias, target in ALIASES.items(): + if alias not in have_aliases: + client.call("POST", "/v1/aliases", {"alias": alias, "class": target}) + + if "Article" in created: + batch(client, author_objects()) + batch(client, article_objects()) + if "Product" in created: + batch(client, product_objects()) + for collection in TENANTS: + if collection in created: + batch(client, note_objects(collection)) + if "EdgeValues" in created: + batch(client, edge_objects()) + + # Cold last: a COLD tenant cannot be written, and the objects must exist before it goes cold. + for collection, tenants in TENANTS.items(): + cold = [{"name": t, "activityStatus": s} for t, s in tenants.items() if s != "HOT"] + if cold: + client.call("PUT", f"/v1/schema/{collection}/tenants", cold) + log("seed done") + + +def ensure_reader(client, key_out): + status, _ = client.call("GET", "/v1/users/db/reader", ok=(200, 404)) + if status == 200 and os.path.exists(key_out): + log("user reader exists") + return + if status == 404: + _, created = client.call("POST", "/v1/users/db/reader", ok=(201,)) + else: + _, created = client.call("POST", "/v1/users/db/reader/rotate-key") + client.call("POST", "/v1/authz/users/reader/assign", {"roles": ["viewer"], "userType": "db"}) + with open(key_out, "w") as f: + f.write(created["apikey"]) + os.chmod(key_out, 0o644) + log(f"user reader (viewer) key written to {key_out}") + + +def count(client, collection, tenant=None): + q = f"/v1/objects?class={collection}&limit=100" + (f"&tenant={tenant}" if tenant else "") + total, after = 0, None + while True: + _, page = client.call("GET", q + (f"&after={after}" if after else "")) + objs = page.get("objects") or [] + total += len(objs) + if len(objs) < 100: + return total + after = objs[-1]["id"] + + +def verify(client): + diffs = [] + expect = {"Article": N_ARTICLE, "Author": N_AUTHOR, "Product": N_PRODUCT, "EdgeValues": len(EDGE_INTS), "Empty": 0} + for collection, n in expect.items(): + got = count(client, collection) + print(f"{collection}: {got} objects") + if got != n: + diffs.append(f"{collection}: expected {n}, got {got}") + for collection, tenants in TENANTS.items(): + _, have = client.call("GET", f"/v1/schema/{collection}/tenants") + status = {t["name"]: t["activityStatus"] for t in have} + print(f"{collection} tenants: {json.dumps(status, sort_keys=True)}") + for t, s in tenants.items(): + if status.get(t) != s: + diffs.append(f"{collection}/{t}: expected {s}, got {status.get(t)}") + if s == "HOT": + got = count(client, collection, t) + if got != N_NOTES: + diffs.append(f"{collection}/{t}: expected {N_NOTES} objects, got {got}") + _, aliases = client.call("GET", "/v1/aliases") + got_aliases = {a["alias"]: a["class"] for a in aliases.get("aliases") or []} + print(f"aliases: {json.dumps(got_aliases, sort_keys=True)}") + if got_aliases != ALIASES: + diffs.append(f"aliases: expected {ALIASES}, got {got_aliases}") + for d in diffs: + print(f"DIFF {d}") + return 1 if diffs else 0 + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--url", required=True) + ap.add_argument("--api-key-file") + ap.add_argument("--cacert") + ap.add_argument("--reader-key-out") + ap.add_argument("--verify", action="store_true") + args = ap.parse_args() + api_key = open(args.api_key_file).read().strip() if args.api_key_file else None + client = Client(args.url, api_key, args.cacert) + client.wait_ready() + if args.verify: + sys.exit(verify(client)) + seed(client) + if args.reader_key_out: + ensure_reader(client, args.reader_key_out) + + +if __name__ == "__main__": + main() diff --git a/docs/ADDING_A_PROVIDER.md b/docs/ADDING_A_PROVIDER.md index e227ebcc02..e07bf02ba5 100644 --- a/docs/ADDING_A_PROVIDER.md +++ b/docs/ADDING_A_PROVIDER.md @@ -242,10 +242,10 @@ The Memgraph provider is filed as `docs/BACKLOG.md` D141. ```typescript // Before: -export type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'opcua' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'bigquery' | 'mqtt' | 'firestore' | 'rabbitmq'; +export type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'weaviate' | 'opcua' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'bigquery' | 'mqtt' | 'firestore' | 'rabbitmq'; // After (example: adding CockroachDB): -export type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'opcua' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'bigquery' | 'mqtt' | 'firestore' | 'rabbitmq' | 'cockroachdb'; +export type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'weaviate' | 'opcua' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'bigquery' | 'mqtt' | 'firestore' | 'rabbitmq' | 'cockroachdb'; ``` A type-id may contain a digit: `db2` does. @@ -260,7 +260,7 @@ If your database uses a new editor mode (not `'sql'` or `'mongodb'`), add it: ```typescript export interface QueryTab { // ... - type: 'sql' | 'mongodb' | 'redis' | 'libredb' | 'promql' | 'kafka' | 'etcd' | 'cypher' | 'milvus' | 'qdrant' | 'opcua' | 'influxql' | 'oxia' | 's3' | 'kubectl' | 'mqtt' | 'firestore' | 'rabbitmq'; // Add your type here if needed + type: 'sql' | 'mongodb' | 'redis' | 'libredb' | 'promql' | 'kafka' | 'etcd' | 'cypher' | 'milvus' | 'qdrant' | 'weaviate' | 'opcua' | 'influxql' | 'oxia' | 's3' | 'kubectl' | 'mqtt' | 'firestore' | 'rabbitmq'; // Add your type here if needed } ``` @@ -982,7 +982,7 @@ For the authoritative, code-verified reference for each shipped provider (extend driver, pooling, capabilities, labels, `prepareQuery` behaviour, and limitations), see the prime docs — they are the single source of truth and are kept in sync with the code: -**[docs/providers/](./providers/README.md)** → postgres · mysql · oracle · db2 · mssql · sqlite · libsql · duckdb · redis · mongodb · couchbase · clickhouse · druid · elasticsearch · opensearch · trino · bigquery · snowflake · spark · cassandra · prometheus · influxdb · influxdb3 · kafka · etcd · neo4j · milvus · qdrant · opcua · oxia · databend · s3 · kubernetes · mqtt · firestore · rabbitmq · libredb +**[docs/providers/](./providers/README.md)** → postgres · mysql · oracle · db2 · mssql · sqlite · libsql · duckdb · redis · mongodb · couchbase · clickhouse · druid · elasticsearch · opensearch · trino · bigquery · snowflake · spark · cassandra · prometheus · influxdb · influxdb3 · kafka · etcd · neo4j · milvus · qdrant · weaviate · opcua · oxia · databend · s3 · kubernetes · mqtt · firestore · rabbitmq · libredb When implementing a new provider, the closest existing analogue is the best template: a pooled SQL provider (postgres/mysql), an embedded SQL provider (sqlite), a non-SQL provider (mongodb/redis), a @@ -1107,8 +1107,8 @@ The integration points, all of which need an entry. This is the list the Strateg published engine count silently undercount; it is listed here because the count in `README.md` and `docs/BRAND_MESSAGING.md` is derived from it and has to move in the same PR - [ ] `package.json` — the driver, **if** it needs one. A driver-free provider leaves it untouched, and - twenty shipped ids do: `couchbase`, `clickhouse`, `druid`, `elasticsearch`, `opensearch`, `trino`, - `libsql`, `sqlite`, `prometheus`, `qdrant`, `milvus`, `influxdb`, `influxdb3`, `oxia`, `databend`, `kubernetes`, `bigquery`, `firestore`, `rabbitmq` and `snowflake` + twenty-one shipped ids do: `couchbase`, `clickhouse`, `druid`, `elasticsearch`, `opensearch`, `trino`, + `libsql`, `sqlite`, `prometheus`, `qdrant`, `weaviate`, `milvus`, `influxdb`, `influxdb3`, `oxia`, `databend`, `kubernetes`, `bigquery`, `firestore`, `rabbitmq` and `snowflake` each add nothing here (`milvus` and `oxia` only extend the `//dependencies` note). `s3` needs no driver but adds the Parquet decoders `hyparquet` and `hyparquet-compressors`, with their `//dependencies` note. `spark` needs no driver but adds the Arrow IPC decoder `apache-arrow`, with its `//dependencies` note. diff --git a/docs/AGENT.md b/docs/AGENT.md index 41fc53929c..9da3d015f2 100644 --- a/docs/AGENT.md +++ b/docs/AGENT.md @@ -635,7 +635,7 @@ What a grounded plan run is given, and where each part comes from: which process happened to have read a catalog first. They are read from what the engine already holds — `pg_class.reltuples` and `pg_stats` on PostgreSQL, `sqlite_stat1` on SQLite — so no column is scanned and no value is read out of any row. A `statistics` reading is supplied by the engine overlays of those two and SQL Server (`buildMssqlEstimates`, from `sys.partitions`) and - nothing else, and #414 added no engine to them: on the other thirty-nine `readSchemaStatistics` answers + nothing else, and #414 added no engine to them: on the other forty `readSchemaStatistics` answers `DIALECT_HAS_NO_STATISTICS` — *"this engine does not hold statistics this run knows how to read"* — so **a known schema with no statistics is now the ORDINARY combination rather than a rare one**, and the two sentences the run is handed agree: the inventory is a record of what exists, and every @@ -756,9 +756,9 @@ Three consequences worth stating plainly, because each is easy to assume the oth 1. **A plan run costs statements now.** On PostgreSQL and SQLite grounding is catalog reads plus one statistics read (two on SQLite: the `sqlite_stat1` availability probe has to be its own statement, - because SQLite resolves table names at prepare time). On the other forty it is **one**, the + because SQLite resolves table names at prepare time). On the other forty-one it is **one**, the single `db.schema.read` call, except on SQL Server, which adds the one statistics read - its overlay's `statistics` supplies without a `catalogCapture`; the other thirty-nine hold no statistics this run + its overlay's `statistics` supplies without a `catalogCapture`; the other forty hold no statistics this run knows how to read. Since #789 an engine that declares object kinds costs **one more**, the object-surface reading above; an engine that declares none is charged nothing extra, because a read that cannot exist is never admitted. They come out of the same per-run statement budget every other read does, @@ -816,7 +816,7 @@ block tagged with the connection's canonical type-id, rationale after the block, not in the inventory. Since #414 the WORDING varies with the engine's `queryLanguage` and the TAG does not: on an engine whose language is not SQL (a `json` engine, since #1085 a `promql` one, a `cypher` one since Neo4j, and an `influxql` one) the run is asked for one statement or command in that engine's own language, a MongoDB aggregation or a PromQL expression rather than a SELECT, and told that this engine speaks no SQL, while the tag stays the canonical type-id in both arms. That is deliberate rather than an oversight: `isQueryFenceTag` -is a total record over `DatabaseType`, so all forty-two ids pass it, whereas a draft the model fenced as +is a total record over `DatabaseType`, so all forty-three ids pass it, whereas a draft the model fenced as ```` ```javascript ```` passes nothing and records no `plan-statement-drafted` event at all — the run would score as having drafted nothing while the user is looking at a statement. A run that cannot answer from the inventory takes the other legitimate ending: a line beginning `NO STATEMENT:` saying exactly what is @@ -1006,7 +1006,7 @@ Two consequences worth stating: composed path has and the provider path cannot: reads audited statement by statement rather than as one opaque call; foreign keys, which no provider can report on an engine that declares none; and SQLite's inventory, which is parsed out of the DDL text the engine stored and which its provider - does not expose in the same shape. Collapsing the other forty onto the composed one is the thing + does not expose in the same shape. Collapsing the other forty-one onto the composed one is the thing #414 exists because nobody can do: a catalog statement has to be written per dialect and verified against a live server, and until it is, refusing the dialect was the honest answer and reading the provider is a better one. diff --git a/docs/AGENT_DATA_FLOW.md b/docs/AGENT_DATA_FLOW.md index 6bddcfb10b..6626b7357f 100644 --- a/docs/AGENT_DATA_FLOW.md +++ b/docs/AGENT_DATA_FLOW.md @@ -55,12 +55,12 @@ if it only lists the good news. | Surface | What it sends | Fenced? | | --- | --- | --- | | `POST /api/agent/classify`, **before any run exists** | Your objective, and nothing else. One short completion that asks the model to name one of the five workflows. It fires when you press **Start** with the workflow left on **Automatic**, which is the default; naming a workflow yourself under **Advanced** skips it entirely. See [the classification, before any run](#the-classification-before-any-run) | No — it carries no database content to fence. Your objective is sent as the user message, and the server's instructions tell the model to treat that text as data to classify and never as instructions to it | -| Any **run**, in either mode, on **any** engine | Your objective, and a schema inventory (table, column, index identifiers and column types) with its relations graph (identifiers only). **Since #414 that inventory leaves on every engine**, where before it left on PostgreSQL and SQLite alone: those two are read with catalog statements the server composes, and the other forty by asking the connection's own provider to describe its schema. On **MongoDB and Couchbase** the provider works out a collection's fields from a **sample of your own documents**: no value from them is in the message, but the **existence** of a field there is derived from your data rather than read from a catalog, which is a weaker claim than a catalog reading's and is why that reading has its own operation id (`db.schema.read`) an operator can deny alone. When the reading cannot be taken (a refusal, a provider that cannot describe its own schema, a description that overran the time the run granted it), nothing of the schema leaves and a server sentence saying which of those happened goes in its place. See [the schema inventory](#3-the-schema-inventory--identifiers-and-types-fenced) | Everything derived from the database is wrapped in an untrusted-content fence before it reaches a prompt | +| Any **run**, in either mode, on **any** engine | Your objective, and a schema inventory (table, column, index identifiers and column types) with its relations graph (identifiers only). **Since #414 that inventory leaves on every engine**, where before it left on PostgreSQL and SQLite alone: those two are read with catalog statements the server composes, and the other forty-one by asking the connection's own provider to describe its schema. On **MongoDB and Couchbase** the provider works out a collection's fields from a **sample of your own documents**: no value from them is in the message, but the **existence** of a field there is derived from your data rather than read from a catalog, which is a weaker claim than a catalog reading's and is why that reading has its own operation id (`db.schema.read`) an operator can deny alone. When the reading cannot be taken (a refusal, a provider that cannot describe its own schema, a description that overran the time the run granted it), nothing of the schema leaves and a server sentence saying which of those happened goes in its place. See [the schema inventory](#3-the-schema-inventory--identifiers-and-types-fenced) | Everything derived from the database is wrapped in an untrusted-content fence before it reaches a prompt | | An **agent run** | The above, plus the rows of each read the model performed, up to 200 per read; engine error text; server-written refusals; server-minted ids | Same fence | | Any **run that continues a conversation**, in either mode, on any engine | **In addition to everything above**: the earlier steps' objectives — *your own earlier questions*, capped at 200 characters each — and the most recent step's report, which is a model's claims about your data. No row of any result, and no earlier step's report but the newest. Sent only when the rail attaches a previous run's id, which it does for a follow-up on the same connection; a run that starts its own conversation sends no such message. Bounded to 4000 characters by default and switchable off with `LIBREDB_AGENT_THREAD_CONTEXT=false`. See [the conversation](#2a-the-conversation-when-a-run-continues-one--fenced) | Same fence, identified as `operation agent/thread`: it is prose a user and a model wrote, and none of it is the server's voice | | An **agent run opened as Operate** | Your objective; a **schema inventory reduced to its own names and index names** (no column names, no column types, no relations graph), read whichever of the two ways that engine is read and named with whichever noun that engine's provider declares — tables, collections, datasources, key patterns; in Plan mode the engine's **row-count estimates** for those same tables where the engine holds any — PostgreSQL and SQLite — and nothing per column; and the rows of each curated reading — which, for the `sessions` and `slow-queries` kinds, include **other database users' in-flight statement text and their database usernames**. See [the operations workflow](#5a-the-operations-workflow-what-a-curated-reading-sends) | Same fence: the inventory and every reading's rows are database content and are fenced | | `POST /api/ai/explain` | Your statement, the EXPLAIN plan, the schema context the browser holds, the engine type | No | -| `POST /api/ai/query-safety` | Your statement, a filtered schema context, the engine type. Never an etcd, Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement: the dialog posts nothing for an engine whose destructive vocabulary declares `safetyAnalysis: false`, which those seven do, because an etcd `put` carries its value in the statement (#1089), a Milvus or Qdrant request carries vectors, filters and values, an InfluxQL statement carries tag values and filters, an Oxia command names keys whose paths name Pulsar tenants and namespaces, an S3 command names buckets and object keys, and a kubectl statement names namespaces and objects | No | +| `POST /api/ai/query-safety` | Your statement, a filtered schema context, the engine type. Never an etcd, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement: the dialog posts nothing for an engine whose destructive vocabulary declares `safetyAnalysis: false`, which those eight do, because an etcd `put` carries its value in the statement (#1089), a Milvus, Qdrant or Weaviate request carries vectors, filters and values, an InfluxQL statement carries tag values and filters, an Oxia command names keys whose paths name Pulsar tenants and namespaces, an S3 command names buckets and object keys, and a kubectl statement names namespaces and objects | No | | `POST /api/ai/describe-schema` | A schema context. From the **Data Profiler** that context includes a per-column `min=` and `max=`, which are **real column values**, except on a column the data masking configuration masks for you, which is sent masked | No | | Everything else in the **running server** | Every outbound connection goes to a host **you** configured — your databases, your OIDC issuer when `NEXT_PUBLIC_AUTH_PROVIDER=oidc` (`src/lib/oidc.ts`), and the model provider above. The one host `src/` names itself is OpenAI's default base URL, reached only if you set `LLM_PROVIDER=openai` (`src/lib/llm/utils/config.ts:23`) | — | | The **`npx` launcher**, before the server exists | The release tarball and `SHA256SUMS` from a hard-coded `github.com` URL (`bin/lib/launcher-utils.mjs:87`, from `bin/studio.js:218-219`). Once per version, cached in `~/.libredb-studio/`; no other install path uses it | — | @@ -219,7 +219,7 @@ One field of your connection record *is*: its **engine type**, the canonical typ spends it on the fence tag the deliverable must carry, and since the Operate-engine fix a prose plan spends it twice: on the rule that binds the readings it may name to the engine it is planning against, and on the fence tag for a reading that engine happens to express as a statement. It is -a server-side enum with forty-two members, so what it discloses is which of forty-two engines this +a server-side enum with forty-three members, so what it discloses is which of forty-three engines this connection is — never its host, its database name or its credentials, none of which reach a prompt at all (see [What never leaves](#what-never-leaves)). @@ -289,18 +289,18 @@ a refusal — nothing of the schema leaves and a server-written note says so in **Two readings produce it, and which one runs is the dialect's decision** (#414). On PostgreSQL and SQLite the server composes a catalog statement per kind and executes it read-only. On the other -forty it invokes `db.schema.read`, which walks the connection's own OBJECT SURFACE, the same +forty-one it invokes `db.schema.read`, which walks the connection's own OBJECT SURFACE, the same `listContainers`, `countObjects`, `listObjects` and `describeObjects` the sidebar walks when it lists your objects, and composes no statement at all. -**Forty counts type-ids the factory can build, not engines a user would name**: `SHIPPED` holds -forty-two, two of them supply a `catalogCapture`, and the remainder is what this second reading covers. +**Forty-one counts type-ids the factory can build, not engines a user would name**: `SHIPPED` holds +forty-three, two of them supply a `catalogCapture`, and the remainder is what this second reading covers. Every other count said about grounding in these docs counts the same thing. libSQL is one of the -forty and not one of the two: it speaks SQLite's dialect, but the read-only catalog path +forty-one and not one of the two: it speaks SQLite's dialect, but the read-only catalog path a `catalogCapture` takes needs a database-native read-only profile, and `PRAGMA query_only` is refused by a libSQL server (see [`providers/libsql.md`](./providers/libsql.md)). Two things it does NOT count. The wire-compatible engines of [`docs/providers/README.md`](./providers/README.md) are not extra members — TiDB is grounded because it -arrives as `mysql`, and it is that type-id that is counted. And two of the forty, the embedded +arrives as `mysql`, and it is that type-id that is counted. And two of the forty-one, the embedded `libredb` and `duckdb`, reach this path through a handle they do not open: the file takes an exclusive lock, so the grounding acquisition borrows the connection's own open provider rather than opening a second one that the lock would refuse (`findOpenSingleWriterProvider`, `src/lib/db/factory.ts`; see @@ -369,7 +369,7 @@ The inventory's foreign keys, rendered as a relation list and fenced beside the It carries table names, column names, and at the deepest detail level a table's primary-key and leading-index column names (`keyColumns`, `er-diagram.ts:145-157`). **Never a row value.** -On the thirty-four engines that declare no foreign keys at all (MongoDB, Redis, LibreDB, Druid, ClickHouse, Couchbase, Firestore, Trino, Snowflake, Apache Spark, Cassandra, Elasticsearch, OpenSearch, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), BigQuery, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, SNMP and Sparkplug B) this block carries no relations and says why: the engine has no such constraint to +On every engine that declares no foreign keys at all (MongoDB, Redis, LibreDB, Druid, ClickHouse, Couchbase, Firestore, Trino, Snowflake, Apache Spark, Cassandra, Elasticsearch, OpenSearch, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), BigQuery, Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, SNMP and Sparkplug B) this block carries no relations and says why: the engine has no such constraint to declare, so there is nothing here a reading could have missed (#414, driven from `ProviderCapabilities.declaresForeignKeys` rather than from the connection's type). It is one server sentence and no database content, which makes it the one form of this block that discloses nothing. @@ -567,7 +567,7 @@ The frozen execution policies are the ceiling on one run's egress, one row per w | Bound | Value | What it caps | | --- | --- | --- | | `maxResultRows` / `maxResultBytes` | 200 rows / 256 KiB | The most one read can return — and therefore the most one tool result can send | -| `maxStatementsPerRun` | 18-45, by workflow | Reads per run, folded across its drives (#999), grounding reads and repairs included: the composed catalog reads and, since #414, the one `db.schema.read` call that replaces them on the other forty. The figures did not move for it: that path is the cheapest of the three, so nothing had to be bought (`docs/AGENT.md`, the budget arithmetic) | +| `maxStatementsPerRun` | 18-45, by workflow | Reads per run, folded across its drives (#999), grounding reads and repairs included: the composed catalog reads and, since #414, the one `db.schema.read` call that replaces them on the other forty-one. The figures did not move for it: that path is the cheapest of the three, so nothing had to be bought (`docs/AGENT.md`, the budget arithmetic) | | `AGENT_CONTEXT_PACK_MAX_CHARS` | 6000 | The fenced schema inventory | | `MAX_ER_CHARS` | 2000 | The fenced relations block | | `AGENT_MAX_OBJECTIVE_LENGTH` | 4000 | Your objective | @@ -663,7 +663,7 @@ fences what it sends: | Feature | Route | What the browser sends | Call site | | --- | --- | --- | --- | | Visual EXPLAIN's AI explanation | `POST /api/ai/explain` | `query`, `explainPlan`, `schemaContext`, `databaseType` | `src/components/VisualExplain.tsx:486-497` | -| Query safety dialog | `POST /api/ai/query-safety` | `query`, a filtered `schemaContext`, `databaseType`; nothing at all for an etcd, Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement (`vocabularySendsToModel`, `src/lib/db/destructive-commands.ts`) | `src/components/QuerySafetyDialog.tsx:221-231` | +| Query safety dialog | `POST /api/ai/query-safety` | `query`, a filtered `schemaContext`, `databaseType`; nothing at all for an etcd, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement (`vocabularySendsToModel`, `src/lib/db/destructive-commands.ts`) | `src/components/QuerySafetyDialog.tsx:221-231` | | Database documentation | `POST /api/ai/describe-schema` | A schema string built from table names, row counts and column definitions | `src/components/DatabaseDocs.tsx:61-68` | | Data Profiler's AI summary | `POST /api/ai/describe-schema` | Per column: null percent, distinct count, **`min=` and `max=`**, masked where the grid would mask the column | `src/components/DataProfiler.tsx:141-176` | diff --git a/docs/AGENT_GUIDE.md b/docs/AGENT_GUIDE.md index 0d3d5eabb4..3258ec5eac 100644 --- a/docs/AGENT_GUIDE.md +++ b/docs/AGENT_GUIDE.md @@ -214,8 +214,8 @@ having **no statistics**, never as empty. On SQLite the statistics exist only af **Every engine, read one of two ways.** On **PostgreSQL and SQLite** the server composes catalog statements and reads them through the same audited, read-only path an Agent run uses. On every other -connection, which is the other forty (MySQL, Oracle, Db2 LUW, SQL Server, libSQL, DuckDB, MongoDB, Redis, -ClickHouse, Couchbase, Firestore, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, Modbus, NETCONF, SNMP, Sparkplug B and the bundled LibreDB +connection, which is the other forty-one (MySQL, Oracle, Db2 LUW, SQL Server, libSQL, DuckDB, MongoDB, Redis, +ClickHouse, Couchbase, Firestore, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, Modbus, NETCONF, SNMP, Sparkplug B and the bundled LibreDB store), it asks that connection's own provider to describe its schema, which is the reading the sidebar already performs when it lists your tables, and composes no statement at all. Grounding is no longer decided by the engine, and that changed in #414; what decides it now is whether the @@ -228,7 +228,7 @@ workflow including **Operate**. now two different sentences, and the difference is the whole of what changed: - **Grounding: every engine.** What a Plan run is TOLD about your database. It needs no read-only - statement path, because the provider reading sends no statement, so it reaches all forty-two engines. + statement path, because the provider reading sends no statement, so it reaches all forty-three engines. - **Agent mode: PostgreSQL, SQLite, DuckDB, SQL Server, MySQL, Kubernetes and MongoDB.** What a run may DO by itself. Its tools execute statements and need a read-only path the provider implements, which only those providers do. So a schema-workflow Agent run on any other engine is refused when you press **Start**, before a run is opened and before anything is read, with the reason the rail's amber card shows (`workflowAvailability` in `src/app/api/agent/runs/route.ts`, #512); a Plan run there is still grounded. @@ -240,7 +240,7 @@ inspection found and not proof that nothing else exists, and the plan is told so engines it works out a collection's fields from a **sample of your own documents**: no value from them is kept, but the existence of a field there is derived from your data rather than read from a catalog. The **estimated statistics** below are PostgreSQL's, SQLite's and SQL Server's alone; on the other -thirty-nine the plan is told that this engine holds none it knows how to read, which means it has an +forty the plan is told that this engine holds none it knows how to read, which means it has an inventory and no sizes — the ordinary case now rather than a rare one. On an engine that speaks no SQL, a Plan run is asked for one statement or command **in that engine's @@ -977,7 +977,7 @@ Stated plainly, because a surface that hides its edges is the one that surprises (`src/lib/db/providers/embedded/libredb.ts`), so the bundled **SQLite sample** is the seeded connection to try a run against (`src/lib/seed/sqlite-sample.ts`). **Plan** mode still opens on every connection — the model is toolless there, so no profile has to be acquired for it — and since - #414 its **grounding** no longer takes this path at all on the other forty: it asks the provider to + #414 its **grounding** no longer takes this path at all on the other forty-one: it asks the provider to describe its schema, which needs no read-only statement profile, so a Plan run on Oracle or Redis is ordinarily grounded while an Agent run on the same connection still cannot read anything. Where the reading does fail — a provider that cannot describe itself, a description that overran its diff --git a/docs/API_DOCS.md b/docs/API_DOCS.md index 02e5804693..cff6fc314f 100644 --- a/docs/API_DOCS.md +++ b/docs/API_DOCS.md @@ -27,12 +27,12 @@ ## Overview -LibreDB Studio provides a RESTful API for database management operations. The API supports PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. +LibreDB Studio provides a RESTful API for database management operations. The API supports PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. ### Key Features - **JWT Authentication** - Secure token-based authentication stored in HTTP-only cookies -- **Multi-Database Support** - Forty-one engines: PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, NETCONF, Sparkplug B +- **Multi-Database Support** - Forty-two engines: PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP, NETCONF, Sparkplug B - **AI-Powered Insights** - EXPLAIN explanations, query-safety analysis and schema docs, streamed - **Real-time Health Monitoring** - Database metrics and performance insights @@ -517,7 +517,7 @@ Under that cap, a result of exactly `limit` rows has `wasLimited: false` and `ha A bound the provider reported sets `wasLimited` and never `hasMore`, because no `offset` can advance a bound the server did not write. A statement the server returned **untouched** — one carrying its own `LIMIT n`, or one whose end the limiter declined to cut into — runs identically at every `offset`, because the requested offset is discarded along with the rewrite. `hasMore` is `false` for those however many rows come back, and re-requesting with a higher `offset` would return the same rows again. Where `hasMore` is `true`, re-request with `offset` advanced by the number of rows you received. See [`docs/editor/query-optimization.md`](editor/query-optimization.md). -Not every engine can serve a positive `offset`. Cassandra and Elasticsearch answer one with HTTP 400 rather than silently returning page one; MongoDB, Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage and Firestore ignore it. `POST /api/db/provider-meta` reports each one's `capabilities.supportsResultPagination`, which is the same flag the app reads before offering its Load More control. +Not every engine can serve a positive `offset`. Cassandra and Elasticsearch answer one with HTTP 400 rather than silently returning page one; MongoDB, Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Firestore ignore it. `POST /api/db/provider-meta` reports each one's `capabilities.supportsResultPagination`, which is the same flag the app reads before offering its Load More control. **The database a run reads (optional):** ```json @@ -589,7 +589,7 @@ The bound is read after the request body is parsed, because the type that select | `sql` is over the declared bound | `413` | `{ "error": "The statement is bytes in UTF-8, over the -byte limit for this connection type. Shorten it to run it." }`, which never repeats the text | `POST /api/db/multi-query` refuses every connection whose type declares such a bound with `400 { "error": "This connection type runs one statement per request: send it to POST /api/db/query, because this route would split its text into several requests." }`, before it splits anything. -Milvus and Qdrant each declare a bound of 1,048,576 bytes and InfluxDB (InfluxQL), Oxia, S3-compatible object storage, Kubernetes and Firestore one of 65,536 bytes each, and no other shipped engine declares one, so neither answer changes anything for a connection of another type. +Milvus, Qdrant and Weaviate each declare a bound of 1,048,576 bytes and InfluxDB (InfluxQL), Oxia, S3-compatible object storage, Kubernetes and Firestore one of 65,536 bytes each, and no other shipped engine declares one, so neither answer changes anything for a connection of another type. **Bound parameters (optional):** ```json @@ -2432,7 +2432,7 @@ interface DatabaseConnection { registerMap?: string; // Modbus only: the register map, as the JSON document the provider parses - a list of points, each naming a unit, a table, a zero-based PDU address and a type. Bounded at 65536 bytes, checked before the parse; public-classified, because Modbus TCP defines no authentication and the document carries nothing to leak } -type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'bigquery' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'mqtt' | 'firestore' | 'rabbitmq' | 'opcua' | 'mtconnect' | 'modbus' | 'netconf' | 'snmp' | 'sparkplug'; +type DatabaseType = 'postgres' | 'mysql' | 'sqlite' | 'libsql' | 'duckdb' | 'mongodb' | 'redis' | 'oracle' | 'db2' | 'mssql' | 'libredb' | 'couchbase' | 'clickhouse' | 'druid' | 'elasticsearch' | 'opensearch' | 'trino' | 'bigquery' | 'snowflake' | 'spark' | 'cassandra' | 'prometheus' | 'kafka' | 'etcd' | 'neo4j' | 'milvus' | 'qdrant' | 'weaviate' | 'influxdb' | 'influxdb3' | 'oxia' | 'databend' | 's3' | 'kubernetes' | 'mqtt' | 'firestore' | 'rabbitmq' | 'opcua' | 'mtconnect' | 'modbus' | 'netconf' | 'snmp' | 'sparkplug'; type ConnectionEnvironment = 'production' | 'staging' | 'development' | 'local' | 'other'; ``` diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 8b661d20f1..236a25f70d 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -5,7 +5,7 @@ This document outlines the architectural patterns, tech stack, and system design ## System Overview LibreDB Studio is a hybrid, cloud-native database management tool that provides an IDE-like experience in the browser. -It supports **42 database backends** via a Strategy Pattern abstraction: PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Elasticsearch, OpenSearch, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, NETCONF, SNMP, Sparkplug B, LibreDB. +It supports **43 database backends** via a Strategy Pattern abstraction: PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Elasticsearch, OpenSearch, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, NETCONF, SNMP, Sparkplug B, LibreDB. The count is the `SHIPPED` record in [`src/lib/db/compatibility.ts`](../src/lib/db/compatibility.ts), which is exhaustive over `DatabaseType`; `elasticsearch` and `opensearch` are two ids served by one provider module, and `influxdb` and `influxdb3` are two ids served by one provider directory with a class each. It runs in two modes: as a **standalone Next.js app** and as an **embedded npm package** (`@libredb/studio`) consumed by libredb-platform. See [§4.6](#46-workspace-abstraction-npm-package-embedding). @@ -80,6 +80,7 @@ graph TD Graph --> Neo4j[(Neo4j)] Vector --> Milvus[(Milvus)] Vector --> Qdrant[(Qdrant)] + Vector --> Weaviate[(Weaviate)] ObjectStore --> S3[(S3-compatible object storage)] Platform --> Kubernetes[(Kubernetes)] DBFactory --> Embedded[Embedded Providers] @@ -147,6 +148,7 @@ classDiagram BaseDatabaseProvider <|-- GraphBaseProvider BaseDatabaseProvider <|-- MilvusProvider BaseDatabaseProvider <|-- QdrantProvider + BaseDatabaseProvider <|-- WeaviateProvider BaseDatabaseProvider <|-- S3Provider BaseDatabaseProvider <|-- KubernetesProvider BaseDatabaseProvider <|-- RabbitMQProvider @@ -419,7 +421,7 @@ src/ │ │ │ # InfluxDB 3's /api/v3/query_sql; the InfluxQL lexer, read policy, quoter and generators are browser-safe) │ │ ├── stream/ # kafka/ (read-client seam + JSON read requests over the Kafka protocol via @platformatic/kafka) │ │ ├── graph/ # neo4j/ (an engine profile, catalog, statement gate and monitoring on the graph layer below) - │ │ ├── vector/ # milvus/ (a gRPC client of its own via the shared gRPC transport, Milvus's REST v2 requests as the console, run over gRPC); qdrant/ (a REST client of its own over the shared node transport, the closed console, the payload sample) + │ │ ├── vector/ # milvus/ (a gRPC client of its own via the shared gRPC transport, Milvus's REST v2 requests as the console, run over gRPC); qdrant/ (a REST client of its own over the shared node transport, the closed console, the payload sample); weaviate/ (a REST client of its own over the shared node transport, the closed console run over REST or GraphQL as the server's version decides) │ │ ├── objectstore/ # s3/ (a REST client of its own over the shared byte transport, signed by its own SigV4 module over node:crypto; an AWS CLI read-command console; object metadata and capped previews, Parquet through hyparquet) │ │ ├── platform/ # kubernetes/ (a REST client of its own over the shared node transport behind a read-only request allowlist; a kubectl read-command console; namespaces and kinds in the tree, a YAML view of every object, Secret values redacted) │ │ └── embedded/ # libredb (built-in embedded provider for the sample connection) @@ -446,7 +448,7 @@ src/ │ # verifier (jose, HS256 pinned) and the in-process jti replay cache ├── llm/ # LLM provider module ├── editor/ # Monaco completions (SQL + MongoDB), the tab-type/language ladder, the - │ # editor registry (dialect-editors.ts), the LibreDB, Redis, etcd, Oxia, S3 and kubectl command languages, Cypher, InfluxQL, and the Milvus and Qdrant console languages + │ # editor registry (dialect-editors.ts), the LibreDB, Redis, etcd, Oxia, S3 and kubectl command languages, Cypher, InfluxQL, and the Milvus, Qdrant and Weaviate console languages ├── schema-diff/ # Diff engine + migration SQL generator ├── export/ # The writers behind every "save this to disk": RFC 4180 CSV, │ # the SQL INSERT/DDL forms, and the one blob-download path diff --git a/docs/BRAND_MESSAGING.md b/docs/BRAND_MESSAGING.md index 2a044d68f2..7fca87151a 100644 --- a/docs/BRAND_MESSAGING.md +++ b/docs/BRAND_MESSAGING.md @@ -4,7 +4,7 @@ The messaging architecture marketing teams work from: what LibreDB claims, who i ## Positioning statement -> For engineering teams whose databases live in the cloud, LibreDB Studio is the database editor that deploys next to the data instead of onto your laptop: one browser tab for PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, SQLite, libSQL, DuckDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes, with SSO and audit built in, under MIT with nothing held back. +> For engineering teams whose databases live in the cloud, LibreDB Studio is the database editor that deploys next to the data instead of onto your laptop: one browser tab for PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, SQLite, libSQL, DuckDB, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes, with SSO and audit built in, under MIT with nothing held back. One sentence, one reference point. Everything else in this brief either supports it or is cut. @@ -59,7 +59,7 @@ One umbrella claim, three entry doors into it, three assurance layers underneath **The three doors** are three ways into that one claim. A campaign picks a door. It does not argue all three at once, because a piece that opens on three arguments has opened on none. 1. You created the database. The editor is already beside it. -2. One tab, forty-one engines. +2. One tab, forty-two engines. 3. Nothing sits behind an Enterprise wall. **Door 3 is deliberately third, and stays third.** Leading with it would define LibreDB as another company's opponent rather than as a position of its own, and it would put our credibility at the mercy of their pricing page. Third, the same fact reads as reassurance rather than accusation. @@ -80,12 +80,12 @@ Each door carries five parts. A promise whose proof does not resolve to a row in This is the sharpest of the three. It is the one claim no competitor can currently make. -### Door 2: One tab, forty-one engines. +### Door 2: One tab, forty-two engines. - **Audience:** teams running more than one kind of database, and the engineers who join them. - **Pain:** four databases, four clients, four sets of credentials, and a connection-string hunt for anyone new. -- **Promise:** forty-one engines in one interface, with the same exploration everywhere, and ER diagrams, schema diff and monitoring wherever the engine has something to show. (Not "across all of them": a search cluster declares no foreign keys, so its ER diagram has no edges, and item 4 below forbids the sentence that hides that.) -- **Proof:** forty-one providers, each with its own reference document under `docs/providers/`. +- **Promise:** forty-two engines in one interface, with the same exploration everywhere, and ER diagrams, schema diff and monitoring wherever the engine has something to show. (Not "across all of them": a search cluster declares no foreign keys, so its ER diagram has no edges, and item 4 below forbids the sentence that hides that.) +- **Proof:** forty-two providers, each with its own reference document under `docs/providers/`. - **Difference:** CloudBeaver Community bundles 18 driver modules and every one of them is SQL. MongoDB and Redis are not among them. The claim here is the span, never the count. See the honesty limits. @@ -124,7 +124,7 @@ Facts drift. Provider counts, channel counts and competitor editions all change, | Claim | Evidence | Source | Verified | | :--- | :--- | :--- | :--- | -| Forty-one database engines | One reference document per engine: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. One more, `libredb.md`, is the embedded provider and is not an external engine. The count is derived, not written: `SHIPPED` in `src/lib/db/compatibility.ts` is an exhaustive record over `DatabaseType`, so the compiler refuses a missing id: read the count from there, minus `libredb` | `docs/providers/`, `src/lib/db/compatibility.ts` | 2026-10-08 | +| Forty-two database engines | One reference document per engine: PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. One more, `libredb.md`, is the embedded provider and is not an external engine. The count is derived, not written: `SHIPPED` in `src/lib/db/compatibility.ts` is an exhaustive record over `DatabaseType`, so the compiler refuses a missing id: read the count from there, minus `libredb` | `docs/providers/`, `src/lib/db/compatibility.ts` | 2026-10-08 | | Published as an embeddable npm package | `"name": "@libredb/studio"`, version 0.16.1 | `package.json` | 2026-09-19 | | MIT licensed | "MIT License / Copyright (c) 2025 SEKOYA GRUP BİLİŞİM VE TEKNOLOJİ LİMİTED ŞİRKETİ" | `LICENSE` | 2026-08-07 | | 42 distribution channels, 34 live | "42 channels · 34 live · 7 pending · 1 deprecated" | `docs/CHANNELS.md` | 2026-10-01 | @@ -198,7 +198,7 @@ Documented so the message exists when it is wanted. Not part of the current camp An agency that knows what it may not embellish is forced to fill the remaining space with real material. That is the purpose of this section. 1. **Display masking is a presentation feature, not a security control.** It was built for screen sharing, demos and screenshots. It runs in the browser, and the API returns full values to an authorized user. State this as scope, not as a shortcoming. No message may imply that display masking is data protection, access control, or compliance. -2. **Never claim leadership on the number of SQL engines.** CloudBeaver Community bundles 18 driver modules covering 15 distinct engines, against forty-one here. The claim is the span across SQL, NoSQL, analytics and search in one interface, never the count. The count moves, so read it from `SHIPPED` in `src/lib/db/compatibility.ts` (an exhaustive record over `DatabaseType`, minus the embedded `libredb`) rather than from the last campaign; but a bigger number never becomes the claim. +2. **Never claim leadership on the number of SQL engines.** CloudBeaver Community bundles 18 driver modules covering 15 distinct engines, against forty-two here. The claim is the span across SQL, NoSQL, analytics and search in one interface, never the count. The count moves, so read it from `SHIPPED` in `src/lib/db/compatibility.ts` (an exhaustive record over `DatabaseType`, minus the embedded `libredb`) rather than from the last campaign; but a bigger number never becomes the claim. 3. **There is no LDAP.** Single sign-on is delivered through OIDC. Teams that require LDAP are told before they install, not after. 4. **Elasticsearch and OpenSearch are a read-only query surface, not a managed one.** Both ship as of [#424](https://github.com/libredb/libredb-studio/issues/424), so both belong in an engine list and in a polyglot story. What may not be implied is parity with PostgreSQL or MySQL. The query language is each product's own SQL endpoint — never ES|QL, which exists on one of the two and is deliberately unused, and never the native JSON DSL. Neither product's SQL grammar has `INSERT`, `UPDATE` or `CREATE TABLE`, so what ships is a query editor plus an index and mapped-field browser plus cluster health and per-index document counts and store sizes. There is no EXPLAIN, no maintenance operation, no slow-query panel and no session list; an ER diagram over a search cluster draws boxes and no edges, because the engine has no foreign keys to declare; aliases and data streams are not in the tree; and on Elasticsearch there is no `OFFSET`, so results after the first page cannot be requested at all. Say "query and browse", never "manage" — and never fold these two into a sentence that says a feature works "across all engines". What the story promises, the product has to hold. 5. **Trino is a query engine, and the story must not sell it as a database.** It ships as of @@ -224,7 +224,7 @@ An engineer speaking to an engineer. - Claim plus proof. Never adjective plus adjective. - No emoji. No exclamation marks. - Competitors are never disparaged by name. A comparison is a table with sources, and the reader draws the conclusion. -- Prefer the concrete number to the impressive word. "Forty-one engines" beats "extensive database support". +- Prefer the concrete number to the impressive word. "Forty-two engines" beats "extensive database support". - Say the limitation out loud. Stating scope precisely is what makes the rest of the claims credible to this audience. - Product terms stay in English in every language. LibreDB Studio, not a translated variant. @@ -244,7 +244,7 @@ Direction, not copy. This brief contains no finished copy for any surface. It sa | Surface | Leads with | Why | Current state | | :--- | :--- | :--- | :--- | -| GitHub About | Door 2, in one line | The first thing a repository visitor reads, and the only place a full sentence has to work with no layout around it | Defect: it names four engines against forty-one shipped. Fix before any campaign starts | +| GitHub About | Door 2, in one line | The first thing a repository visitor reads, and the only place a full sentence has to work with no layout around it | Defect: it names four engines against forty-two shipped. Fix before any campaign starts | | README opening | Door 1, then Door 3 | Visitors arriving from search need the claim before the feature list | States a category rather than a claim. Rewrite | | Website hero | Door 1 | The site as a whole can carry the story; the hero carries the claim and a single proof | States a category rather than a claim. Rewrite | | Website story section | The brand story, both scenes | Nothing on the site currently says why LibreDB exists | Missing entirely. Add | diff --git a/docs/DATABASE_PROVIDERS.md b/docs/DATABASE_PROVIDERS.md index 2be4cffa60..b494b00899 100644 --- a/docs/DATABASE_PROVIDERS.md +++ b/docs/DATABASE_PROVIDERS.md @@ -153,7 +153,8 @@ src/lib/db/ │ │ └── labels.ts # labels, and the plan-mode statement language │ ├── vector/ # Vector Providers │ │ ├── milvus/ # Milvus Strategy (Milvus REST v2 requests run over its own gRPC client) -│ │ └── qdrant/ # Qdrant Strategy (read-only REST over the shared node transport) +│ │ ├── qdrant/ # Qdrant Strategy (read-only REST over the shared node transport) +│ │ └── weaviate/ # Weaviate Strategy (read-only REST, GraphQL below 1.39.7, over the shared node transport) │ ├── objectstore/ # Object Storage Providers │ │ └── s3/ # S3 Strategy (read-only REST over the shared byte transport, Studio's own SigV4, AWS CLI read commands) │ ├── platform/ # Platform Providers @@ -199,6 +200,7 @@ BaseDatabaseProvider (abstract) │ └── Neo4jProvider ──────────────────────┤ Graph (read-only Cypher over Bolt) ├── MilvusProvider ─────────────────────────┤ Vector (Milvus REST v2 requests over gRPC) ├── QdrantProvider ─────────────────────────┤ Vector (Qdrant REST requests, read-only) +├── WeaviateProvider ───────────────────────┤ Vector (Weaviate REST requests, read-only) ├── S3Provider ─────────────────────────────┤ Object storage (AWS CLI read commands over the S3 REST API, read-only) ├── KubernetesProvider ─────────────────────┤ Platform (kubectl read commands over HTTP, read-only) └── LibreDBProvider ────────────────────────┘ Embedded (key-value) @@ -263,7 +265,7 @@ QueryEditor /api/db/query ## Supported Databases -Forty-two type-ids are supported by forty provider modules: two pairs share one, `elasticsearch` and `opensearch` in `providers/sql/search/`, and `influxdb` and `influxdb3` in `providers/timeseries/influxdb/`. +Forty-three type-ids are supported by forty-one provider modules: two pairs share one, `elasticsearch` and `opensearch` in `providers/sql/search/`, and `influxdb` and `influxdb3` in `providers/timeseries/influxdb/`. The count is derived from the exhaustive `SHIPPED` record in [`src/lib/db/compatibility.ts`](../src/lib/db/compatibility.ts) rather than written here twice - and the TABLE under it has to be checked by hand, which is the lesson a review left here: the numeral was @@ -304,6 +306,7 @@ monitoring, limitations, …) see the prime docs in **[`docs/providers/`](./prov | Neo4j | `neo4j` | Graph (Cypher over Bolt, read-only) | [providers/neo4j.md](./providers/neo4j.md) | | Milvus | `milvus` | Vector (Milvus REST v2 requests over gRPC) | [providers/milvus.md](./providers/milvus.md) | | Qdrant | `qdrant` | Vector (Qdrant REST requests, read-only) | [providers/qdrant.md](./providers/qdrant.md) | +| Weaviate | `weaviate` | Vector (Weaviate REST requests, read-only) | [providers/weaviate.md](./providers/weaviate.md) | | Oxia | `oxia` | Key-Value (oxia client read commands over gRPC, read-only) | [providers/oxia.md](./providers/oxia.md) | | S3-compatible object storage | `s3` | Object storage (AWS CLI read commands over the S3 REST API, read-only) | [providers/s3.md](./providers/s3.md) | | Kubernetes | `kubernetes` | Platform (kubectl read commands over the API server's REST API, read-only) | [providers/kubernetes.md](./providers/kubernetes.md) | @@ -446,6 +449,7 @@ examples live in their prime docs: - **Neo4j** (one read-only Cypher statement): [providers/neo4j.md](./providers/neo4j.md). - **Milvus** (one Milvus REST v2 request): [providers/milvus.md](./providers/milvus.md). - **Qdrant** (one Qdrant REST request): [providers/qdrant.md](./providers/qdrant.md). +- **Weaviate** (one Weaviate REST request): [providers/weaviate.md](./providers/weaviate.md). - **LibreDB** (one command: `get`, `put`, `delete`, `prefix` or `range`): [providers/libredb.md](./providers/libredb.md). - **Oxia** (one oxia client read command): [providers/oxia.md](./providers/oxia.md). - **S3-compatible object storage** (one AWS CLI read command, or Studio's own `preview`): [providers/s3.md](./providers/s3.md). @@ -529,7 +533,7 @@ maintenance operations, and known limitations — is documented per provider und [`docs/providers/`](./providers/README.md). Start there for anything specific to PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, Redis, MongoDB, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), -Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, or LibreDB. +Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, or LibreDB. Not every provider has every feature, and the docs record the absences rather than glossing over them. Druid is the sharpest case: its SQL has no `UPDATE`, no `DELETE` and no `CREATE TABLE`, no diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 3a8c52d334..30de91e682 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -26,7 +26,7 @@ ### 3. Pro Data Grid (Excel-Style) * **High Performance:** Virtualized rendering using TanStack Virtual for smooth scrolling through millions of rows. -* **Inline Editing:** Double-click any cell, or press Enter or F2 on the active cell, to edit data directly; apply pending cell changes as one `UPDATE` per edited row or discard them. The table written to is the one the *statement that fetched the rows* names, not the tab's title. A query whose rows have no single table - a join, a comma-separated `FROM`, a subquery in `FROM` or in the select list, a CTE, a set operation - is refused with a reason rather than guessed at. The key the `WHERE` is built on is a guess off the result's own fields, so before anything is written the apply asks the engine whether that column addresses one row per value and refuses the whole apply when it does not: on a result carrying a foreign key rather than the table's own key, one cell edit used to rewrite every row sharing that value. Offered only where the provider declares `supportsInlineRowEdit`. ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Cassandra, MongoDB, Firestore, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes and LibreDB show no editing control at all because they have no single-table row update - on Cassandra because CQL requires the WHOLE primary key restricted by equality while the editor names one column it guessed from the result fields, so a clustered table answers "Some partition key parts are missing" (measured); on Trino because it declares no primary key for any table in any catalog, so the generated `WHERE` could not identify one row; on Databend for the same reason: it declares no key, so an edit has no row identity; on Apache Spark because its keys are informational and a write depends on the table format; on the two search engines `UPDATE` is absent from the SQL grammar itself, measured on both; Couchbase shows none because the document key reaches the grid as a projection alias the generated `WHERE` cannot address. +* **Inline Editing:** Double-click any cell, or press Enter or F2 on the active cell, to edit data directly; apply pending cell changes as one `UPDATE` per edited row or discard them. The table written to is the one the *statement that fetched the rows* names, not the tab's title. A query whose rows have no single table - a join, a comma-separated `FROM`, a subquery in `FROM` or in the select list, a CTE, a set operation - is refused with a reason rather than guessed at. The key the `WHERE` is built on is a guess off the result's own fields, so before anything is written the apply asks the engine whether that column addresses one row per value and refuses the whole apply when it does not: on a result carrying a foreign key rather than the table's own key, one cell edit used to rewrite every row sharing that value. Offered only where the provider declares `supportsInlineRowEdit`. ClickHouse, Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Cassandra, MongoDB, Firestore, Redis, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes and LibreDB show no editing control at all because they have no single-table row update - on Cassandra because CQL requires the WHOLE primary key restricted by equality while the editor names one column it guessed from the result fields, so a clustered table answers "Some partition key parts are missing" (measured); on Trino because it declares no primary key for any table in any catalog, so the generated `WHERE` could not identify one row; on Databend for the same reason: it declares no key, so an edit has no row identity; on Apache Spark because its keys are informational and a write depends on the table format; on the two search engines `UPDATE` is absent from the SQL grammar itself, measured on both; Couchbase shows none because the document key reaches the grid as a projection alias the generated `WHERE` cannot address. * **Data-Type Formatting:** Specialized rendering for Numbers, Booleans, and Nulls. * **Vector Cells:** A column the result declares as a vector (`QueryResult.vectorColumns`) shows its first 8 elements and its size, such as `768 dims`, bits for a binary vector, entries for a sparse vector and rows for a multivector, instead of one line of thousands of digits. The row detail shows a header line such as `dense float32, 768 dims` over the whole value, wrapped. @@ -136,6 +136,11 @@ Collections are browsable with their vectors, payload indexes and a sampled view of payload keys, and vectors reach the grid as vector cells with their dimension and full-value copy. Every inference input but local BM25 is refused, in every release. See [`providers/qdrant.md`](providers/qdrant.md). + * **Weaviate:** Read-only over Weaviate's REST API through a client of Studio's own, and over GraphQL for the searches of a server older than 1.39.7, tested on Weaviate 1.40.2, 1.38.22 and 1.37.4. + Weaviate's own REST requests in the editor, seventeen read routes: objects, BM25, hybrid, near-vector and near-object searches and aggregate counts, written in the REST search shape on every server. + Collections are browsable with their properties and vectors, tenants and aliases appear in a collection's Source, and vectors reach the grid as vector cells with their dimension and full-value copy. + Every search that would embed text on the server is refused before anything is sent, and a cold tenant is never woken, in every release. + See [`providers/weaviate.md`](providers/weaviate.md). * **Object Storage:** * **S3-compatible object storage:** Read-only over the S3 REST API with **no SDK and no driver**: Studio's own SigV4 code signs each request with the access key pair typed into the connection, never with the server's environment, shared credential files or instance role, and an empty pair sends unsigned requests. AWS CLI read commands in the editor, such as `aws s3api list-buckets`, `aws s3 ls`, `aws s3api head-object` and `aws s3api list-object-versions`, plus Studio's own `preview`; buckets in the tree, or the one bucket the connection names; folders and objects in the Keys panel, one folder level at a time with a Load more per level. @@ -173,7 +178,7 @@ Two components are described below and a claim true of one can be false of the o * **Contextual Actions (schema tab):** Quick access menus for each table including "Select Top 50", "Generate Query", "Generate Count Query", and "Copy Name". Action labels adapt per provider (e.g. "Scan Keys" for Redis, "Find Documents" for MongoDB). * **Generate Count Query (both explorers):** Opens an editable count statement in a new tab without running it, so a filter can be added before Run. SQL engines get a qualified, dialect-quoted `SELECT COUNT(*)` (`COUNT_BIG(*)` on SQL Server), and MongoDB gets its `count` document. - Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes have no count grammar here, and a derived key-prefix grouping has nothing to count, so they are not offered it. + Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes have no count grammar here, and a derived key-prefix grouping has nothing to count, so they are not offered it. * **DBA Quick Tools:** (Admin Only) Instant access to "Analyze Table" and "Vacuum Table" directly from the table context menu, on the providers whose rows are real objects. A key-value provider such as Redis, whose rows are derived key-prefix groupings, offers neither -- there is no table for the maintenance page to act on. * **Visual Clarity:** Modern glassmorphic design with Framer Motion animations for smooth transitions. * **Database Stats:** Integrated table counts and connection health monitoring directly in the sidebar. diff --git a/docs/MCP.md b/docs/MCP.md index 25fd79f564..ba91cf5697 100644 --- a/docs/MCP.md +++ b/docs/MCP.md @@ -17,6 +17,7 @@ It is off by default. A column an engine only inferred from sampled data, rather than read from a declaration, is never listed, so a table may hold fields the answer does not show; `columns_omitted` counts only the columns beyond the 50-column cap, and agent grounding and the AI panels never receive such a column either. On Milvus it lists the collection's declared fields, with the dynamic field as one `$meta` column and never a key inside it. On Qdrant it lists payload-index fields and vectors only, and says that other payload keys may exist: the keys Studio samples from points never reach an MCP client. + On Weaviate it lists each collection's declared properties and vectors; a collection's tenants and aliases are never returned, and a call wakes no tenant. On InfluxDB (InfluxQL) it lists measurements with their tag and field keys, and on InfluxDB 3 (SQL) tables with their columns; the `_internal` database and the `system.*` tables of a 3.x server are never returned. On Databend it lists tables, views, materialized views and dynamic tables; on a Databend Cloud connection with a Warehouse set, a call resumes a suspended warehouse, which bills while it runs, as any statement does. On Apache Spark it lists the tables and views of one namespace, read with SHOW and DESCRIBE statements that start no Spark job on Studio's own session; a namespace is named in Spark's spelling, its parts joined by dots. diff --git a/docs/SCHEMA_DIFF.md b/docs/SCHEMA_DIFF.md index f835df9091..ac4d7b0923 100644 --- a/docs/SCHEMA_DIFF.md +++ b/docs/SCHEMA_DIFF.md @@ -29,7 +29,7 @@ PostgreSQL 18.6 replay with `relation "_pkey" already exists`. Every othe table is still created. An existing table's added indexes are all emitted, because the generator writes no key for one. -MongoDB, Redis, LibreDB, Couchbase, Druid, Elasticsearch, OpenSearch, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes receive an explanatory +MongoDB, Redis, LibreDB, Couchbase, Druid, Elasticsearch, OpenSearch, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, MQTT, RabbitMQ, OPC UA, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes receive an explanatory comment instead of relational table DDL. Trino, ClickHouse and Databend refuse foreign-key clauses; Trino and Databend refuse primary keys too, so an added table's key is declined in a comment after its `CREATE TABLE`. Trino has no index grammar, Databend's indexes are inverted, ngram, vector and spatial search indexes the diff does not record, and the diff does not retain enough diff --git a/docs/SECURITY.md b/docs/SECURITY.md index b2bea59471..52e7450c82 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -73,6 +73,7 @@ Two consequences worth stating before the table: | 3.22 | On an Apache Spark connection, every request runs its statements in a Spark session of its own: a call with no request scope runs on a statement session released when its statement ends, and a request scope's session is released when the scope is ended, by Studio's query routes or, in the embedded package, by a host that passes a scope; a provider disconnect releases every session, and until then, or when a release cannot reach the server, a session can live until Spark's idle timeout; the provider's own metadata session runs no user statement; every session starts with variable substitution and Arrow compression off before its first statement; the token is never sent without TLS to a host that is neither loopback nor tunnelled; and every answer is bounded: before decoding, by a 16 MiB message cap with 4 MiB result chunks, a 32 MiB stream bound, and an Arrow stream check of framing, schema depth and size, buffer lengths and types that refuses compressed batches; while decoding, by a 100,000-row and 16 MiB statement budget in which each value's cost is known before the value is built and a Variant's text is bounded as it is written | Implemented | [`src/lib/db/providers/sql/spark/session.ts`](../src/lib/db/providers/sql/spark/session.ts), [`src/lib/db/providers/sql/spark/connection-options.ts`](../src/lib/db/providers/sql/spark/connection-options.ts), [`src/lib/db/providers/sql/spark/grpc-client.ts`](../src/lib/db/providers/sql/spark/grpc-client.ts), [`src/lib/db/providers/sql/spark/requests.ts`](../src/lib/db/providers/sql/spark/requests.ts), [`src/lib/db/providers/sql/spark/execute.ts`](../src/lib/db/providers/sql/spark/execute.ts), [`src/lib/db/providers/sql/spark/result-stream.ts`](../src/lib/db/providers/sql/spark/result-stream.ts), [`src/lib/db/providers/sql/spark/ipc-guard.ts`](../src/lib/db/providers/sql/spark/ipc-guard.ts), [`src/lib/db/providers/sql/spark/schema.ts`](../src/lib/db/providers/sql/spark/schema.ts), [`src/lib/db/providers/sql/spark/values.ts`](../src/lib/db/providers/sql/spark/values.ts), [`src/lib/db/providers/sql/spark/variant.ts`](../src/lib/db/providers/sql/spark/variant.ts) | [`tests/unit/db/spark/session.test.ts`](../tests/unit/db/spark/session.test.ts), [`tests/unit/db/spark/connection-options.test.ts`](../tests/unit/db/spark/connection-options.test.ts), [`tests/unit/db/spark/grpc-client.test.ts`](../tests/unit/db/spark/grpc-client.test.ts), [`tests/unit/db/spark/requests.test.ts`](../tests/unit/db/spark/requests.test.ts), [`tests/unit/db/spark/result-stream.test.ts`](../tests/unit/db/spark/result-stream.test.ts), [`tests/unit/db/spark/budgets.test.ts`](../tests/unit/db/spark/budgets.test.ts), [`tests/unit/db/spark/ipc-guard.test.ts`](../tests/unit/db/spark/ipc-guard.test.ts), [`tests/unit/db/spark/schema.test.ts`](../tests/unit/db/spark/schema.test.ts), [`tests/unit/db/spark/values.test.ts`](../tests/unit/db/spark/values.test.ts), [`tests/unit/db/spark/variant.test.ts`](../tests/unit/db/spark/variant.test.ts) | | 3.23 | Under governance, Studio opens a sealed connection credential only with a private key of the keyring file `GOVERNANCE_PRIVATE_KEYS_FILE` names, under additional authenticated data that binds the envelope to its connection id, level, engine, key id and canonical definition, so an envelope moved to another connection, level, engine, host, port or TLS mode fails with `AUTH_FAILED`; the modules that open envelopes have no way to seal one; the server refuses to start when the keyring file cannot be read, is not JSON of version 1, lists no key or more than 16, lists a key that is not the unpadded base64url of 32 bytes, or lists two keys with one key id; an opened credential is cached under the SHA-256 of its envelope together with the additional authenticated data it opened under, so a cache hit never skips the binding check; and no refusal or log line carries key material or a credential, only key ids, positions and codes | Implemented | [`src/lib/governance/keyring.ts`](../src/lib/governance/keyring.ts), [`src/lib/governance/secrets.ts`](../src/lib/governance/secrets.ts), [`src/lib/governance/lsb1.ts`](../src/lib/governance/lsb1.ts), [`src/lib/governance/hpke.ts`](../src/lib/governance/hpke.ts), [`src/lib/governance/preflight.ts`](../src/lib/governance/preflight.ts) | [`tests/security/governance-sealed-secrets.test.ts`](../tests/security/governance-sealed-secrets.test.ts), [`tests/unit/lib/governance/keyring.test.ts`](../tests/unit/lib/governance/keyring.test.ts), [`tests/unit/lib/governance/secrets.test.ts`](../tests/unit/lib/governance/secrets.test.ts), [`tests/unit/lib/governance/lsb1.test.ts`](../tests/unit/lib/governance/lsb1.test.ts), [`tests/unit/lib/governance/hpke.test.ts`](../tests/unit/lib/governance/hpke.test.ts), [`tests/unit/lib/governance/preflight.test.ts`](../tests/unit/lib/governance/preflight.test.ts) | | 3.24 | Under governance a query event row keeps of the statement only what the runtime setting `queryLog.statementCapture` allows, `none` unless the control plane sets another mode: under `none` no statement, fingerprint or error text; under `redacted` the statement with every literal, number and comment replaced by `?`, a password written as a bare word included, and the SHA-256 of that text; under `full` the statement and the error text with the value after `PASSWORD` or `IDENTIFIED BY` and the userinfo of every URI masked; a refused request whose connection did not resolve keeps no statement or error text in any mode; and `buildQueryEvent()`, the only maker of rows, copies only the fields its input names, so a bind parameter value, a result row or a connection credential has no column to land in, whatever object a caller hands it | Implemented | [`src/lib/query-events/build.ts`](../src/lib/query-events/build.ts), [`src/lib/query-events/redact.ts`](../src/lib/query-events/redact.ts), [`src/lib/query-events/types.ts`](../src/lib/query-events/types.ts) | [`tests/security/governance-query-events.test.ts`](../tests/security/governance-query-events.test.ts), [`tests/unit/lib/query-events/build.test.ts`](../tests/unit/lib/query-events/build.test.ts), [`tests/unit/lib/query-events/redact.test.ts`](../tests/unit/lib/query-events/redact.test.ts) | +| 3.25 | On a Weaviate connection, a request runs only when it is one of the seventeen read routes of the closed console, every body and filter key at every level is one its route declares, it makes the server send no text to a model (no near-text, generative or rerank search, and hybrid only at `alpha` 0), it names no tenant that is not HOT, and it fits the console's bounds; a refused request is never sent and never written to history | Implemented | [`src/lib/db/providers/vector/weaviate/routes.ts`](../src/lib/db/providers/vector/weaviate/routes.ts), [`src/lib/db/providers/vector/weaviate/request.ts`](../src/lib/db/providers/vector/weaviate/request.ts), [`src/lib/db/providers/vector/weaviate/guard.ts`](../src/lib/db/providers/vector/weaviate/guard.ts), [`src/lib/db/providers/vector/weaviate/execute.ts`](../src/lib/db/providers/vector/weaviate/execute.ts), [`src/lib/db/destructive-commands.ts`](../src/lib/db/destructive-commands.ts) | [`tests/unit/db/weaviate/guard.test.ts`](../tests/unit/db/weaviate/guard.test.ts), [`tests/unit/db/weaviate/request-phase0.test.ts`](../tests/unit/db/weaviate/request-phase0.test.ts), [`tests/unit/db/weaviate/request-search.test.ts`](../tests/unit/db/weaviate/request-search.test.ts), [`tests/unit/db/weaviate/request-filter.test.ts`](../tests/unit/db/weaviate/request-filter.test.ts), [`tests/unit/db/weaviate/request-phase1.test.ts`](../tests/unit/db/weaviate/request-phase1.test.ts), [`tests/unit/db/weaviate/execute.test.ts`](../tests/unit/db/weaviate/execute.test.ts), [`tests/integration/db/weaviate-provider.test.ts`](../tests/integration/db/weaviate-provider.test.ts) | ## Notes on individual rows @@ -574,8 +575,9 @@ A connection is recorded by its bare seed id and only once it resolved; the conn **3.8.** Partial for one precondition: the mode is a boundary only on a managed seed, which `resolveConnection` re-resolves from the operator's file whatever a caller sends, and only where etcd authenticates the client with a secret that seed keeps on the server, a password or a client certificate. On an etcd that authenticates nobody, and on a connection of the user's own, it is a safety rail, because a `user` can reach the same host and port with a connection of their own and can turn off Read-only on one (Known limits). `readOnly` is checked by one function, `assertReadOnlyHonoured`, before any provider is built and before any SSH tunnel is dialled, so on an engine whose provider does not keep the mode `readOnly: true` is refused rather than ignored, and the seed loader refuses it there too, and on a seed that is not managed. -etcd's, Neo4j's, Milvus's and Qdrant's providers keep the mode today, and so do both InfluxDB providers, Oxia's, S3's, Kubernetes's, MQTT's and OPC UA's (`READ_ONLY_ENFORCED` in `src/lib/db/compatibility.ts`): etcd's names where the mode was set in every refusal ([`docs/providers/etcd.md`](./providers/etcd.md) section 3.4), and Neo4j's refuses every write whatever the mode says (row 3.10). +etcd's, Neo4j's, Milvus's, Qdrant's and Weaviate's providers keep the mode today, and so do both InfluxDB providers, Oxia's, S3's, Kubernetes's, MQTT's and OPC UA's (`READ_ONLY_ENFORCED` in `src/lib/db/compatibility.ts`): etcd's names where the mode was set in every refusal ([`docs/providers/etcd.md`](./providers/etcd.md) section 3.4), and Neo4j's refuses every write whatever the mode says (row 3.10). Qdrant's runs reads only, so the mode changes nothing a request can do today, and on a Qdrant server without a key it binds only the seeded connection ([`docs/providers/qdrant.md`](./providers/qdrant.md) section 3.4). +Weaviate's runs reads only too, and a read-only seed with no key is refused, because a Weaviate server with anonymous access on, its default, grants a request with no key every write ([`docs/providers/weaviate.md`](./providers/weaviate.md) section 3.5). Milvus's names where the mode was set, as etcd's does, in refusing Load and Release, and on Milvus the mode binds only when the server has authorization enabled, which is not its default ([`docs/providers/milvus.md`](./providers/milvus.md) section 3.4). The InfluxDB providers keep it whatever the flag says: each runs only statements its read policy allows (rows 3.12 and 3.13) and has no object edit and no maintenance operation, so a read-only connection refuses every non-read before any request. Oxia's names the read-only mode while it holds and says v1 reads only otherwise ([`docs/providers/oxia.md`](./providers/oxia.md) section 3.5). @@ -658,6 +660,10 @@ The keyring is the residual: a Studio process holds every governed credential, a It stores no error text and replaces every literal, so a secret written as a string or a number is gone, while a secret written as a bare name is kept like any other name, the password of `IDENTIFIED BY` excepted. `full` is the wider residual: it keeps every other secret written into a statement, such as a Redis `AUTH` argument or a token passed to a function, and in the error text it masks a password only where the words around it read as they would in a statement, so a driver that quotes a statement its own way can echo one ([`docs/GOVERNANCE.md`](GOVERNANCE.md#query-events)). +**3.25.** A Weaviate collection may declare a vectorizer, generative or reranker module, and some searches make the server send the user's text to that module's provider: near-text, generative search, `rerank`, and hybrid with an `alpha` other than 0, whose server default is 0.7. +Studio refuses each before anything is sent, so the console cannot trigger that path; a listener behind a `text2vec-openai` base URL received nothing from any route the console runs on 1.37.4 and 1.40.2 ([`docs/providers/weaviate.md`](./providers/weaviate.md) section 3.2). +On a collection with `autoTenantActivation` on, any data read of a COLD tenant sets it HOT, for a `viewer` too, so Studio reads the tenant's own record first and refuses unless it is HOT; on the 1.37 line a woken tenant's `/shards` read also stops answering until the server restarts (section 3.4). + ## Known limits These are real, current, and not oversights. Each is a decision with a reason. @@ -667,7 +673,7 @@ These are real, current, and not oversights. Each is a decision with a reason. server; a seed meant for one database names it and is then pinned to it. - **The HTTP destination guard is opt-in and address-based.** `DB_HTTP_BLOCK_PRIVATE_HOSTS` is off by default so local databases remain usable. When enabled, it covers ClickHouse, Druid, Elasticsearch, - OpenSearch, Trino, libSQL, Couchbase, Prometheus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), S3-compatible object storage and Kubernetes HTTP requests, rejecting loopback, private, + OpenSearch, Trino, libSQL, Couchbase, Prometheus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), S3-compatible object storage and Kubernetes HTTP requests, rejecting loopback, private, link-local, unique-local and selected special-use IP ranges at the literal-host and DNS/socket boundaries. A public service address such as Azure's `168.63.129.16` remains reachable because the policy checks address ranges, not ownership or service purpose. Non-HTTP drivers, including Kafka, @@ -715,7 +721,7 @@ These are real, current, and not oversights. Each is a decision with a reason. Such a statement is refused in the browser before the confirmation dialog, on every path the editor takes: Run, Proceed, Explain, Load More and playground mode, and the embedded workspace's four run paths. It reaches no route and no host callback, and it is not written to query history. `POST /api/db/query` answers 413 for a text over the bound and `POST /api/db/multi-query` refuses such a type with 400, so a caller outside the editor meets the same bound. - The Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18 and 3.20); no other shipped engine declares either. + The Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18, 3.20 and 3.25); no other shipped engine declares either. A statement the editor accepts is written to history whole, as on every engine, even when the server then refuses it, except for the values of the credential flags its dialect declares as `historyMask` on its `QUERY_DIALECTS` record, which are replaced by `***` before the entry is stored, in comments too, and in the error text the entry stores, since an error can repeat the statement ([`src/lib/history-mask.ts`](../src/lib/history-mask.ts)); the `kubectl` dialect declares `--token`, `--password`, `--client-key`, `--client-certificate`, `--from-literal` and `--docker-password`, though its console refuses every line that carries them. It does not mask a value written before the flag that names it, as an error can quote one, a value on a later line than its flag that no continuation or open quote carries there, or the value of a flag spelled in a way the module does not read, such as with a dash for a hyphen inside its name. That mask reaches the standalone app's query history only: a tab keeps what the user typed, a saved query keeps what the user saved, and the embedded workspace writes no history of its own; a statement run before the connection's metadata has loaded is stored under every dialect's declared flags at once and masked as a command line is, so a SQL statement holding a declared flag and a value may then be stored without that value, without the quotes around it or cut to the end of its line, a statement that may no longer parse, never a credential. @@ -757,6 +763,18 @@ These are real, current, and not oversights. Each is a decision with a reason. A vendor address pasted into the connection-string box instead of the Host box still selects ClickHouse. A hostile or impersonated endpoint holds the key it receives and can return it in an encoding Studio does not list, so Studio withholds only the forms it sends. [`docs/providers/qdrant.md`](./providers/qdrant.md) section 13 lists the same limits. +- **Weaviate is reached over a REST client of Studio's own.** + A Weaviate API key or OIDC token over no TLS is refused unless the host is a loopback address or `localhost`, or an SSH tunnel carries the connection. + TLS mode `require` sends the key to an unverified peer. + The server's own egress, its vectorizer, generative and reranker modules and its backups included, is outside the HTTP egress guard; Studio refuses every search that would make the server send text to a model (row 3.25). + Vectors and property values reach query history and saved queries, as every statement's text does. + A Weaviate server with anonymous access on, its default, grants a request with no key every write, so it has no boundary at all. + Prefer the key of a database user that holds only the built-in `viewer` role; the server refuses its writes. + A `viewer` user can read the server's roles and database users outside Studio. + An OIDC token is pasted, never refreshed, and is held until the connection closes. + A seed's in-flight slots, queue and running requests are shared by every user of the seed, so any user who knows a run's id can cancel it. + A hostile or impersonated endpoint holds the key it receives and can return it in an encoding Studio does not list, so Studio withholds only the forms it sends. + [`docs/providers/weaviate.md`](./providers/weaviate.md) section 13 lists the same limits. - **S3-compatible object storage is reached over a REST client of Studio's own.** A request over no TLS, signed or not, is refused unless the host is a loopback address or `localhost`, an SSH tunnel carries the connection, or the connection consents. Anyone who captures a signed request can send it again while the server's clock window lasts: 14 minutes of skew were accepted and 20 refused on MinIO, Silo and RustFS, while Garage accepted a signature up to 24 hours old and any date in the future. diff --git a/docs/SEED_CONNECTIONS.md b/docs/SEED_CONNECTIONS.md index c72b67dc68..9e46f7ed30 100644 --- a/docs/SEED_CONNECTIONS.md +++ b/docs/SEED_CONNECTIONS.md @@ -88,7 +88,7 @@ An mssql seed that carried only a `connectionString`, for example, loaded and op The types whose provider reads it are postgres, mysql, sqlite, libsql, oracle, db2, clickhouse, mongodb and couchbase. sqlite reads it as the database file path, with a `file:` prefix removed, although its provider's capability flag says it does not ([docs/providers/sqlite.md](./providers/sqlite.md)). mssql does not read it, although its provider's capability flag says it does: the flag covers the connection form, which splits a pasted URI into fields, and the provider builds from those fields only ([docs/providers/mssql.md](./providers/mssql.md#44-connection-string-nuance)). -The 33 that refuse it are bigquery, snowflake, spark, duckdb, mssql, druid, trino, cassandra, elasticsearch, opensearch, redis, prometheus, kafka, etcd, neo4j, milvus, qdrant, influxdb, influxdb3, oxia, databend, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect, modbus, netconf, snmp, sparkplug and libredb. +The 34 that refuse it are bigquery, snowflake, spark, duckdb, mssql, druid, trino, cassandra, elasticsearch, opensearch, redis, prometheus, kafka, etcd, neo4j, milvus, qdrant, weaviate, influxdb, influxdb3, oxia, databend, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect, modbus, netconf, snmp, sparkplug and libredb. To fix a refused file, move the value into `host`, `port`, `user`, `password` and `database`, and remove `connectionString`. ### A Firestore connection @@ -190,7 +190,7 @@ defaults: # Optional — merges managed/environment/ssl only connections: - id: "analytics-pg" # Required, unique, lowercase slug [a-z0-9-] name: "Analytics DB" # Required, display name in UI - type: postgres # Required: postgres|mysql|sqlite|libsql|duckdb|mongodb|redis|oracle|db2|mssql|libredb|couchbase|firestore|clickhouse|druid|elasticsearch|opensearch|trino|bigquery|snowflake|spark|cassandra|prometheus|kafka|mqtt|rabbitmq|opcua|etcd|neo4j|milvus|qdrant|influxdb|influxdb3|oxia|databend|s3|kubernetes + type: postgres # Required: postgres|mysql|sqlite|libsql|duckdb|mongodb|redis|oracle|db2|mssql|libredb|couchbase|firestore|clickhouse|druid|elasticsearch|opensearch|trino|bigquery|snowflake|spark|cassandra|prometheus|kafka|mqtt|rabbitmq|opcua|etcd|neo4j|milvus|qdrant|weaviate|influxdb|influxdb3|oxia|databend|s3|kubernetes host: "${PG_HOST}" port: 5432 database: analytics @@ -373,7 +373,7 @@ connections: | `connections` | Yes | — | Array of connection definitions (min 1) | | `connections[].id` | Yes | — | Unique slug: `[a-z0-9-]+`, max 64 chars | | `connections[].name` | Yes | — | Display name, max 128 chars | -| `connections[].type` | Yes | - | Database type: `postgres`, `mysql`, `sqlite`, `libsql`, `duckdb`, `mongodb`, `redis`, `oracle`, `db2`, `mssql`, `libredb`, `couchbase`, `firestore`, `clickhouse`, `druid`, `elasticsearch`, `opensearch`, `trino`, `bigquery`, `snowflake`, `spark`, `cassandra`, `prometheus`, `kafka`, `mqtt`, `rabbitmq`, `opcua`, `etcd`, `neo4j`, `milvus`, `qdrant`, `influxdb`, `influxdb3`, `oxia`, `databend`, `s3`, `kubernetes` | +| `connections[].type` | Yes | - | Database type: `postgres`, `mysql`, `sqlite`, `libsql`, `duckdb`, `mongodb`, `redis`, `oracle`, `db2`, `mssql`, `libredb`, `couchbase`, `firestore`, `clickhouse`, `druid`, `elasticsearch`, `opensearch`, `trino`, `bigquery`, `snowflake`, `spark`, `cassandra`, `prometheus`, `kafka`, `mqtt`, `rabbitmq`, `opcua`, `etcd`, `neo4j`, `milvus`, `qdrant`, `weaviate`, `influxdb`, `influxdb3`, `oxia`, `databend`, `s3`, `kubernetes` | | `connections[].host` | No | — | Hostname or IP | | `connections[].port` | No | — | Port number (1-65535) | | `connections[].database` | No | — | Database name (Couchbase: the bucket. Druid has one catalog and ignores it. Trino: the **catalog**. S3: the optional pinned bucket. PostgreSQL: empty reaches the whole server, every database the role can CONNECT to) | @@ -389,7 +389,7 @@ connections: | `connections[].connectionString` | No | - | Full connection string (use `${ENV_VAR}`). Read only by postgres, mysql, sqlite (as the database file path), libsql, oracle, db2, clickhouse, mongodb and couchbase; every other type, mssql included, refuses it when the file loads, naming the connection and the type ([The connection string refusal](#the-connection-string-refusal)) | | `connections[].roles` | Yes | — | Access control: `["*"]`, `["admin"]`, `["user"]`, `["admin", "user"]`, or custom roles starting with `OIDC_ROLE_PREFIX` when OIDC is enabled | | `connections[].managed` | No | from defaults | `true` = admin-controlled: not editable in the UI, its secrets stay on the server; `false` = an editable copy for the user | -| `connections[].readOnly` | No | absent | `true` refuses every write, value edit and maintenance operation on the connection, on an engine whose provider enforces it (etcd, Neo4j, Milvus, Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage and Kubernetes); every other engine refuses `readOnly: true` when the file loads, naming the type and the field. Refused with `managed` false, on the connection or through `defaults.managed`, because an editable copy carries the credentials into the browser. A literal boolean: a `${ENV}` reference is refused | +| `connections[].readOnly` | No | absent | `true` refuses every write, value edit and maintenance operation on the connection, on an engine whose provider enforces it (etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Oxia, S3-compatible object storage and Kubernetes); every other engine refuses `readOnly: true` when the file loads, naming the type and the field. Refused with `managed` false, on the connection or through `defaults.managed`, because an editable copy carries the credentials into the browser. A literal boolean: a `${ENV}` reference is refused | | `connections[].environment` | No | from defaults | Environment badge | | `connections[].group` | No | — | Group label | | `connections[].color` | No | — | Hex color for badge (e.g., `#10B981`) | @@ -429,7 +429,7 @@ With no seed file, or with no entry that opts in for the token's role, `list_con ### A read-only cluster for everyone `readOnly: true` makes a connection refuse every write, value edit and maintenance operation before any request, on an engine whose provider keeps the mode. -etcd's, Neo4j's, Milvus's, Qdrant's, both InfluxDB types', Oxia's, S3's and Kubernetes's do today ([providers/etcd.md](providers/etcd.md), section 3.4, the Neo4j recipe below, [providers/milvus.md](providers/milvus.md) and [providers/qdrant.md](providers/qdrant.md), section 3.4 of each, the InfluxDB recipes above, [providers/oxia.md](providers/oxia.md), section 3.5, [providers/s3.md](providers/s3.md), section 3.5, and [providers/kubernetes.md](providers/kubernetes.md), section 9), and on every other engine the file is refused at load, with a sentence naming the type and the field. +etcd's, Neo4j's, Milvus's, Qdrant's, Weaviate's, both InfluxDB types', Oxia's, S3's and Kubernetes's do today ([providers/etcd.md](providers/etcd.md), section 3.4, the Neo4j recipe below, [providers/milvus.md](providers/milvus.md) and [providers/qdrant.md](providers/qdrant.md), section 3.4 of each, [providers/weaviate.md](providers/weaviate.md), section 3.5, the InfluxDB recipes above, [providers/oxia.md](providers/oxia.md), section 3.5, [providers/s3.md](providers/s3.md), section 3.5, and [providers/kubernetes.md](providers/kubernetes.md), section 9), and on every other engine the file is refused at load, with a sentence naming the type and the field. The recipe is two seeds of one cluster: one every role reaches, read-only, and one for the people who may write. ```yaml @@ -473,6 +473,8 @@ Milvus declares both: its documented default `root` pair, and no password ([prov A Milvus seed's read-only mode is a boundary only when the server has authorization enabled, which is not Milvus's default. Qdrant declares the second: a read-only Qdrant seed with no key is refused, because a Qdrant server without a key accepts any key or none ([providers/qdrant.md](providers/qdrant.md), section 4.2). Give a read-only Qdrant seed the server's read-only key or a read-scoped JWT, through a reference such as `password: "${QDRANT_READ_ONLY_KEY}"`. +Weaviate declares the same: a read-only Weaviate seed with no key is refused, because a server with anonymous access on, its default, grants a request with no key every write ([providers/weaviate.md](providers/weaviate.md), section 3.5). +Give it the key of a database user with the built-in `viewer` role, through a reference such as `password: "${WEAVIATE_VIEWER_KEY}"`. Both InfluxDB types declare the second too: an InfluxDB 1.x server with authentication off, its default, and an InfluxDB 3 server started with `--without-auth` accept any credential or none, so a read-only InfluxDB seed with no password or token is refused. Give a read-only `influxdb` seed a 1.x user granted READ, or a 2.x read token for the bucket, through a reference such as `password: "${INFLUX_READER_PASSWORD}"`, and a read-only `influxdb3` seed a token through a reference such as `password: "${INFLUXDB3_TOKEN}"`. On a type that does, the seed loader refuses a `readOnly: true` connection whose credential matches, in two stages: load refuses what the file shows; resolution refuses the rest. diff --git a/docs/editor/query-optimization.md b/docs/editor/query-optimization.md index 5527da0fb2..85e688bfdd 100644 --- a/docs/editor/query-optimization.md +++ b/docs/editor/query-optimization.md @@ -206,7 +206,7 @@ A rule that could **not** be established is not guessed from a neighbouring dial at the compatibility default below, and it is listed here rather than left implicit. The default is per **fact**, not per dialect: a dialect whose `#` rule is known can still be undecided about its brackets. -**MongoDB, Firestore, Redis, Prometheus, InfluxDB (InfluxQL), Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B are the twenty-one types whose query text is not SQL at all**: `readsSqlText: false`, declared in each engine's grammar module in the registry in `src/lib/db/sql-grammar/`, holds exactly those twenty-one, which is what `readsSqlText()` reports on. +**MongoDB, Firestore, Redis, Prometheus, InfluxDB (InfluxQL), Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B are the twenty-two types whose query text is not SQL at all**: `readsSqlText: false`, declared in each engine's grammar module in the registry in `src/lib/db/sql-grammar/`, holds exactly those twenty-two, which is what `readsSqlText()` reports on. Their providers never reach these readers on the query path, and the confirmation gate, which reads whatever is in the editor, asks `readsSqlText()` before applying any span-based rule to their text, so a JSON document, a Redis command, a PromQL expression, an InfluxQL statement, a Kafka read request, an etcdctl command, a Cypher statement, a Milvus request, a Qdrant request, an `oxia client` read command, an AWS CLI read command, a kubectl statement, a NETCONF read request, a Sparkplug read request or an SNMP walk is not judged by a SQL reader that cannot parse it. The gate's SQL keyword test still reads MongoDB and Redis text first, as a backstop, which on Redis also asks about a read whose arguments include `update` and then `set` (`docs/BACKLOG.md` U43). @@ -764,7 +764,7 @@ ordering notice beside it cannot disagree: | Condition | Where it comes from | Why | |-----------|--------------------|-----| -| `supportsResultPagination === true` | the connection's `ProviderCapabilities` | Sixteen providers cannot serve page two. Cassandra and Elasticsearch throw on a positive offset; MongoDB, Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Oxia and S3-compatible object storage answer it with page one. An absent flag reads as unsupported | +| `supportsResultPagination === true` | the connection's `ProviderCapabilities` | Seventeen providers cannot serve page two. Cassandra and Elasticsearch throw on a positive offset; MongoDB, Redis, LibreDB, Prometheus, InfluxDB (InfluxQL), Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia and S3-compatible object storage answer it with page one. An absent flag reads as unsupported | | `pagination.hasMore` | `POST /api/db/query` | Requires the limiter's `PreparedQuery.wasLimited` as well as a row past the page — see below | | the surface supplies `onLoadMore` | `BottomPanel` | A result hydrated from an agent run has no statement of its own to page | diff --git a/docs/providers/README.md b/docs/providers/README.md index f2851d82bf..fe72e8bbc0 100644 --- a/docs/providers/README.md +++ b/docs/providers/README.md @@ -35,6 +35,7 @@ in lockstep with the code (see the tri-sync rule in [`../../CLAUDE.md`](../../CL | Neo4j | `neo4j` | Graph | `neo4j-driver-lite` (pure JavaScript, Bolt) | Cypher (read-only) | [neo4j.md](./neo4j.md) | | Milvus | `milvus` | Vector | `@grpc/grpc-js` (pure JavaScript, gRPC) | Milvus REST v2 requests (read routes) | [milvus.md](./milvus.md) | | Qdrant | `qdrant` | Vector | none, REST over the shared `node:http(s)` transport | Qdrant REST requests (read routes) | [qdrant.md](./qdrant.md) | +| Weaviate | `weaviate` | Vector | none, REST (and GraphQL below 1.39.7) over the shared `node:http(s)` transport | Weaviate REST requests (read routes) | [weaviate.md](./weaviate.md) | | InfluxDB (InfluxQL) | `influxdb` | Time series | none, HTTP over the shared `node:http(s)` transport | InfluxQL (read-only) | [influxdb.md](./influxdb.md) | | InfluxDB 3 (SQL) | `influxdb3` | Time series | none, HTTP over the shared `node:http(s)` transport | SQL (Apache DataFusion, read-only) | [influxdb3.md](./influxdb3.md) | | S3-compatible object storage | `s3` | Object storage | none, REST over the shared `node:http(s)` transport, signed by Studio's own SigV4 code; `hyparquet` for Parquet previews | AWS CLI read commands (a subset, read-only) | [s3.md](./s3.md) | @@ -53,7 +54,7 @@ in lockstep with the code (see the tri-sync rule in [`../../CLAUDE.md`](../../CL - **Filename = canonical type-id** (`postgres.md`, `mssql.md`, …), mirroring the source file (`src/lib/db/providers//.ts`, or a `/` directory when a provider is - split across modules, as Couchbase, ClickHouse, Druid, Trino, BigQuery, Snowflake, Spark, Cassandra, libSQL, DuckDB, Db2, Prometheus, Kafka, etcd, Neo4j, Milvus, Qdrant, InfluxDB, Oxia, Databend, S3, Kubernetes, MQTT, Firestore, RabbitMQ and OPC UA are). The official product name (e.g. + split across modules, as Couchbase, ClickHouse, Druid, Trino, BigQuery, Snowflake, Spark, Cassandra, libSQL, DuckDB, Db2, Prometheus, Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, Oxia, Databend, S3, Kubernetes, MQTT, Firestore, RabbitMQ and OPC UA are). The official product name (e.g. "SQL Server") is used only in each doc's title and prose. **One directory may serve two type-ids** — `providers/sql/search/` is `elasticsearch` and `opensearch`, and `providers/timeseries/influxdb/` is `influxdb` and `influxdb3`, two classes on two base classes sharing one connection layer — and each type-id still gets its own @@ -289,8 +290,8 @@ InfluxDB (InfluxQL) has a row per server line it reads, because each line is a s The Oxia row was verified against the running container on 2026-10-04, by the capture `tests/fixtures/oxia/README.md` records. The Databend row was verified against the running `databend-http` container (v1.2.951-nightly) on 2026-10-08: the user and password below sign in, and `system.databases` lists the seeded `libredb_demo` and `studio_demo`. -Start the fifty-one always-on services with a plain `docker compose -f database-compose.yml up -d`: -thirty-three engine containers plus the one-shot `couchbase-init`, `trino-init`, `kafka-init`, `rabbitmq-init`, `etcd-seed`, `oxia-seed`, `milvus-seed`, `qdrant-seed`, `influxdb-seed`, `databend-http-seed`, `silo-principals`, `silo-seed`, `garage-keys`, `garage-setup`, `garage-seed`, `rustfs-principals`, `rustfs-seed` and `firestore-seed` seed sidecars; the `Profile` column names +Start the fifty-three always-on services with a plain `docker compose -f database-compose.yml up -d`: +thirty-four engine containers plus the one-shot `couchbase-init`, `trino-init`, `kafka-init`, `rabbitmq-init`, `etcd-seed`, `oxia-seed`, `milvus-seed`, `qdrant-seed`, `weaviate-seed`, `influxdb-seed`, `databend-http-seed`, `silo-principals`, `silo-seed`, `garage-keys`, `garage-setup`, `garage-seed`, `rustfs-principals`, `rustfs-seed` and `firestore-seed` seed sidecars; the `Profile` column names the ones that need asking for. The count is derived, not written: a service in this file carries no `profiles:` key precisely when it backs a SHIPPED provider whose fixture lives here, so a plain `up -d` can reproduce that provider's integration pass. @@ -335,6 +336,7 @@ reproduces every provider in the table below and those two are reproduced by the | Neo4j | `neo4j` | localhost | 7687 | `neo4j` | `password123` | `neo4j`, or empty for the home database | *none* | | Milvus | `milvus` | localhost | 19530 | `root` | the documented default ([milvus.md, section 4.2](./milvus.md#42-authentication)) | `default` | *none* | | Qdrant | `qdrant` | localhost | 6333 | *none* | *none* | *none* | *none* | +| Weaviate | `weaviate` | localhost | 18280 | *none* | *none* | *none* | *none* | | S3-compatible object storage, MinIO | `minio` | localhost | 9000 | `studio-browse` | `Browse123pass!` | *none*, or a bucket such as `studio-demo` to pin it | `s3-minio` | | S3-compatible object storage, MinIO with a site region | `minio-region` | localhost | 9030 | `studio-browse` | `Browse123pass!` | *none*; Region `eu-central-1` | `s3-region` | | S3-compatible object storage, Silo | `silo` | localhost | 9010 | `studio-browse` | `Browse123pass!` | *none*, or a bucket such as `studio-demo` | *none* | @@ -387,6 +389,10 @@ Their certificates are generated into a volume by the `milvus-certs` one-shot an `qdrant` is seeded by its `qdrant-seed` one-shot; `qdrant-auth` (port 6343, an admin key, a read-only key and JWT RBAC) sits behind the profile `qdrant-auth`, and `qdrant-tls` (port 6353, one-way TLS) and `qdrant-mtls` (port 6363, TLS that verifies a client certificate) behind `qdrant-tls`. Their keys and certificates are generated into a volume by the `qdrant-keys` one-shot and never committed; [`docker/qdrant/README.md`](../../docker/qdrant/README.md) says how to start and seed each, how to copy the keys out, and what every seeded collection is for. +**Weaviate has three more servers behind `weaviate-matrix` and two keyed ones behind `weaviate-secure`, and the plain `weaviate` service takes no key and no TLS.** +`weaviate` (1.40.2) is seeded by its `weaviate-seed` one-shot; `weaviate-1-37` (1.37.4, port 18281), `weaviate-1-38` (1.38.22, port 18285) and `weaviate-nographql` (1.40.2 with GraphQL disabled, port 18282) sit behind `weaviate-matrix`, one per server shape the provider reads, and `weaviate-auth` (port 18283, API keys and RBAC) and `weaviate-tls` (port 18284, Weaviate's own TLS listener) behind `weaviate-secure`, each with a database user that holds only the `viewer` role. +Their root key and certificate are generated into a volume by the `weaviate-keys` one-shot and never committed; [`docker/weaviate/README.md`](../../docker/weaviate/README.md) says how to start and seed each, how to copy the keys out, and what every seeded collection is for. + **InfluxDB has one more fixture behind a profile of its own, and the three plain services take no TLS.** `influxdb1`, `influxdb2` and `influxdb3` are seeded by the `influxdb-seed` one-shot, which writes the `home` sample with timestamps in the last 25 hours, the fixed `edge` measurements, the 1.x user `reader` and the 2.x read-only token; `influxdb3-filelimit` (port 8182, `--query-file-limit 1`) sits behind the profile `influxdb-filelimit` and is seeded from the host. The 1.x admin is `admin` / `password123` and the 2.x operator token is `libredb-influxdb2-operator-token`; connect with the read principals in the table, because on 1.x and 2.x the server keeps a read-only mode only for a READ user or a read bucket token. diff --git a/docs/providers/weaviate.md b/docs/providers/weaviate.md new file mode 100644 index 0000000000..112f8c0c3d --- /dev/null +++ b/docs/providers/weaviate.md @@ -0,0 +1,376 @@ +# Weaviate Provider + +The `weaviate` type-id: read-only vector database browsing and searching over Weaviate's REST API, and over GraphQL for the searches of a server older than 1.39.7, tested on Weaviate 1.40.2, 1.38.22 and 1.37.4. +Source: [`src/lib/db/providers/vector/weaviate/`](../../src/lib/db/providers/vector/weaviate/). +Tests: [`tests/unit/db/weaviate/`](../../tests/unit/db/weaviate/) and [`tests/integration/db/weaviate-provider.test.ts`](../../tests/integration/db/weaviate-provider.test.ts). +Tracking issue: [#1566](https://github.com/libredb/libredb-studio/issues/1566), with [#1089](https://github.com/libredb/libredb-studio/issues/1089) and [#424](https://github.com/libredb/libredb-studio/issues/424). + +## 1. Overview + +Studio reads a Weaviate server through Weaviate's own REST requests, written in the editor as one `METHOD /v1/path` line and one JSON body, the form Weaviate's REST reference prints. +It browses collections with their properties and vectors, lists and reads objects, and runs BM25, hybrid, near-vector and near-object searches and aggregate counts, written in the REST search shape on every server and run over REST or GraphQL as the server's version decides. +It writes nothing: every request Studio sends is a read, and no maintenance operation exists for Weaviate. +It sends no text to a model: the searches that embed text on the server are refused before anything is sent, which a listener behind a vectorizer module confirms (section 3.2). +It never wakes a cold tenant, and it sends an API key without TLS only to this machine or through an SSH tunnel. + +### Concept mapping + +| Weaviate | Studio | +|---|---| +| One server or cluster | One connection, with no database or container level | +| A collection (class) | A row of Collections in the tree, opened in the Source tab | +| An object | A row of a result: `$id`, its properties, and with `include=vector` its vectors | +| The unnamed vector, a named vector | A column `$vector` or `$vector.`, typed `Vector(dimension, distance, index)` | +| A tenant of a multi-tenant collection | A name and activity status in the collection's Source, never a tree row | +| An alias | A name in its collection's Source and in `GET /v1/aliases`, never a tree row | +| A REST read or search route | One request per run in the editor | + +Tenants and aliases follow the precedent of Milvus's partitions and Qdrant's aliases: a detail of the collection, in its Source and in the console, because a tenant belongs to one collection and a collection may hold hundreds of thousands of them. + +## 2. Architecture + +### 2.1 Where it sits + +`WeaviateProvider` extends `BaseDatabaseProvider` in the `vector` family, and every module talks to Weaviate only through the `WeaviateClient` interface of `client.ts`, each through the slice of operations it sends. +`rest-client.ts` is the one file that builds a path, from the route table, over the shared `node:http(s)` transport (`src/lib/db/http/node-transport.ts`), so the client can build the console's read routes, the readiness probe and the GraphQL read, and nothing else. +`graphql.ts` is the one producer of GraphQL text. +`routes.ts`, the phase 0 half of `request.ts`, `guard.ts`, `generators.ts` and `labels.ts` are pure and shipped to the browser, because the editor, the confirmation gate and the generators read them; everything else runs on the server only. + +### 2.2 Modules + +| File | What it owns | +|---|---| +| `client.ts` | The seam: `WeaviateClient`, its operations, its request and answer types, and `WeaviateError` | +| `rest-client.ts` | The only builder of paths, from the route table; the `Authorization` header; the shared transport | +| `connection-options.ts` | The endpoint, the token, the plaintext rule, the TLS material, the tunnel's far end and the seed stage | +| `routes.ts` | The console's dialect and its seventeen routes, their query keys and closed body schemas, the refused keys and the refusal sentences | +| `request.ts`, `guard.ts` | A parsed request to a typed one (names, the where filter, the inference rule, bounds), the search model, and the browser's verdict | +| `versions.ts` | The version `GET /v1/meta` reports and the table that picks REST or GraphQL | +| `graphql.ts` | The REST and GraphQL encoders of one search model, and the GraphQL builder | +| `schema.ts` | A class definition to columns, vectors, the GraphQL selection and the facts a request reads | +| `results.ts`, `execute.ts`, `errors.ts` | Answers to results, one request within its bounds, deadline and permit, the tenant guard, and the one error table | +| `source.ts`, `objects.ts`, `generators.ts`, `labels.ts` | The Source, the object surface, the generated requests and the labels | +| `monitoring.ts`, `monitoring-reads.ts`, `index.ts` | The monitoring panels and the composition root | + +### 2.3 Registration & lifecycle + +The constructor validates nothing and opens nothing, so a provider built from any connection answers its capabilities and labels. +`connect()` checks the endpoint, the token and the TLS panel first, then sends exactly one request, `GET /v1/meta`, which authenticates (a server with anonymous access off answers 401 without a key) and gives the version the path table reads. +A server older than 1.37 connects, with one warning that it is below the supported range. +`disconnect()` closes the connection's one keep-alive agent, which closes a socket left idle for 4 s on its own, below Weaviate's 10 s idle close. +The transport never goes through an `http_proxy` or `https_proxy` variable and never follows a redirect: use an SSH tunnel to reach a private endpoint. + +### 2.4 The client, and why + +The client is Studio's own, over the shared transport, and it adds no package. +The official TypeScript client speaks gRPC for its queries, which on Weaviate Cloud and DigitalOcean is a second host name, against the one-endpoint rule the vector providers keep, and it sends headers Studio does not choose. + +## 3. Design decisions + +### 3.1 Weaviate's REST requests as the console, run over REST or GraphQL + +The editor text is the form Weaviate's REST reference documents, so a request can be pasted from it. +Searches are written in the REST search shape on every server, the precedent of Milvus, whose REST text runs over gRPC. +REST search did not arrive in version order, measured on 2026-10-23: 1.38.22 carries the routes behind `EXPERIMENTAL_REST_SEARCH_ENABLED`, 1.39.0 has none, 1.39.6 has them behind the flag, 1.39.7 serves them by default, and near-vector starts at 1.39.8. +So `connect()` reads the version, as Qdrant, Milvus and InfluxDB do, and a table picks the path: + +| Server | bm25, hybrid, near-object, aggregate | near-vector | +|---|---|---| +| 1.39.8 and later | REST | REST | +| 1.39.7 | REST | GraphQL | +| below 1.39.7 | GraphQL | GraphQL | +| version not read | GraphQL | GraphQL | + +GraphQL is chosen below 1.39.7 even where a 1.38 server has the flag on: both paths return the same rows, and the flag is configuration the version cannot show. +A server that answers `graphql api is disabled` (new Weaviate Cloud clusters set `DISABLE_GRAPHQL`) has the same search sent once more over REST; one that has neither path is refused with one sentence, and browsing keeps working. +1.38.22 ignores `DISABLE_GRAPHQL` and serves GraphQL anyway; 1.39.0 and later honour it (measured). +The path that answered is remembered for the session and named on the result ("Answered via REST search." or "Answered via GraphQL."), and nothing is stored with the saved connection, because managed services upgrade the engine on their own schedule. +No raw GraphQL is a route: `graphql.ts` writes every document from the search model, identifiers checked, strings escaped by one function and numbers as typed. + +### 3.2 No text is sent to a model + +A Weaviate collection may declare a vectorizer module, and some searches make the server send the user's text to it: the near-text route, generative search (`singlePrompt`, `groupedTask`), `rerank`, and hybrid with an `alpha` other than 0, whose server default is 0.7. +Each is refused before anything is sent, and `alpha` must be written as 0. +Measured on 2026-10-23 with a collection whose `text2vec-openai` base URL is a listener on the Docker bridge gateway: hybrid at `alpha` 0, BM25, near-object, near-vector, aggregate, the object reads and every surface sent the listener nothing on 1.37.4 and 1.40.2, through REST and GraphQL, while hybrid at 0.5 and a nearText control each sent it one request. +No header but `Authorization`, `Content-Type` and `Accept` is ever sent, so a model-provider key such as `X-OpenAI-Api-Key` cannot reach the server through Studio. + +### 3.3 Nothing is written + +v1 runs reads only: every write route (objects, batch, schema, tenants, aliases, backups, users and roles, replication, namespaces, classifications) is refused by name, saying what v1 runs. +The client sends `GET`, and `POST` only to the search, aggregate and GraphQL paths. + +### 3.4 A read never wakes a tenant + +On a collection with `autoTenantActivation` on, any data read of a COLD tenant sets it HOT, for a user with only the built-in `viewer` role too; reading the tenant's own record, the tenant list and `/v1/nodes` does not (measured on 1.37.4 and 1.40.2). +So before any request that names a tenant, the provider reads `GET /v1/schema/{collection}/tenants/{tenant}` and refuses unless the status is HOT (or its older name, ACTIVE), naming the status; a multi-tenant collection without a tenant is refused too. +On the 1.37 line (1.37.4 and 1.37.17), `GET /v1/schema/{collection}/shards?tenant=` with a COLD tenant wakes it and then does not answer, and that collection's `/shards` stops answering for every tenant until the server restarts; the guard is what keeps the provider from sending it. + +### 3.5 The read-only mode + +`enforcesReadOnly` is true: every console request is a read and the provider has no maintenance operation. +A read-only seed connection with no key is refused, because a server with anonymous access on, its default, grants a request with no key every write, so the mode would promise a boundary the server does not keep. + +### 3.6 Integers + +Weaviate stores an `int` property as a float64 (`intVal` in `usecases/objects/validation/properties_validation.go`): written through REST or gRPC, 2^53 + 1 is stored as 2^53 and 2^63 - 1 is refused, so a plain JSON parse loses nothing the server has. +GraphQL answers null for every int outside the 32-bit range, 2^53 - 1 included, so a null in an `int` column on the GraphQL path carries a warning saying it may be such a value. + +## 4. Connection + +### 4.1 Configuration fields + +| Field | Use | +|---|---| +| Host, Port | One endpoint; `8080` by default. REST and GraphQL share it; gRPC (50051) is never dialled | +| API key or token | An API key or an OIDC access token, sent as `Authorization: Bearer`; empty for anonymous access | +| SSL / TLS | Off, or the mode, CA and client certificate of the shared panel | + +There is no User field and no Database box: Weaviate takes a bearer token alone and has no container level, and a non-empty user from a seed or the API is refused naming the field. + +### 4.2 Authentication + +An API key and an OIDC access token travel the same way, as one bearer header set once per connection. +An OIDC token is pasted, not obtained: v1 has no refresh flow, and an expired token is refused by the server as any other. +The safest credential is the key of a database user that holds only the built-in `viewer` role: it reads every surface this provider shows, and the server refuses its writes (measured). +A `viewer` user can also read `/v1/authz/roles` and `/v1/users/db`, which this provider never reads or shows. +A role scoped to some collections cannot use GraphQL at all, because GraphQL introspection needs `read_collections` on every collection, so on a server below 1.39.7 such a role browses but cannot search. + +### 4.3 TLS + +The SSL panel maps to the shared TLS material; Weaviate's own listener serves TLS with `--scheme https`, and plain HTTP to a TLS port is refused with a sentence asking for an SSL mode. + +### 4.4 One endpoint + +Every request goes to the one host and port; REST and GraphQL are two paths on it. + +### 4.5 SSH tunnel + +The shared tunnel is offered: the origin dialled is the local forward, while sentences, the plaintext rule and the certificate identity use the tunnel's far end. + +### 4.6 A key needs TLS off this machine + +A key is sent without TLS only to a loopback host or through an SSH tunnel (`plaintextSecretRefusal`); anything else is refused before any socket opens. + +### 4.7 Pasting an address + +The Host box takes a pasted `http://` or `https://` address and splits it into Host and Port. + +### 4.8 Server versions + +1.37 and later are supported; 1.37 left Weaviate's support window (the three most recent minors) when 1.40 shipped and stays supported because a managed service still runs it. +The fixture matrix runs 1.40.2, 1.38.22 and 1.37.4, and 1.40.2 with GraphQL disabled; the path table was measured on 1.37.4, 1.37.17, 1.38.22, 1.39.0, 1.39.6, 1.39.7, 1.39.8, 1.39.13, 1.40.0 and 1.40.2. +A later release takes REST by the table, and REST search is still a preview upstream, so a release is claimed only once it is measured. + +### 4.9 Hosted services + +Weaviate Cloud and DigitalOcean Managed Weaviate are claimed nowhere until a test cluster passes the live check. + +### Connection string + +`weaviate` has no connection string scheme, no `readTls` and no seed load check: every field of its row in `CONNECTION_STRING` is `null` ([`connection-string.ts`](../../src/lib/db/providers/vector/weaviate/connection-string.ts)). + +### Execution UI + +The rolled-back notice names `COMMIT` as the keyword that keeps an open transaction, and `weaviate` has no consent deadline, so the agent's consent card shows no deadline chip or sentence for it. +Its row in `EXECUTION_UI` is declared in [`execution-ui.ts`](../../src/lib/db/providers/vector/weaviate/execution-ui.ts). + +## 5. Query interface + +### 5.1 The request + +One request per run: optional comment lines starting with `//` or `#`, one `METHOD /v1/path` line with an optional query string, and for `POST` one JSON object. +The prefix may be left out: `GET schema` is `GET /v1/schema`. + +### 5.2 The routes + +| Route | Query keys | Body | +|---|---|---| +| `GET /v1/meta`, `GET /v1/schema`, `GET /v1/schema/{collection}` | none | none | +| `GET /v1/schema/{collection}/shards` | `tenant` | none | +| `GET /v1/schema/{collection}/tenants`, `GET /v1/schema/{collection}/tenants/{tenant}` | none | none | +| `GET /v1/aliases`, `GET /v1/aliases/{alias}` | none | none | +| `GET /v1/nodes`, `GET /v1/nodes/{collection}` | `output` | none | +| `GET /v1/objects` | `class` (required), `limit`, `after`, `offset`, `include`, `sort`, `order`, `tenant` | none | +| `GET /v1/objects/{collection}/{id}` | `include`, `tenant` | none | +| `POST /v1/search/{collection}/bm25` | none | required `query`; `queryProperties` | +| `POST /v1/search/{collection}/hybrid` | none | required `query` and `alpha: 0`; `queryProperties`, `fusionType`, `maxVectorDistance`, `targetVector` | +| `POST /v1/search/{collection}/near-vector` | none | required `vector`; `targetVector`, `distance`, `certainty` | +| `POST /v1/search/{collection}/near-object` | none | required `id`; `targetVector`, `distance`, `certainty` | +| `POST /v1/aggregate/{collection}` | none | optional: `where`, `tenant`, `groupBy`, `limit`, `returnMetrics` (`count`) | + +Every search also takes `where`, `limit`, `offset`, `autoLimit`, `returnProperties`, `returnMetadata` (`distance`, `certainty`, `score`, `explainScore`, `creationTime`, `lastUpdateTime`), `tenant` and `consistencyLevel`. + +### 5.3 Request rules + +- Every body key, at every level the where filter declares, is checked against a closed set and an unknown key is refused by name: the server ignores an unknown key in silence, so a misspelled `where` returned unfiltered results and a misspelled `limit` ten rows (measured). +- `singlePrompt`, `groupedTask` and `rerank` are refused because they call a model; `groupBy`, `numberOfGroups` and `objectsPerGroup` on a search, and `over` and `objectLimit` on an aggregate, because the server reserves them; `returnReferences` because returning cross-references is outside v1. +- A collection or alias name follows Weaviate's own rule, a letter then letters, digits and `_`, at most 255 characters, with its first letter capitalised as the server does; a tenant name holds letters, digits, `-` and `_`, 1 to 64 characters; an object id is a UUID. +- A where filter's `And` and `Or` take operands and `Not` exactly one; every other operator takes a path and exactly one value key; at most 256 conditions, 8 levels and 64 KiB. +- A vector search names a vector with `targetVector` when its collection has more than one, and hybrid does too even at `alpha` 0, which the server refuses without one (measured); a BM25 search reads no vector and sends none; a property a search names must exist and must not be a cross-reference. +- `limit` plus `offset` is at most 1,000, below the server's `QUERY_MAXIMUM_RESULTS`, and `offset` may be 0; a search with no limit is sent with 10 and an object list with 25, so both paths answer the same rows. +- An aggregate with `groupBy` and no `limit` is sent with 100, the number of groups both paths answer then (measured on 1.37.4 and 1.40.2), and a result that reaches its limit says more groups may exist. + +### 5.4 Examples + +``` +GET /v1/objects?class=Article&limit=50 +POST /v1/search/Article/bm25 {"query": "vector search", "where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}, "limit": 5, "returnMetadata": ["score"]} +POST /v1/search/Product/near-vector {"vector": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], "targetVector": "image", "limit": 3, "returnMetadata": ["distance"]} +POST /v1/aggregate/TenantNotes {"tenant": "acme"} +``` + +### 5.5 Where the console differs from a REST call + +A request is checked and re-written before it is sent, never forwarded as typed, and on a server below 1.39.7 a search is sent as GraphQL. + +### 5.6 Result shape + +A search row has the same columns on both paths: `$id`, the properties asked for (every non-reference property when none is named), then the metadata asked for as `$distance`, `$certainty`, `$score`, `$explainScore`, `$creationTime` and `$lastUpdateTime`, the times in milliseconds since the epoch; GraphQL answers the times and the score as text, which are read back as the numbers REST answers. +Neither search path returns a vector: REST search has no metadata for it. +An object read with `include=vector` returns `$vector` and `$vector.` cells, drawn as vectors. +An aggregate answers one `count` row, or one row per group with the group's value; an object list that fills its limit says how to read the next page with `after` from the last row shown, which after the result budget drops a page's tail is the last row kept, or to set the `after` it already names; a list that names `offset` or `sort` gets no such notice, because `after` takes neither. +A near-vector search that finds nothing on a compressed index says that a vector of the wrong length looks the same there, because Weaviate answers an empty result rather than an error then. + +### 5.7 Bounds + +A response is read up to 16 MiB, a result is built up to 8 MiB and dropped whole past it, and a text cell is cut at 65,536 characters with a marker. +A metadata route has 10 s and a read or search 30 s, at most the connection's query timeout and below Weaviate's 60 s write timeout. + +### 5.8 Time, cancellation and the confirmation gate + +A running or queued request can be cancelled; the request's socket is closed. +Every route is a read, so nothing asks for confirmation; the browser runs the same phase 0 the provider runs, and a text it refuses is never sent. + +### 5.9 SQL grammar + +How this engine's statement text is read is declared once, in [`src/lib/db/providers/vector/weaviate/sql-grammar.ts`](../../src/lib/db/providers/vector/weaviate/sql-grammar.ts), the `weaviate` row of the SQL grammar registry in `src/lib/db/sql-grammar/`. +`readsSqlText` is `false`: `weaviate` takes one Weaviate console request, a `METHOD /v1/path` line and one JSON body, whose strings escape with a backslash and where `//` opens a comment outside a string; the provider parses it with the shared console parser. +The confirmation gate therefore answers from this engine's row of `NON_SQL_DESTRUCTIVE_VOCABULARY` in `src/lib/db/destructive-commands.ts` instead of a SQL reading. +Its grammar is `DEFAULT_SQL_GRAMMAR`, the compatibility default, since no SQL grammar of its own applies to this text. +Redaction is `none`: a redacted statement is stored as `?`, because a reader guessing where a literal ends in a language it does not read can store the literal. + +## 6. Schema introspection + +### 6.1 The object surface + +One kind, Collection, from one `GET /v1/schema`, which also answers every collection's columns, so describing every collection is one round trip; collections are listed by name. +A collection's columns are `$id`, its properties in schema order typed with Weaviate's own word (`text`, `int`, `number`, `date`, `geoCoordinates`, `object` and the rest, a cross-reference as `ref → Target`), then its vectors. +The schema declares no dimension, so opening one single-tenant collection reads one object with `include=vector` to spell it; a multi-tenant collection is never read past its schema. +No row count is on the listing. + +### 6.2 Object source + +The Source has two parts: `Schema`, the class definition as Weaviate answers it, and `State`: the aliases that point at the collection, then for a single-tenant collection its shards with their statuses and its exact object count (aggregate `meta.count`), and for a multi-tenant one its tenant count and the first 1,024 tenants by name with their activity statuses, as Milvus lists partitions. +`/v1/nodes` object counts are never used: they read 0 for collections that held objects twenty minutes after they were written. + +### 6.3 Object edit (#789): nothing to write + +No kind declares `acceptsRowWrites` or `acceptsSourceEdits`: v1 reads only (section 3.3). +The absence is `weaviate`'s entry in `EXPECTED_EDIT_ABSTAINERS` (`tests/helpers/object-edit-expectation.ts`), and `tests/isolated/object-edit-declarations.test.ts` is what holds that entry and this section together. + +### 6.4 Generated requests + +A collection click runs `GET /v1/objects?class=&limit=50`; on a multi-tenant collection phase 1 refuses it with no call and names the request that lists the tenants and which are HOT. +Generate Request writes, without running it, a near-vector search over the first vector with a probe vector of the right length, and a BM25 search and an aggregate count as comments. +Where no object has shown the vector's length, as in the tree's one-read schema columns, the BM25 search is the request and the near-vector search a comment waiting for the user's numbers, because a guessed length is a server error ("vector lengths don't match", measured on 1.40.2). + +## 7. Monitoring & health + +| Surface | Reads | +|---|---| +| Health | `GET /v1/.well-known/ready`, readiness only | +| Overview | `GET /v1/meta` for the version, `GET /v1/schema` for the collections and vector indexes; uptime and size are not reported | +| Tables | One exact count per single-tenant collection of the first 200 by name; a multi-tenant collection is counted per tenant in the console | +| Indexes | One row per vector: index type, distance and compression | +| Slow queries, sessions, storage | Empty: Weaviate reports none over the routes Studio reads | + +## 8. Maintenance + +None: Weaviate has no maintenance operation in v1, so no Admin > Operations card and no tree control is offered for it. + +## 9. Capabilities & labels + +`queryLanguage` `json` with `queryDialect` `weaviate`, `containerLevels` empty, `enforcesReadOnly` true, every `supports*` false, `defaultPort` 8080. +The labels name a Collection and an Object, "Read Objects" and "Generate Request", and the statement language plan mode states is generated from the route table. + +### SQL writing + +[`weaviate/sql-writing.ts`](../../src/lib/db/providers/vector/weaviate/sql-writing.ts) declares how a generated statement spells a literal, a name and a bind for this engine, and it is this engine's row of `SQL_WRITING` ([`src/lib/db/sql-writing/index.ts`](../../src/lib/db/sql-writing/index.ts)), which the readers in [`src/lib/sql/values.ts`](../../src/lib/sql/values.ts) and [`src/lib/sql/identifier.ts`](../../src/lib/sql/identifier.ts) look up. +A literal is written by `literalStandard` and read back by `unquoteStandard`: the quote is doubled and a backslash is data. +A name is quoted by `identifierDoubleQuoted`, the SQL standard form: a double-quoted name with an inner double quote doubled. +There is no placeholder (`placeholder: null`), so a generator quotes the value with `quoteLiteral` instead of emitting a bind. +This engine declares `queryLanguage: "json"`, so no statement is ever built for it to read; what a generator emits for such a connection is portable SQL meant to run elsewhere, and the standard form is the only thing it can claim. +Inline row editing reads a key column's kind through the shared `INSTANT_TYPE_NAMES`, `FLOAT64_TYPE_NAMES` and `EXACT_DECIMAL_TYPE_NAMES` of the module's `inlineEdit`, and binds every edit as typed. + +The module's `export` field writes a result export's CREATE TABLE and INSERT from the shared building blocks alone: `STANDARD_DDL_TYPES` for the column types, `NOTHING_STANDS_ALONE` and `NO_BARE_SPELLING`, so every bare declared name is re-spelled from its family, `NULL_NON_FINITE` for NaN and the infinities, and `binaryStandardHex` for a binary cell (`X'0102'`). +The engine declares `queryLanguage: "json"`, so no SQL statement is ever built for it to read, and a file exported from it is meant to run somewhere else: every bare name in it is re-spelled portably rather than kept as one engine's private word. + +## 10. Error handling + +| Condition | Class | +|---|---| +| 401, a missing or refused key or token | `AuthenticationError` | +| 403 from RBAC at connect | `AuthenticationError`; after connect a `QueryError` naming what the server refused | +| A collection that does not exist (404, or GraphQL's unknown field) | `QueryError` | +| A route this server version does not serve | `QueryError` | +| A cold tenant | refused before any read, naming its status | +| GraphQL disabled, REST search absent or behind its flag | `QueryError` naming what the server lacks | +| A GraphQL refusal of a scoped role | `QueryError` naming the version where REST search serves | +| Past `QUERY_MAXIMUM_RESULTS` | `QueryError` | +| Plain HTTP to a TLS port, a TLS failure, a refused or unreachable endpoint | `ConnectionError` | +| A deadline | `TimeoutError` | +| An invalid request, name, key or token | `DatabaseConfigError` or a phase 0 refusal, never echoing a secret | + +GraphQL answers its refusals under HTTP 200 with `errors` beside `data`; they are read into the same classes. + +## 11. Testing + +### 11.1 How the tests work + +The unit tests drive every module through a recording client and a recording transport, with no `mock.module()`. +The integration test replays [`tests/fixtures/weaviate/`](../../tests/fixtures/weaviate/README.md): each file is one scenario of `tests/live/weaviate-scenarios.ts`, written by `tests/live/weaviate-evidence.ts` against the fixture servers, holding every request the provider sent, each answer, and what each call returned or threw. +The replay builds the same provider over a transport that answers from the file, makes the same calls, and fails unless the requests and the outcomes are the recorded ones. + +### 11.2 Run it + +`bun tests/run-tests.ts tests/unit/db/weaviate/` and `bun tests/run-tests.ts tests/integration/db/weaviate-provider.test.ts`. + +### 11.3 The live fixtures + +`database-compose.yml` runs `weaviate` (1.40.2), and behind `weaviate-matrix` `weaviate-1-37` (1.37.4), `weaviate-1-38` (1.38.22) and `weaviate-nographql`, and behind `weaviate-secure` `weaviate-auth` and `weaviate-tls` with a `viewer` user; [`docker/weaviate/README.md`](../../docker/weaviate/README.md) describes them and the seeded collections. + +### 11.4 The live check + +`bun tests/live/weaviate-live-check.ts --keys ` runs every scenario against the fixture servers and holds each run to its capture, the same requests and the same outcomes, compared with object keys and arrays sorted because Weaviate's own order differs between two identical reads; it snapshots the schema, the aliases and every tenant's status before and after, and fails on any change. +Measured on 2026-10-23: every scenario matched and no tenant changed status. +`bun tests/live/weaviate-path-parity.ts` sends 72 requests, every where operator and value type, every search kind and the aggregates, to 1.40.2 over REST and to 1.38.22 and 1.37.4 over GraphQL, and fails unless each answers the same rows with the same cell types; a grouped aggregate's order and 1.37's WithinGeoRange count are the servers' own and expected. + +## 12. Running Weaviate for Studio + +Start a server with no vectorizer and `API_BASED_MODULES_DISABLED=true` for a server Studio only reads: an empty `ENABLE_MODULES` still loads every API-based module. +Create a database user with the built-in `viewer` role and give Studio its key. + +## 13. Known limitations + +- No write path, no raw GraphQL, no gRPC and no cross-references in results. +- A search on a server below 1.39.7 with GraphQL disabled and the REST flag off is refused; browsing works. +- A role scoped to some collections cannot search a server below 1.39.7. +- Per-tenant counts are read in the console, not in the Source. +- An OIDC token is not refreshed. +- Weaviate 1.37 counts an aggregate filtered by `WithinGeoRange` as 0 even where objects match (measured on 1.37.4: 0, while a search finds 500; 1.38.22 and 1.40.2 count 500); such a count carries a note saying so. + +## Migration DDL + +[`WEAVIATE_MIGRATION_DDL`](../../src/lib/db/providers/vector/weaviate/migration-ddl.ts) is what the schema-diff migration generator writes for `weaviate`, read through `migrationDdlFor` in `src/lib/db/migration-ddl/`. +It declines the whole diff: `refusal` is the one line the migration prints after its header, in place of any DDL, and `transactionWrapper` is `null`. +`weaviate` text is a Weaviate console request, not SQL, so there is no table DDL to wrap (#284). + +The refusal reason it prints, verbatim: + +- "A collection's properties and vectors are declared through Weaviate's own schema API, not SQL DDL, so there is no column definition to change." + +## 14. References + +- Weaviate REST reference and OpenAPI document, v1.40.2. +- Weaviate source, `usecases/objects/validation/properties_validation.go`, `entities/schema/validation.go`, `adapters/handlers/rest/server.go`, v1.40.2. +- The design: issue [#1566](https://github.com/libredb/libredb-studio/issues/1566). diff --git a/e2e/weaviate-provider.spec.ts b/e2e/weaviate-provider.spec.ts new file mode 100644 index 0000000000..bf4f0b3320 --- /dev/null +++ b/e2e/weaviate-provider.spec.ts @@ -0,0 +1,80 @@ +import { expect, test } from "@playwright/test"; + +/** + * Gate 2 and gate 5 for the Weaviate provider (#1566 spec 8.3), the Qdrant shape (e2e/qdrant-provider.spec.ts). + * + * What a new type-id needs in order to be SELECTABLE lives outside the provider, as declarations + * (`DatabaseUIConfig`, `READ_ONLY_ENFORCED`, the credential record), which is why this runs in a browser. The + * refusal a key without TLS gets is checked through Test Connection, which the server answers before any socket + * opens, so no Weaviate is needed. It runs on the second server because Test Connection spends the shared account's + * per-process rate-limit bucket, and it signs in as the admin for the reason e2e/neo4j-provider.spec.ts gives. + */ +const TEST_KEY = "password"; + +test.describe("Weaviate in the connection dialog", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/login"); + await page.locator('input[type="email"]').fill("admin@libredb.org"); + await page.locator('input[type="password"]').fill("test-admin"); + await page.getByRole("button", { name: "Sign In" }).click(); + // The admin lands on the Admin Dashboard; the editor is one navigation away. + await page.waitForURL(/\/admin/); + await page.goto("/"); + await expect(page.locator("text=Query 1").first()).toBeVisible({ timeout: 10000 }); + + const sidebarButtons = page.locator("text=LibreDB Studio").locator("..").locator("..").locator("button"); + await sidebarButtons.last().click(); + await expect(page.locator('[role="dialog"]')).toBeVisible({ timeout: 5000 }); + await page.locator('[role="dialog"]').getByRole("button", { name: "Weaviate", exact: true }).click(); + }); + + test("is offered as its own driver, prefills port 8080 and offers no connection string", async ({ page }) => { + const dialog = page.locator('[role="dialog"]'); + await expect(dialog.locator('input[value="8080"]')).toBeVisible(); + await expect(dialog.getByText("Connection String", { exact: true })).toHaveCount(0); + }); + + test("draws Host, Port and API key or token, no User and no Database, and the TLS, SSH and Read-only controls", async ({ + page, + }) => { + const dialog = page.locator('[role="dialog"]'); + await expect(dialog.locator("#host")).toBeVisible(); + await expect(dialog.locator("#port")).toBeVisible(); + await expect(dialog.locator("#password")).toBeVisible(); + await expect(dialog.locator("#user")).toHaveCount(0); + await expect(dialog.locator("#database")).toHaveCount(0); + await expect(dialog.getByText("API key or token", { exact: true })).toBeVisible(); + await expect(dialog.getByText("SSL / TLS", { exact: true })).toBeVisible(); + await expect(dialog.getByText("SSH Tunnel", { exact: true })).toBeVisible(); + await expect(dialog.getByLabel("Read-only", { exact: true })).toBeVisible(); + }); + + test("draws the field hints of spec 6.1", async ({ page }) => { + const dialog = page.locator('[role="dialog"]'); + await expect(dialog.getByText(/never Weaviate's gRPC port 50051\./)).toBeVisible(); + await expect(dialog.getByText(/A key for a user with only the viewer role is the safest choice\./)).toBeVisible(); + }); + + test("a pasted http address in the Host box splits into Host and Port", async ({ page }) => { + const dialog = page.locator('[role="dialog"]'); + const host = dialog.locator("#host"); + await host.fill("http://localhost:8080"); + await host.blur(); + await expect(host).toHaveValue("localhost"); + await expect(dialog.locator("#port")).toHaveValue("8080"); + }); + + test("a key with TLS off to a public host is refused on Test Connection, naming the three ways out", async ({ + page, + }) => { + const dialog = page.locator('[role="dialog"]'); + await dialog.locator("#host").fill("weaviate.example.com"); + await dialog.locator("#password").fill(TEST_KEY); + await dialog.getByRole("button", { name: "Test Connection", exact: true }).click(); + const result = dialog.getByTestId("connection-test-result"); + await expect(result).toContainText("SSL / TLS", { timeout: 15000 }); + await expect(result).toContainText("SSH tunnel"); + await expect(result).toContainText("clear the"); + await expect(result).not.toContainText(TEST_KEY); + }); +}); diff --git a/operator/bundle/manifests/libredb-studio-operator.clusterserviceversion.yaml b/operator/bundle/manifests/libredb-studio-operator.clusterserviceversion.yaml index a82ac438ad..b9ccae17e8 100644 --- a/operator/bundle/manifests/libredb-studio-operator.clusterserviceversion.yaml +++ b/operator/bundle/manifests/libredb-studio-operator.clusterserviceversion.yaml @@ -23,13 +23,13 @@ metadata: categories: Database, Developer Tools containerImage: ghcr.io/libredb/libredb-studio-operator:1.0.0 createdAt: "2026-10-17T20:44:37Z" - description: Open-source web-based SQL IDE for forty-one engines - PostgreSQL, + description: Open-source web-based SQL IDE for forty-two engines - PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, - MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, - S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, - SNMP and Sparkplug B - with AI-powered query assistance. + MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, + Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, + Modbus, NETCONF, SNMP and Sparkplug B - with AI-powered query assistance. olm.skipRange: '>=0.0.0 <1.0.0' operators.operatorframework.io/builder: operator-sdk-v1.42.3 operators.operatorframework.io/project_layout: helm.sdk.operatorframework.io/v1 @@ -56,7 +56,7 @@ spec: LibreDB Studio is an open-source, web-based SQL IDE. Query PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, - Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, + Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B from the browser, with AI-powered query assistance (natural-language-to-SQL, explain, fix), an ERD viewer, schema diff and a data profiler. No desktop client required. diff --git a/operator/config/manifests/bases/libredb-studio-operator.clusterserviceversion.yaml b/operator/config/manifests/bases/libredb-studio-operator.clusterserviceversion.yaml index 40b71a07a6..f96193128f 100644 --- a/operator/config/manifests/bases/libredb-studio-operator.clusterserviceversion.yaml +++ b/operator/config/manifests/bases/libredb-studio-operator.clusterserviceversion.yaml @@ -6,13 +6,13 @@ metadata: capabilities: Basic Install categories: Database, Developer Tools containerImage: ghcr.io/libredb/libredb-studio-operator:0.0.0 - description: Open-source web-based SQL IDE for forty-one engines - PostgreSQL, + description: Open-source web-based SQL IDE for forty-two engines - PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, - MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, - S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, - SNMP and Sparkplug B - with AI-powered query assistance. + MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, + Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, + Modbus, NETCONF, SNMP and Sparkplug B - with AI-powered query assistance. olm.skipRange: '>=0.0.0 <0.0.0' repository: https://github.com/libredb/libredb-studio support: LibreDB @@ -37,7 +37,7 @@ spec: LibreDB Studio is an open-source, web-based SQL IDE. Query PostgreSQL, MySQL, Oracle, Db2 LUW, SQL Server, SQLite, libSQL, DuckDB, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, - Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, + Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B from the browser, with AI-powered query assistance (natural-language-to-SQL, explain, fix), an ERD viewer, schema diff and a data profiler. No desktop client required. diff --git a/operator/helm-charts/libredb-studio/Chart.yaml b/operator/helm-charts/libredb-studio/Chart.yaml index 9714f8971b..c7190b2873 100644 --- a/operator/helm-charts/libredb-studio/Chart.yaml +++ b/operator/helm-charts/libredb-studio/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 name: libredb-studio -description: Web-based SQL IDE for cloud-native teams supporting forty-one engines - PostgreSQL, MySQL, SQLite, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B +description: Web-based SQL IDE for cloud-native teams supporting forty-two engines - PostgreSQL, MySQL, SQLite, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, libSQL, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B type: application -version: 0.1.102 +version: 0.1.103 appVersion: "1.0.0" kubeVersion: ">=1.26.0-0" home: https://github.com/libredb/libredb-studio @@ -69,6 +69,8 @@ keywords: # evaluator looking for a Milvus or Qdrant client types, so there is no second spelling to catch. - milvus - qdrant + # Weaviate (#1566): the type-id is also the word an evaluator looking for a Weaviate client types. + - weaviate # Three keywords, like the prometheus pair above with one more: `influxdb` and `influxdb3` are # the two type-ids and the products, and `influxql` is what an evaluator looking for an # InfluxQL client types. @@ -314,7 +316,7 @@ annotations: - name: Source url: https://github.com/libredb/libredb-studio artifacthub.io/changes: | - - "Add config.oidcRolePrefix, written as OIDC_ROLE_PREFIX: prefix filter for custom seed roles from the OIDC role claim" + - "Name Weaviate, read-only over its REST API, in the description and the keywords" dependencies: - name: postgresql version: "16.x.x" diff --git a/operator/helm-charts/libredb-studio/README.md b/operator/helm-charts/libredb-studio/README.md index 06b50742e8..16663b44cf 100644 --- a/operator/helm-charts/libredb-studio/README.md +++ b/operator/helm-charts/libredb-studio/README.md @@ -2,7 +2,7 @@ [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/libredb-studio)](https://artifacthub.io/packages/search?repo=libredb-studio) -Web-based SQL IDE for cloud-native teams supporting forty-one engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. +Web-based SQL IDE for cloud-native teams supporting forty-two engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, Apache Kafka, MQTT, RabbitMQ, etcd, Neo4j, Milvus, Qdrant, Weaviate, InfluxDB, InfluxDB 3, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. ## Prerequisites @@ -40,7 +40,7 @@ helm install libredb libredb/libredb-studio \ ```bash helm install libredb oci://ghcr.io/libredb/charts/libredb-studio \ - --version 0.1.102 \ + --version 0.1.103 \ --set secrets.jwtSecret=$(openssl rand -base64 32) \ --set secrets.adminPassword=MyAdmin123 ``` diff --git a/packaging/aur/.SRCINFO b/packaging/aur/.SRCINFO index cb49ea7e21..4ee93e321a 100644 --- a/packaging/aur/.SRCINFO +++ b/packaging/aur/.SRCINFO @@ -1,5 +1,5 @@ pkgbase = libredb-studio-bin -pkgdesc = Web-based SQL IDE for forty-one database engines with AI query assistance (prebuilt standalone server) +pkgdesc = Web-based SQL IDE for forty-two database engines with AI query assistance (prebuilt standalone server) pkgver = 0.17.0 pkgrel = 1 url = https://github.com/libredb/libredb-studio diff --git a/packaging/aur/PKGBUILD b/packaging/aur/PKGBUILD index 9b018743da..53e365c559 100644 --- a/packaging/aur/PKGBUILD +++ b/packaging/aur/PKGBUILD @@ -19,7 +19,7 @@ pkgname=libredb-studio-bin pkgver=0.17.0 pkgrel=1 -pkgdesc='Web-based SQL IDE for forty-one database engines with AI query assistance (prebuilt standalone server)' +pkgdesc='Web-based SQL IDE for forty-two database engines with AI query assistance (prebuilt standalone server)' arch=('x86_64' 'aarch64') url='https://github.com/libredb/libredb-studio' license=('MIT') diff --git a/packaging/aur/README.md b/packaging/aur/README.md index 23624ca00a..6391310d4d 100644 --- a/packaging/aur/README.md +++ b/packaging/aur/README.md @@ -56,7 +56,7 @@ git add PKGBUILD .SRCINFO libredb-studio-bin.install LICENSE REUSE.toml git commit -m "Initial import: 0.17.0" && git push origin HEAD:master ``` -The files here name forty-one engines and pin 0.17.0, which ships eighteen, because the etcd provider (#1089), the Neo4j provider, the Db2 LUW provider (#786), the Qdrant provider, the Milvus provider, the InfluxDB provider, the Oxia provider, the Databend provider, the S3 provider, the Kubernetes provider, the MQTT provider (#1635), the BigQuery provider, the Firestore provider, the RabbitMQ provider, the Snowflake provider, the OPC UA provider (#1677), the MTConnect provider (#1722), the Modbus provider (#1723), the NETCONF provider (#1724) and the SNMP provider (#1721) merged after it, so render the `PKGBUILD` with `scripts/render-aur-pkgbuild.mjs` for the release that carries all twenty, regenerate `.SRCINFO` from that render with `makepkg --printsrcinfo > .SRCINFO`, since the script writes the `PKGBUILD` alone, and push both, with that version in the commit message. +The files here name forty-two engines and pin 0.17.0, which ships eighteen, because the etcd provider (#1089), the Neo4j provider, the Db2 LUW provider (#786), the Qdrant provider, the Milvus provider, the InfluxDB provider, the Oxia provider, the Databend provider, the S3 provider, the Kubernetes provider, the MQTT provider (#1635), the BigQuery provider, the Firestore provider, the RabbitMQ provider, the Snowflake provider, the OPC UA provider (#1677), the MTConnect provider (#1722), the Modbus provider (#1723), the NETCONF provider (#1724), the SNMP provider (#1721) and the Weaviate provider (#1566) merged after it, so render the `PKGBUILD` with `scripts/render-aur-pkgbuild.mjs` for the release that carries all twenty-one, regenerate `.SRCINFO` from that render with `makepkg --printsrcinfo > .SRCINFO`, since the script writes the `PKGBUILD` alone, and push both, with that version in the commit message. Then set the `aur` channel to `status: live` in `distribution/channels.yaml` and add the key as the `AUR_SSH_PRIVATE_KEY` repository secret. diff --git a/packaging/chocolatey/libredb-studio.nuspec.tmpl b/packaging/chocolatey/libredb-studio.nuspec.tmpl index 73fa186326..1eda157294 100644 --- a/packaging/chocolatey/libredb-studio.nuspec.tmpl +++ b/packaging/chocolatey/libredb-studio.nuspec.tmpl @@ -34,7 +34,7 @@ engines instead - the description below is the exhaustive list. --> Web-based SQL IDE for PostgreSQL, MySQL, SQL Server, Oracle, MongoDB, Redis, ClickHouse, Cassandra, Elasticsearch and more, with AI query assistance. Neo4j (read-only)
    • Milvus (read-only, with admin Load and Release)
    • Qdrant (read-only)
    • +
    • Weaviate (read-only)
    • Oxia (read-only)
    • S3-compatible object storage (read-only)
    • Kubernetes (read-only)
    • diff --git a/packaging/flatpark/org.libredb.Studio.desktop b/packaging/flatpark/org.libredb.Studio.desktop index cd098ba2d8..6e9a70334e 100644 --- a/packaging/flatpark/org.libredb.Studio.desktop +++ b/packaging/flatpark/org.libredb.Studio.desktop @@ -7,6 +7,6 @@ Exec=libredb-studio Icon=org.libredb.Studio Terminal=false Categories=Development;Database; -Keywords=SQL;Database;PostgreSQL;MySQL;SQLite;libSQL;Turso;DuckDB;MongoDB;Redis;Oracle;Db2;SQLServer;ClickHouse;Couchbase;Druid;Elasticsearch;OpenSearch;Trino;Databend;Spark;Cassandra;Prometheus;PromQL;InfluxDB;InfluxQL;Kafka;MQTT;RabbitMQ;AMQP;OPCUA;OPC-UA;etcd;Neo4j;Cypher;Milvus;Qdrant;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;Query; +Keywords=SQL;Database;PostgreSQL;MySQL;SQLite;libSQL;Turso;DuckDB;MongoDB;Redis;Oracle;Db2;SQLServer;ClickHouse;Couchbase;Druid;Elasticsearch;OpenSearch;Trino;Databend;Spark;Cassandra;Prometheus;PromQL;InfluxDB;InfluxQL;Kafka;MQTT;RabbitMQ;AMQP;OPCUA;OPC-UA;etcd;Neo4j;Cypher;Milvus;Qdrant;Weaviate;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;Query; StartupNotify=true StartupWMClass=libredb-studio-desktop diff --git a/packaging/flatpark/org.libredb.Studio.metainfo.xml b/packaging/flatpark/org.libredb.Studio.metainfo.xml index da458eefe0..3a1058e791 100644 --- a/packaging/flatpark/org.libredb.Studio.metainfo.xml +++ b/packaging/flatpark/org.libredb.Studio.metainfo.xml @@ -67,6 +67,7 @@
    • Neo4j (read-only)
    • Milvus (read-only, with admin Load and Release)
    • Qdrant (read-only)
    • +
    • Weaviate (read-only)
    • Oxia (read-only)
    • S3-compatible object storage (read-only)
    • Kubernetes (read-only)
    • diff --git a/packaging/linux/nfpm.yaml b/packaging/linux/nfpm.yaml index 8ea31efb15..38a2e10452 100644 --- a/packaging/linux/nfpm.yaml +++ b/packaging/linux/nfpm.yaml @@ -23,10 +23,10 @@ section: database priority: optional maintainer: cevheri description: | - Web-based SQL IDE for forty-one engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, + Web-based SQL IDE for forty-two engines - PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, Firestore, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, BigQuery, Snowflake, Apache Spark, Apache Cassandra, Prometheus, - InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - with AI query assistance. + InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B - with AI query assistance. Ships the standalone Next.js server with a bundled private Node.js runtime (no external dependencies) and a systemd unit (libredb-studio) serving the app on port 3000; enable it with diff --git a/packaging/winget/LibreDB.Studio.locale.en-US.yaml.tmpl b/packaging/winget/LibreDB.Studio.locale.en-US.yaml.tmpl index 9da3032bf1..24b5370c89 100644 --- a/packaging/winget/LibreDB.Studio.locale.en-US.yaml.tmpl +++ b/packaging/winget/LibreDB.Studio.locale.en-US.yaml.tmpl @@ -22,7 +22,7 @@ Description: |- LibreDB Studio is an open-source, web-based SQL IDE for cloud-native teams. It connects to PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, - Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect and Modbus, and ships a Monaco-powered editor with AI query + Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ, OPC UA, MTConnect and Modbus, and ships a Monaco-powered editor with AI query assistance, schema browsing, ER diagrams, charts, and import/export tooling. This package installs the standalone server with a bundled Node.js runtime; run `libredb-studio` and open http://127.0.0.1:3000 - the first run prints diff --git a/playwright.config.ts b/playwright.config.ts index 9dcf0ec270..b69871c2fd 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -8,7 +8,7 @@ import { LAUNCH_E2E_ENV } from "./e2e/helpers/launch-token"; // Override one with its variable when that port is occupied by another instance. const port = Number(process.env.E2E_PORT ?? 3000); -// offline-editor.spec.ts, the kafka, etcd, neo4j, milvus and qdrant provider specs, the influxdb +// offline-editor.spec.ts, the kafka, etcd, neo4j, milvus, qdrant and weaviate provider specs, the influxdb // providers spec and the oxia, databend, snowflake, spark, s3, kubernetes, rabbitmq and mqtt provider specs get a second server // process on its own port - see the projects and the webServer array below for why. Override with // E2E_OFFLINE_PORT under the same collision circumstances as E2E_PORT. @@ -68,12 +68,12 @@ export default defineConfig({ { name: "chromium", use: { ...devices["Desktop Chrome"] }, - // offline-editor.spec.ts, the kafka, etcd, neo4j, milvus and qdrant provider specs, the influxdb providers + // offline-editor.spec.ts, the kafka, etcd, neo4j, milvus, qdrant and weaviate provider specs, the influxdb providers // spec, the oxia, databend, snowflake, spark, s3, kubernetes, rabbitmq and mqtt provider specs and the firestore dialog spec // run under their own projects below, against the second server, passkey.spec.ts against the third, // launch.spec.ts against the fourth and the firestore browse spec against the fifth. testIgnore: - /(?:offline-editor|base-path|kafka-provider|etcd-provider|neo4j-provider|milvus-provider|qdrant-provider|influxdb-providers|mtconnect-provider|modbus-provider|oxia-provider|databend-provider|snowflake-provider|spark-provider|s3-provider|kubernetes-provider|firestore-connection|firestore-provider|rabbitmq-provider|mqtt-provider|passkey|launch)\.spec\.ts/, + /(?:offline-editor|base-path|kafka-provider|etcd-provider|neo4j-provider|milvus-provider|qdrant-provider|weaviate-provider|influxdb-providers|mtconnect-provider|modbus-provider|oxia-provider|databend-provider|snowflake-provider|spark-provider|s3-provider|kubernetes-provider|firestore-connection|firestore-provider|rabbitmq-provider|mqtt-provider|passkey|launch)\.spec\.ts/, }, { // Every other spec in this suite signs in as the same shared user@libredb.org account @@ -145,6 +145,13 @@ export default defineConfig({ use: { ...devices["Desktop Chrome"], baseURL: `http://localhost:${offlinePort}` }, testMatch: /qdrant-provider\.spec\.ts/, }, + { + // weaviate-provider.spec.ts drives Test Connection too (one call, for the refusal it asserts), so it takes the + // second server for the reason kafka-provider.spec.ts does. + name: "chromium-weaviate", + use: { ...devices["Desktop Chrome"], baseURL: `http://localhost:${offlinePort}` }, + testMatch: /weaviate-provider\.spec\.ts/, + }, { // influxdb-providers.spec.ts drives Test Connection too (two calls, one refusal per type it asserts), so it takes // the second server for the reason kafka-provider.spec.ts does. diff --git a/portainer-template.json b/portainer-template.json index 83dd97901a..cd73c93da6 100644 --- a/portainer-template.json +++ b/portainer-template.json @@ -2,7 +2,7 @@ "type": 1, "title": "LibreDB Studio", "name": "libredb-studio", -"description": "Self-hosted database IDE you use from a browser, covering forty-one engines - PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra, Elasticsearch and more - with a schema browser and query history on all of them, and ER diagrams and EXPLAIN plans wherever the engine declares keys or returns a plan. Source: https://github.com/libredb/libredb-studio", +"description": "Self-hosted database IDE you use from a browser, covering forty-two engines - PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra, Elasticsearch and more - with a schema browser and query history on all of them, and ER diagrams and EXPLAIN plans wherever the engine declares keys or returns a plan. Source: https://github.com/libredb/libredb-studio", "categories": [ "Database", "Tools", diff --git a/scripts/security-check.mjs b/scripts/security-check.mjs index 090fb3306d..dadbd8f866 100644 --- a/scripts/security-check.mjs +++ b/scripts/security-check.mjs @@ -91,6 +91,7 @@ export const PROGRAMME_CONTROL_IDS = [ "3.22", "3.23", "3.24", + "3.25", ]; export const STATUSES = new Set(["Implemented", "Partial", "Not implemented"]); diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 3909a74317..9c020af741 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -37,7 +37,7 @@ description: | Web-based SQL IDE for PostgreSQL, MySQL, SQLite, libSQL, DuckDB, Oracle, Db2 LUW, SQL Server, MongoDB, Redis, Couchbase, ClickHouse, Apache Druid, Elasticsearch, OpenSearch, Trino, Databend, Snowflake, Apache Spark, Apache Cassandra, Prometheus, - InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Oxia, S3-compatible object storage, + InfluxDB (InfluxQL), InfluxDB 3 (SQL), Apache Kafka, etcd, Neo4j, Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, MQTT, RabbitMQ and OPC UA with AI query assistance. Installing the snap starts a background service that serves the app on diff --git a/src/components/QueryEditor.tsx b/src/components/QueryEditor.tsx index f834bef2cb..43c7098179 100644 --- a/src/components/QueryEditor.tsx +++ b/src/components/QueryEditor.tsx @@ -97,6 +97,7 @@ interface QueryEditorProps { | "graph-cypher" | "milvus" | "qdrant" + | "weaviate" | "influxql" | "oxia" | "s3" diff --git a/src/components/agent/AnswerCard.tsx b/src/components/agent/AnswerCard.tsx index 30a31a0e9d..d96cae7fa6 100644 --- a/src/components/agent/AnswerCard.tsx +++ b/src/components/agent/AnswerCard.tsx @@ -122,6 +122,7 @@ type StatementLanguage = | "graph-cypher" | "milvus" | "qdrant" + | "weaviate" | "influxql" | "oxia" | "s3" @@ -178,6 +179,12 @@ type StatementLanguage = * "not checked" chip, which rules out amber itself, yellow and orange, and red is ruled out as a failure hue. Of the * declared `-alt` steps left, pink's stands furthest from every status hue and every other language here in both * palettes (0.062 in OKLab from Qdrant's pink, its nearest), measured. + * + * Weaviate takes lime's `-alt` step (#1566): no guard here reads a Weaviate request, so its draft stands beside the + * amber "not checked" chip, which rules out amber itself, yellow and orange, and red is ruled out as a failure hue. Of + * the chromatic declared steps left, lime-alt stands furthest from every status hue and every other language here in + * both palettes (0.0608 in OKLab from InfluxQL's green, its nearest, in light), measured; the greys mauve and taupe + * stand further, but no language here has taken a grey, and a grey border reads as no accent. */ const LANGUAGE_ACCENTS: Readonly> = Object.freeze({ sql: "border-hue-blue/40", @@ -189,6 +196,7 @@ const LANGUAGE_ACCENTS: Readonly> = Object.fre "graph-cypher": "border-hue-purple/40", milvus: "border-hue-teal/40", qdrant: "border-hue-pink/40", + weaviate: "border-hue-lime-alt/40", influxql: "border-hue-green/40", oxia: "border-hue-purple-alt/40", s3: "border-hue-indigo-alt/40", diff --git a/src/components/icons/db-icons.tsx b/src/components/icons/db-icons.tsx index 0af63e5639..abfee56d81 100644 --- a/src/components/icons/db-icons.tsx +++ b/src/components/icons/db-icons.tsx @@ -582,6 +582,31 @@ export const QdrantIcon: React.FC = ({ className, ...props }) => ( ); +/** + * Weaviate: a mark drawn for Studio, never the project's logo or any vendor asset (#1566). + * + * Three objects at the corners of a hexagon, joined through its centre: a collection of objects linked by their + * vectors and cross-references, at the house weight with no fill, identifiable at the 14px the connection list draws. + */ +export const WeaviateIcon: React.FC = ({ className, ...props }) => ( + + + + + + + +); + /** * InfluxDB: a mark drawn for Studio, never InfluxData's logo or any vendor asset (InfluxDB spec E19), shared by the * InfluxQL and the SQL connection type. diff --git a/src/lib/agent/agent-manifest.ts b/src/lib/agent/agent-manifest.ts index ad82e5d8c2..a03b87648f 100644 --- a/src/lib/agent/agent-manifest.ts +++ b/src/lib/agent/agent-manifest.ts @@ -51,6 +51,7 @@ export const AGENT_STATEMENT_LANGUAGE = Object.freeze({ neo4j: null, milvus: null, qdrant: null, + weaviate: null, influxdb: null, influxdb3: null, oxia: null, diff --git a/src/lib/db-showcase.ts b/src/lib/db-showcase.ts index 7528b921aa..683836bcc2 100644 --- a/src/lib/db-showcase.ts +++ b/src/lib/db-showcase.ts @@ -112,30 +112,33 @@ export const SHOWCASE_RANK: Record = { // Behind etcd and ahead of the embedded store: libSQL is the name on this page an // evaluator is least likely to have met, but it is a product name (Turso's server) // rather than our own, so it goes ahead of `libredb`. - libsql: 34, + // Behind Spark and ahead of libSQL (#1566): the third vector database on this page, after Milvus and Qdrant, and + // the newest name, so only libSQL, the embedded store and the industrial and network names after it move. + weaviate: 34, + libsql: 35, // Last of the databases on purpose: the embedded store is the least recognisable database name here. It is // still shown - it is a shipped provider with a doc (docs/providers/libredb.md), an // icon and a slot in the connection picker, so omitting it would make the login page // contradict the app (issue #425, step 2). - libredb: 35, - // Last (rank 36), behind the embedded store: a plant's address space is the least recognisable name + libredb: 36, + // Last (rank 37), behind the embedded store: a plant's address space is the least recognisable name // on a page of databases, so no existing engine moves for it (#1677). - opcua: 36, - // Last (rank 37), behind the address space: a machine tool's agent is a narrower name still, so nothing + opcua: 37, + // Last (rank 38), behind the address space: a machine tool's agent is a narrower name still, so nothing // above it moves for it either (#1722). - mtconnect: 37, - // Last (rank 38): a device's registers are narrower still, and a map the user writes is the only + mtconnect: 38, + // Last (rank 39): a device's registers are narrower still, and a map the user writes is the only // thing that names them, so nothing above it moves for this one either (#1723). - modbus: 38, - // Rank 39, behind the device's registers: a device's configuration tree is a narrower name still, + modbus: 39, + // Rank 40, behind the device's registers: a device's configuration tree is a narrower name still, // and the people who know it are network engineers rather than the readers a page of databases is // written for, so nothing above it moves for this one either (#1724). - netconf: 39, - // Last (rank 40), behind the configuration tree: the three letters are an acronym a reader + netconf: 40, + // Last (rank 41), behind the configuration tree: the three letters are an acronym a reader // either knows from managing networks or does not know at all, and the page is read by people // who came for databases (#1721). - snmp: 40, - // Last (rank 41), behind the agent's object tree: the name on the box is a specification's rather + snmp: 41, + // Last (rank 42), behind the agent's object tree: the name on the box is a specification's rather // than a product's, so a reader scanning the login page is least likely to arrive already knowing // it (#1720). THE RANK MOVES WITH THE BASE AND THE SENTENCE WITH IT: this entry has been written // against five trees now, whose last engine was in turn NETCONF, MTConnect, Modbus, NETCONF again @@ -143,7 +146,7 @@ export const SHOWCASE_RANK: Record = { // already taken by the time this branch rebased onto them - and the census that covers 0..N-1 is // what said so, all four times. Nothing else would: a duplicate rank only reorders two engines on // the page, so there is no failure to notice and no user to report it. - sparkplug: 41, + sparkplug: 42, }; /** diff --git a/src/lib/db-ui-config.ts b/src/lib/db-ui-config.ts index 5e1fc2e5ba..1317b7d89d 100644 --- a/src/lib/db-ui-config.ts +++ b/src/lib/db-ui-config.ts @@ -29,6 +29,7 @@ import { Db2Icon, Neo4jIcon, QdrantIcon, + WeaviateIcon, MilvusIcon, InfluxDBIcon, OxiaIcon, @@ -165,6 +166,11 @@ export const DB_UI_CONFIG: { // clears the separation test, which is why `rose` joined IDENTITY_ALTS in tests/unit/theme-accent-contrast.test.ts // with this entry, as `fuchsia` did with Neo4j's. qdrant: branded(CONNECTION_FORM.qdrant, QdrantIcon, "text-hue-rose-alt"), + // A mark drawn for Studio, never the vendor's logo (#1566). A NEW hue, as for Sparkplug's `olive`: every base hue, + // every `-alt` step and every grey theme.css declared was an engine's, so the palette gains `zinc`. Measured, not + // chosen: `zinc-900` light and `zinc-400` dark leave both closest identity pairs where they were (theme.css says the + // figures, tests/unit/theme-accent-contrast.test.ts holds them). + weaviate: branded(CONNECTION_FORM.weaviate, WeaviateIcon, "text-hue-zinc"), // A generic time-series mark drawn for Studio, never InfluxData's logo (InfluxDB spec E19), shared by both types. // `hue-purple` is Db2's; its `-alt` step is a second identity only because it clears the separation test, which // is why `purple` joined IDENTITY_ALTS in tests/unit/theme-accent-contrast.test.ts with this entry. diff --git a/src/lib/db/compatibility.ts b/src/lib/db/compatibility.ts index 7d09021fa6..56eb55bd88 100644 --- a/src/lib/db/compatibility.ts +++ b/src/lib/db/compatibility.ts @@ -92,6 +92,9 @@ const SHIPPED: Readonly> = Object.freeze({ // Qdrant (vector-family spec 6): its own provider, doc and integration test, a member of the `vector/` family. // Qdrant Cloud speaks the same API and is recorded nowhere until a test cluster passes gate 4 (vector-family spec 6.2). qdrant: true, + // Weaviate (#1566): its own provider, doc and integration test, the third member of the `vector/` family. Weaviate + // Cloud and DigitalOcean Managed Weaviate are recorded nowhere until a test cluster passes gate 4 (spec 8). + weaviate: true, // InfluxDB (InfluxDB spec I2): its own provider class, doc and integration test; the first of two type-ids served by // `timeseries/influxdb/`, one per query language. InfluxDB Cloud, Clustered and Enterprise 1.x are claimed nowhere // until a gate-4 probe measures one. @@ -199,6 +202,8 @@ const EXTERNAL: Readonly> = Object.freeze({ milvus: true, // A server or cluster the user already runs, reached over Qdrant's REST API. qdrant: true, + // A server or cluster the user already runs, reached over Weaviate's REST API (and GraphQL below 1.39.7). + weaviate: true, // A server the user already runs, reached over InfluxDB's v1 HTTP API. influxdb: true, // A server the user already runs, reached over InfluxDB 3's HTTP SQL API. @@ -298,6 +303,9 @@ export const READ_ONLY_ENFORCED: Record = Object.freeze({ // Every v1 console request is a read and the provider has no maintenance operation, and while the mode holds it // refuses every route that is not a read before any request (vector-family spec 4.4). qdrant: true, + // As Qdrant (#1566 spec 3.5): every console request is a read, the provider has no maintenance operation, and it + // refuses every route that is not a read, and every request that would wake a cold tenant, before any request. + weaviate: true, // Read-only whatever the flag says: on 1.x and 2.x the InfluxQL lexer policy (`influxql-policy.ts`) is the only // boundary between a Studio user and `DROP DATABASE`, so it refuses every statement that is not one `SELECT`, `SHOW` // or `EXPLAIN` before any request; the route table reaches no write endpoint. @@ -394,6 +402,7 @@ export const READS_FILE_ACCESS_POSTURE: Readonly> neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, @@ -455,6 +464,7 @@ export const SINGLE_WRITER_FILE: Readonly> = Objec neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, @@ -520,6 +530,9 @@ export const MCP_EXPOSABLE: Readonly> = Object.fre // Offered for the two metadata tools, carrying names and types only (vector-family spec 4.4); `run_read_query` does not // serve it, because the provider implements no `queryReadOnly`. qdrant: true, + // As Milvus and Qdrant (#1566 spec 3.5): offered for the two metadata tools; tenant names are a collection's detail, + // listed in its Source up to 1,024 as Milvus lists partitions, and `run_read_query` does not serve it. + weaviate: true, // Both offered for the two metadata tools (InfluxDB spec I13); `run_read_query` does not serve either, because // neither provider implements `queryReadOnly`. influxdb: true, @@ -605,6 +618,7 @@ export const CONNECTION_FORM_URI_MODE: Readonly> = neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, @@ -671,6 +685,7 @@ export const CONNECTION_STRING_ACCEPTED: Readonly> neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, @@ -733,6 +748,7 @@ export const OPENS_LOCAL_FILE: Readonly> = Object. neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, @@ -793,6 +809,7 @@ export const OPENS_SERVER_LEVEL_WITHOUT_DATABASE: Readonly> = Obj sparkplug: SPARKPLUG_EXECUTION_UI, sqlite: SQLITE_EXECUTION_UI, trino: TRINO_EXECUTION_UI, + weaviate: WEAVIATE_EXECUTION_UI, }); /** diff --git a/src/lib/db/factory.ts b/src/lib/db/factory.ts index 5322475716..3287abce22 100644 --- a/src/lib/db/factory.ts +++ b/src/lib/db/factory.ts @@ -460,6 +460,13 @@ export async function createDatabaseProvider( return new QdrantProvider(connection, options, execution); } + case "weaviate": { + // The explicit /index specifier keeps this dynamic import statically analysable. The execution context + // rides along, so an execution profile opens it read-only, as Qdrant's does. + const { WeaviateProvider } = await import("./providers/vector/weaviate/index"); + return new WeaviateProvider(connection, options, execution); + } + // Object storage - dynamically imported case "s3": { // The explicit /index specifier keeps this dynamic import statically analysable. The execution context rides @@ -568,7 +575,7 @@ export async function createDatabaseProvider( // This list is NOT type-checked against the union - a new case above with no // entry here is silent - so it is kept in the same order as the cases and // tests/isolated/factory.test.ts pins individual names in it by regex. - `Unknown database type: ${connection.type}. Supported types: postgres, mysql, sqlite, duckdb, libsql, oracle, db2, mssql, clickhouse, druid, trino, databend, bigquery, snowflake, spark, cassandra, elasticsearch, opensearch, mongodb, couchbase, firestore, redis, etcd, oxia, prometheus, influxdb, influxdb3, kafka, neo4j, milvus, qdrant, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb`, + `Unknown database type: ${connection.type}. Supported types: postgres, mysql, sqlite, duckdb, libsql, oracle, db2, mssql, clickhouse, druid, trino, databend, bigquery, snowflake, spark, cassandra, elasticsearch, opensearch, mongodb, couchbase, firestore, redis, etcd, oxia, prometheus, influxdb, influxdb3, kafka, neo4j, milvus, qdrant, weaviate, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb`, connection.type, ); } diff --git a/src/lib/db/migration-ddl/index.ts b/src/lib/db/migration-ddl/index.ts index c853711f2f..186ff76e23 100644 --- a/src/lib/db/migration-ddl/index.ts +++ b/src/lib/db/migration-ddl/index.ts @@ -44,6 +44,7 @@ import { INFLUXDB3_MIGRATION_DDL } from "@/lib/db/providers/timeseries/influxdb/ import { PROMETHEUS_MIGRATION_DDL } from "@/lib/db/providers/timeseries/prometheus/migration-ddl"; import { MILVUS_MIGRATION_DDL } from "@/lib/db/providers/vector/milvus/migration-ddl"; import { QDRANT_MIGRATION_DDL } from "@/lib/db/providers/vector/qdrant/migration-ddl"; +import { WEAVIATE_MIGRATION_DDL } from "@/lib/db/providers/vector/weaviate/migration-ddl"; import type { DatabaseType } from "@/lib/types"; import { NO_CONNECTION_DIALECT, NO_CONNECTION_MIGRATION_DDL } from "./no-connection"; import type { MigrationDdlSpec } from "./types"; @@ -92,6 +93,7 @@ export const MIGRATION_DDL: Readonly> = O sparkplug: SPARKPLUG_MIGRATION_DDL, sqlite: SQLITE_MIGRATION_DDL, trino: TRINO_MIGRATION_DDL, + weaviate: WEAVIATE_MIGRATION_DDL, }); /** diff --git a/src/lib/db/providers/vector/weaviate/client.ts b/src/lib/db/providers/vector/weaviate/client.ts new file mode 100644 index 0000000000..d9d9554f7d --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/client.ts @@ -0,0 +1,120 @@ +/** + * The Weaviate provider's client seam (#1566 spec 3.1): the operations the provider sends, the request and the + * answer that cross the seam, the client every consumer is handed a slice of, and the error an answer is classified + * into. No I/O: `rest-client.ts` is the one implementation, and the only file that builds a path. + * + * A consumer never holds the whole client. It receives a `WeaviateSend` typed to exactly the operations it calls, + * so a module that reads the schema cannot send a search, and a call-site test over a recording client holds the + * slices at run time. + */ + +/** + * Every operation the client sends: the console's routes (`routes.ts`) first, in their table order, then the two + * the console never names, the readiness probe of the health surface and the GraphQL read the encoder writes for a + * server that serves no REST search (spec 3.3). + */ +export const WEAVIATE_OPS = [ + "meta", + "schema", + "collection", + "shards", + "tenants", + "tenant", + "aliases", + "alias", + "nodes", + "collection_nodes", + "objects", + "object", + "search_bm25", + "search_hybrid", + "search_near_vector", + "search_near_object", + "aggregate", + "ready", + "graphql", +] as const; + +export type WeaviateOp = (typeof WEAVIATE_OPS)[number]; + +/** The operations a console request may name: every operation but the two the provider writes itself. */ +export type WeaviateConsoleOp = Exclude; + +/** The four search routes and the aggregate route: the operations that run over REST or GraphQL (spec 3.3). */ +export type WeaviateSearchOp = "search_bm25" | "search_hybrid" | "search_near_vector" | "search_near_object"; +export type WeaviateEncodedOp = WeaviateSearchOp | "aggregate"; + +export interface WeaviateRequest { + readonly op: WeaviateOp; + /** Path parameters, already checked by kind. */ + readonly params: Readonly>; + /** Only keys the route declares. */ + readonly query: Readonly>; + /** JSON text written by toJsonText or JSON.stringify of a value Studio built, never a user's text as typed. */ + readonly body?: string; +} + +export interface WeaviateAnswer { + readonly status: number; + readonly contentType: string | null; + /** The Retry-After header as received, cut to 64 characters; null when absent. */ + readonly retryAfter: string | null; + readonly text: string; +} + +export interface WeaviateClient { + send(request: WeaviateRequest, signal: AbortSignal): Promise; + close(): void; +} + +/** The slice of the client a consumer is handed: `send`, narrowed to the operations it calls. */ +export type WeaviateSend = ( + request: WeaviateRequest & { readonly op: Ops }, + signal: AbortSignal, +) => Promise; + +/** One route as the path builder takes it: the method, the path template with `{name}` parameters, the query keys. */ +export interface WeaviateRouteTemplate { + readonly method: "GET" | "POST"; + readonly path: string; + readonly query: readonly string[]; +} + +export type WeaviateRouteTemplates = Readonly>; + +/** + * What an answer that is not a success is, read from its status and the server's words (spec 5.6). A GraphQL answer + * that carries `errors` is one too, whatever its status, because GraphQL answers its refusals under HTTP 200. + */ +export type WeaviateErrorCategory = + | "unauthenticated" // 401: no key, or a key or token the server does not accept + | "forbidden" // 403, an RBAC refusal naming the action + | "graphql-scope" // the GraphQL introspection refusal of a role scoped to some collections + | "collection-not-found" // 404 "could not find collection", or GraphQL "class ... does not exist" + | "route-absent" // the router's 404 "path ... was not found": this server version has no such route + | "not-found" // any other 404: an object or a tenant + | "tenant-not-active" // 422 "tenant not active" + | "rest-search-disabled" // 422 "rest search api is experimental and not enabled" + | "graphql-disabled" // 422 "graphql api is disabled" + | "result-limit" // 400 past QUERY_MAXIMUM_RESULTS + | "tls-required" // 400 from the TLS listener: plain HTTP sent to a port that speaks TLS + | "input" // any other 400 or 422, and a GraphQL error no row above reads + | "rate-limited" // 429 + | "server" // any other 5xx but 503 + | "unavailable" // 503 + | "unexpected-status"; // an answer no row above reads + +export class WeaviateError extends Error { + constructor( + readonly category: WeaviateErrorCategory, + /** The server's own words: the `message` of its error body, else the body. Never shown before serverText. */ + readonly detail: string, + readonly status: number, + /** The Retry-After header of a 429 as received; null when absent, and on every other category. */ + readonly retryAfter: string | null = null, + ) { + super(`Weaviate answered HTTP ${status} (${category})`); + this.name = "WeaviateError"; + Object.setPrototypeOf(this, WeaviateError.prototype); + } +} diff --git a/src/lib/db/providers/vector/weaviate/connection-options.ts b/src/lib/db/providers/vector/weaviate/connection-options.ts new file mode 100644 index 0000000000..da45857639 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/connection-options.ts @@ -0,0 +1,200 @@ +/** + * Maps a connection to the options the REST client opens its transport with (#1566 spec 6.1), after the endpoint + * check (W1), the token check, the TLS mapping, the plaintext rule (W2) and the read-only seed stage. No socket + * opens here: every refusal is a DatabaseConfigError raised before any client is built, and none repeats the value + * it refuses. + * + * Every field read is checked before it is used, because a connection sent to the API arrives as the caller wrote + * it: a field that is not the type `DatabaseConnection` declares is refused, naming the field. A null in a text + * field reads as absent, as does an empty string, which the dialog writes for a blank box; `readOnly` must be true + * or false when present, as Qdrant's. + * + * Weaviate takes an API key and an OIDC access token alike as a bearer token, so the secret sits in the password + * and travels as one `Authorization: Bearer` header, set once per connection, never in a URL or a query string. No + * other header is ever set (spec W3): a model-provider key such as `X-OpenAI-Api-Key` cannot be sent. REST and + * GraphQL share the one port dialled; gRPC (50051) never is. + * + * The parameter is named `config` on purpose: tests/unit/lib/db-ui-config.test.ts finds which addressing fields a + * provider reads by the `config.` pattern, and this file reads `config.user` and `config.password` as written. + */ +import { readOnlySeedRefusal } from "@/lib/db/credential-warnings"; +import { DatabaseConfigError } from "@/lib/db/errors"; +import { + type HttpOrigin, + httpOrigin, + plaintextSecretRefusal, + validateHost, + validatePort, +} from "@/lib/db/http/endpoint"; +import { type NodeTlsMaterial, nodeTlsMaterial } from "@/lib/db/http/node-transport"; +import { secretForms } from "@/lib/db/utils/server-text"; +import { + type DatabaseConnection, + type DatabaseType, + type SSHTunnelConfig, + TUNNEL_FAR_END, + type TunnelFarEnd, + type WithTunnelFarEnd, +} from "@/lib/types"; + +/** Where a read-only mode was set; the provider words its refusal by it. */ +export type WeaviateReadOnlySource = "connection" | "seed" | "execution-profile"; + +export interface WeaviateConnectionOptions { + /** What is dialled: the validated host and port, the local forward under a tunnel; `https` exactly when TLS is on. */ + readonly origin: HttpOrigin; + /** The endpoint as configured (the far end under a tunnel), an IPv6 literal without brackets; what sentences name. */ + readonly endpoint: { readonly host: string; readonly port: number }; + /** The SSL / TLS panel as the transport takes it; null for plaintext. */ + readonly tls: NodeTlsMaterial | null; + /** The headers set once per connection: the one `Authorization` header, or none. */ + readonly headers: Readonly>; + /** The provider's in-flight bound, which is the transport's socket bound. */ + readonly maxSockets: number; + /** The most bytes one response may hold. */ + readonly responseCapBytes: number; + readonly readOnly?: WeaviateReadOnlySource; + /** The connection's query timeout, which caps every request's deadline. */ + readonly callTimeoutMs: number; + /** `secretForms` of the secret: empty with no secret. */ + readonly secretForms: readonly string[]; +} + +/** REST and GraphQL, with TLS or without; the only Weaviate port this provider dials. */ +export const WEAVIATE_DEFAULT_PORT = 8080; +/** The calls in flight for one provider, and so the sockets of its one Agent. */ +export const WEAVIATE_MAX_IN_FLIGHT = 4; +/** The transport's cap on one response: twice the 8 MiB conversion budget (spec W8). */ +export const WEAVIATE_RESPONSE_CAP_BYTES = 16 * 1024 * 1024; + +const PROVIDER: DatabaseType = "weaviate"; +const SECRET_LABEL = "API key or token"; +/** Printable ASCII: what a bearer header carries unchanged. A line break, a NUL, a tab or a non-ASCII character is refused. */ +const PRINTABLE_ASCII = /^[\x21-\x7E]+$/; +const MAX_QUERY_TIMEOUT_MS = 2_147_483_647; + +const USER_NOT_TAKEN = + "Weaviate takes no user name: clear the connection's user, and put the API key or OIDC access token in the password. Nothing was sent."; +const SECRET_NOT_PRINTABLE = + "The connection's password (the API key or token) holds a space, a line break, a NUL or another character outside printable ASCII; remove it. Nothing was sent."; +const TUNNEL_NOT_OPENED = + "This connection's SSH tunnel is on, but the connection arrived without its tunnel, so Weaviate was not dialled directly: the tunnel opens only when both Host and Port are set."; +const SEED_REFUSED = + "This read-only seed connection is refused with this credential, because the mode would promise a boundary the server does not keep; nothing was sent."; +const READ_ONLY_NOT_BOOLEAN = "readOnly must be true or false."; +const QUERY_TIMEOUT_RANGE = "Query timeout must be a whole number between 1 and 2147483647 milliseconds."; + +/** Throws DatabaseConfigError for every refusal of W1, W2 and the seed stage; never echoes a value. */ +export function buildWeaviateConnectionOptions( + config: DatabaseConnection & WithTunnelFarEnd, + context: { readonly executionReadOnly: boolean; readonly queryTimeout: number }, +): WeaviateConnectionOptions { + const farEnd = tunnelFarEnd(config); + const dialled = shared(() => httpOrigin("http", config.host, config.port ?? WEAVIATE_DEFAULT_PORT)); + const endpoint = + farEnd === undefined + ? { host: unbracketed(dialled.host), port: dialled.port } + : { host: unbracketed(shared(() => validateHost(farEnd.host))), port: shared(() => validatePort(farEnd.port)) }; + const secret = credential(config); + const tls = shared(() => nodeTlsMaterial(config.ssl, endpoint.host)); + const plaintext = plaintextSecretRefusal({ + host: endpoint.host, + tunnelled: farEnd !== undefined, + tls: tls !== null, + hasSecret: secret !== undefined, + secretLabel: SECRET_LABEL, + }); + if (plaintext !== undefined) throw configError(plaintext); + const readOnly = readOnlySource(config, context.executionReadOnly); + if (readOnly === "seed") seedStage(secret); + return { + origin: { scheme: tls === null ? "http" : "https", host: dialled.host, port: dialled.port }, + endpoint, + tls, + headers: secret === undefined ? {} : { authorization: `Bearer ${secret}` }, + maxSockets: WEAVIATE_MAX_IN_FLIGHT, + responseCapBytes: WEAVIATE_RESPONSE_CAP_BYTES, + ...(readOnly === undefined ? {} : { readOnly }), + callTimeoutMs: callTimeout(context.queryTimeout), + secretForms: secretForms(secret === undefined ? [] : [secret]), + }; +} + +function tunnelFarEnd(config: DatabaseConnection & WithTunnelFarEnd): TunnelFarEnd | undefined { + const tunnel = optionalObject(config.sshTunnel, "sshTunnel"); + const enabled = optionalBoolean(tunnel?.enabled, "sshTunnel.enabled") === true; + const farEnd = config[TUNNEL_FAR_END]; + if (enabled && farEnd === undefined) throw configError(TUNNEL_NOT_OPENED); + return farEnd; +} + +function unbracketed(host: string): string { + return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host; +} + +/** The shared validators refuse with a DatabaseConfigError that names no provider; re-raised as Weaviate's. */ +function shared(validate: () => T): T { + try { + return validate(); + } catch (error) { + throw configError((error as Error).message); + } +} + +/** The bearer token, or undefined with none. A user is refused, because Weaviate has none to send it as. */ +function credential(config: DatabaseConnection): string | undefined { + if (optionalText(config.user, "user") !== undefined) throw configError(USER_NOT_TAKEN); + const secret = optionalText(config.password, "password"); + if (secret !== undefined && !PRINTABLE_ASCII.test(secret)) throw configError(SECRET_NOT_PRINTABLE); + return secret; +} + +/** The resolution stage: a read-only seed whose resolved credential the record declares unsafe. */ +function seedStage(secret: string | undefined): void { + const refusal = readOnlySeedRefusal(PROVIDER, secret === undefined ? {} : { password: secret }); + if (refusal !== undefined) throw configError(`${refusal} ${SEED_REFUSED}`); +} + +/** The connection's own `readOnly` first (a seed's when it carries `seedId`), then the execution profile's. */ +function readOnlySource(config: DatabaseConnection, executionReadOnly: boolean): WeaviateReadOnlySource | undefined { + const readOnly: unknown = config.readOnly; + if (readOnly !== undefined && typeof readOnly !== "boolean") throw configError(READ_ONLY_NOT_BOOLEAN); + if (readOnly === true) { + const seedId = optionalText(config.seedId, "seedId"); + return seedId === undefined ? "connection" : "seed"; + } + return executionReadOnly ? "execution-profile" : undefined; +} + +function callTimeout(queryTimeout: number): number { + if (!Number.isInteger(queryTimeout) || queryTimeout < 1 || queryTimeout > MAX_QUERY_TIMEOUT_MS) { + throw configError(QUERY_TIMEOUT_RANGE); + } + return queryTimeout; +} + +function optionalObject(value: unknown, field: string): Partial> | undefined { + if (value === undefined || value === null) return undefined; + if (typeof value !== "object" || Array.isArray(value)) throw wrongType(field, "an object"); + return value as Partial>; +} + +function optionalText(value: unknown, field: string): string | undefined { + if (value === undefined || value === null || value === "") return undefined; + if (typeof value !== "string") throw wrongType(field, "a string"); + return value; +} + +function optionalBoolean(value: unknown, field: string): boolean | undefined { + if (value === undefined || value === null) return undefined; + if (typeof value !== "boolean") throw wrongType(field, "true or false"); + return value; +} + +function wrongType(field: string, expected: string): DatabaseConfigError { + return configError(`The connection's ${field} must be ${expected}; nothing was sent.`); +} + +function configError(message: string): DatabaseConfigError { + return new DatabaseConfigError(message, PROVIDER); +} diff --git a/src/lib/db/providers/vector/weaviate/connection-string.ts b/src/lib/db/providers/vector/weaviate/connection-string.ts new file mode 100644 index 0000000000..b459610410 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/connection-string.ts @@ -0,0 +1,8 @@ +import type { ConnectionStringSpec } from "@/lib/db/connection-string/types"; + +/** `weaviate`: no connection string scheme, no TLS read from a URL query, no seed load check. */ +export const WEAVIATE_CONNECTION_STRING: ConnectionStringSpec = { + scheme: null, + readTls: null, + validateSeed: null, +}; diff --git a/src/lib/db/providers/vector/weaviate/errors.ts b/src/lib/db/providers/vector/weaviate/errors.ts new file mode 100644 index 0000000000..9cbcb24ed2 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/errors.ts @@ -0,0 +1,299 @@ +/** + * The Weaviate error table (#1566 spec 5.6): what an answer that is not a success is, and the sentence a person + * reads for it and for a request that never completed. + * + * Two halves. `answerFailure` and `graphqlFailure` read an answer into a `WeaviateError` with a category, keeping + * the server's words as `detail`. `toProviderError` words that error, or the shared transport's, as one of the + * repository's error classes: Studio's sentence first, the server's words after it, and every server text passes + * `serverText` first, so a text that holds any form of the configured secret is withheld whole. + * + * Weaviate answers three error shapes, all measured on 1.37.4 and 1.40.2: `{"error":[{"message"}]}` from its + * handlers, `{"code","message"}` from the router for a path it does not serve, and `{"errors":[{"message"}]}` from + * GraphQL, under HTTP 200. Several 404s carry no body at all (a collection, an object, an alias or a tenant that + * does not exist), so the operation words what was not found. The status decides, the words refine it. + */ +import { + AuthenticationError, + ConnectionError, + DatabaseError, + QueryCancelledError, + QueryError, + TimeoutError, +} from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import { serverText } from "@/lib/db/utils/server-text"; +import type { DatabaseType } from "@/lib/types"; +import { type WeaviateAnswer, WeaviateError, type WeaviateErrorCategory, type WeaviateOp } from "./client"; + +const PROVIDER: DatabaseType = "weaviate"; + +/** The longest server text a sentence carries; a longer one is cut and says so. */ +const MAX_SERVER_TEXT = 2000; +/** An error body longer than this is never parsed: a refusal's body is a sentence, not a result. */ +const MAX_ERROR_BODY = 65_536; + +export interface WeaviateErrorContext { + /** `connect` while the provider's connect request runs, `request` after it. */ + readonly phase: "connect" | "request"; + readonly op: WeaviateOp; + /** The endpoint as configured: the far end under an SSH tunnel. */ + readonly endpoint: { readonly host: string; readonly port: number }; + readonly responseCapBytes: number; + readonly timeoutMs: number; + /** `secretForms` of the connection's secret. */ + readonly secretForms: readonly string[]; +} + +function messagesOf(value: unknown): readonly string[] { + if (!Array.isArray(value)) return []; + return value.flatMap((entry: unknown) => { + const message = + typeof entry === "object" && entry !== null ? (entry as { readonly message?: unknown }).message : undefined; + return typeof message === "string" ? [message] : []; + }); +} + +/** The server's own words in an answer: every `message` of its error body, else the body as text. */ +export function serverWords(text: string): string { + if (text.length <= MAX_ERROR_BODY) { + try { + const parsed: unknown = JSON.parse(text); + if (typeof parsed === "object" && parsed !== null) { + const body = parsed as { readonly error?: unknown; readonly errors?: unknown; readonly message?: unknown }; + const listed = [...messagesOf(body.error), ...messagesOf(body.errors)]; + if (listed.length > 0) return listed.join("; "); + if (typeof body.message === "string") return body.message; + if (typeof body.error === "string") return body.error; + } + } catch { + // Not JSON: a proxy's page, which is read as it is. + } + } + return text.trim(); +} + +const ROUTE_ABSENT = /^path \S+ was not found$/; +const GRAPHQL_SCOPE = "due to GraphQL introspection"; +const UNKNOWN_CLASS = /Cannot query field "[^"]*" on type "(?:GetObjectsObj|AggregateObjectsObj)"/; + +/** The category of words alone, for a GraphQL `errors` list or the body of a 4xx. */ +function wordsCategory(words: string): WeaviateErrorCategory | undefined { + if (words.includes("tenant not active")) return "tenant-not-active"; + if (words.includes("rest search api is experimental and not enabled")) return "rest-search-disabled"; + if (words.includes("graphql api is disabled")) return "graphql-disabled"; + if (words.includes(GRAPHQL_SCOPE)) return "graphql-scope"; + if (words.includes("could not find collection") || UNKNOWN_CLASS.test(words)) return "collection-not-found"; + if (words.includes("query maximum results exceeded")) return "result-limit"; + if (words.startsWith("Client sent an HTTP request to an HTTPS server")) return "tls-required"; + if (words.startsWith("rbac: authorization, forbidden action")) return "forbidden"; + return undefined; +} + +function categoryOf(status: number, words: string): WeaviateErrorCategory { + if (status === 401) return "unauthenticated"; + if (status === 403) return words.includes(GRAPHQL_SCOPE) ? "graphql-scope" : "forbidden"; + if (status === 404) { + if (ROUTE_ABSENT.test(words)) return "route-absent"; + return wordsCategory(words) === "collection-not-found" ? "collection-not-found" : "not-found"; + } + if (status === 429) return "rate-limited"; + if (status === 400 || status === 422) return wordsCategory(words) ?? "input"; + if (status === 503) return "unavailable"; + if (status >= 500) return "server"; + return "unexpected-status"; +} + +/** What an answer that is not a 2xx is, or undefined for a success. The answer's text is kept, never shown here. */ +export function answerFailure(answer: WeaviateAnswer): WeaviateError | undefined { + if (answer.status >= 200 && answer.status <= 299) return undefined; + const words = serverWords(answer.text); + const category = categoryOf(answer.status, words); + return new WeaviateError(category, words, answer.status, category === "rate-limited" ? answer.retryAfter : null); +} + +/** + * The failure a GraphQL answer carries in its `errors` list, whatever its status, or undefined where it holds none. + * GraphQL answers a refusal under HTTP 200 with `errors` beside `data` (spec A.4), so a 200 is not a success here. + */ +export function graphqlFailure(answer: WeaviateAnswer): WeaviateError | undefined { + const http = answerFailure(answer); + if (http !== undefined) return http; + let parsed: unknown; + try { + parsed = JSON.parse(answer.text); + } catch { + return new WeaviateError("unexpected-status", "", answer.status); + } + const errors = + typeof parsed === "object" && parsed !== null ? (parsed as { readonly errors?: unknown }).errors : undefined; + const messages = messagesOf(errors); + if (messages.length === 0) return undefined; + const words = messages.join("; "); + return new WeaviateError(wordsCategory(words) ?? "input", words, answer.status); +} + +const DELAY_SECONDS = /^\d{1,9}$/; + +/** The wait a Retry-After header names, in whole seconds, when it is 1 to 9 digits; undefined otherwise, never echoed. */ +export function retryAfterSeconds(retryAfter: string | null): number | undefined { + if (retryAfter === null || !DELAY_SECONDS.test(retryAfter)) return undefined; + return Number(retryAfter); +} + +/** The server's words after Studio's, withheld whole when they hold any form of the secret. */ +function after(detail: string, context: WeaviateErrorContext): string { + if (detail === "") return ""; + const text = serverText(detail, context.secretForms); + const shown = text.length > MAX_SERVER_TEXT ? `${text.slice(0, MAX_SERVER_TEXT)} (cut)` : text; + return ` (Weaviate: ${shown})`; +} + +function endpointOf(context: WeaviateErrorContext): string { + const { host, port } = context.endpoint; + return `${host.includes(":") ? `[${host}]` : host}:${port}`; +} + +function formatBytes(bytes: number): string { + if (bytes % (1024 * 1024) === 0) return `${bytes / (1024 * 1024)} MiB`; + if (bytes % 1024 === 0) return `${bytes / 1024} KiB`; + return `${bytes.toLocaleString("en-US")} bytes`; +} + +/** What a 404 with no words means, by the operation that met it. */ +const NOT_FOUND: Partial> = { + collection: "The collection does not exist or is not visible to this credential.", + shards: "The collection does not exist or is not visible to this credential.", + tenants: "The collection does not exist or is not visible to this credential.", + tenant: "The tenant does not exist in this collection.", + alias: "The alias does not exist.", + objects: "The collection does not exist or is not visible to this credential.", + object: "No object has this id in this collection.", + collection_nodes: "The collection does not exist or is not visible to this credential.", +}; + +function answerError(error: WeaviateError, context: WeaviateErrorContext): Error { + const words = after(error.detail, context); + switch (error.category) { + case "unauthenticated": + return new AuthenticationError(`Weaviate refused the API key or token.${words}`, PROVIDER); + case "forbidden": + return context.phase === "connect" + ? new AuthenticationError(`The credential is not allowed to read this server's meta.${words}`, PROVIDER) + : new QueryError(`The credential is not allowed to run this request.${words}`, PROVIDER); + case "graphql-scope": + return new QueryError( + "This credential's role is scoped to some collections, and Weaviate allows GraphQL only to a role that may read every collection, so this server version (below 1.39.7, which serves REST search) cannot run the search for it.", + PROVIDER, + ); + case "collection-not-found": + return new QueryError("The collection does not exist or is not visible to this credential.", PROVIDER); + case "route-absent": + return new QueryError(`This Weaviate server has no such route.${words}`, PROVIDER); + case "not-found": + return new QueryError( + error.detail === "" + ? (NOT_FOUND[context.op] ?? "Weaviate found nothing at the name or id the request gives.") + : `Weaviate found nothing at the name or id the request gives.${words}`, + PROVIDER, + ); + case "tenant-not-active": + return new QueryError( + `The tenant is not active, and Studio does not activate a tenant by reading it.${words}`, + PROVIDER, + ); + case "rest-search-disabled": + return new QueryError( + `This Weaviate server keeps its REST search behind EXPERIMENTAL_REST_SEARCH_ENABLED, and GraphQL is not available either.${words}`, + PROVIDER, + ); + case "graphql-disabled": + return new QueryError(`This Weaviate server has GraphQL disabled.${words}`, PROVIDER); + case "result-limit": + return new QueryError( + `The request asks for more objects than the server's QUERY_MAXIMUM_RESULTS.${words}`, + PROVIDER, + ); + case "tls-required": + return new ConnectionError( + `Weaviate at ${endpointOf(context)} speaks TLS on this port, and the connection sent plain HTTP: choose an SSL mode under SSL / TLS.`, + PROVIDER, + context.endpoint.host, + context.endpoint.port, + ); + case "input": + return new QueryError(`Weaviate did not accept the request as written.${words}`, PROVIDER); + case "rate-limited": { + const wait = retryAfterSeconds(error.retryAfter); + const again = wait === undefined ? "try again later" : `try again in ${wait} s`; + return new QueryError(`Weaviate rate-limited the request; ${again}. It was not sent again.${words}`, PROVIDER); + } + case "server": + return new QueryError(`Weaviate failed to run the request (HTTP ${error.status}).${words}`, PROVIDER); + case "unavailable": + return new ConnectionError( + `Weaviate is not ready to serve the request (HTTP ${error.status}).${words}`, + PROVIDER, + context.endpoint.host, + context.endpoint.port, + ); + case "unexpected-status": + return new QueryError(`Weaviate answered HTTP ${error.status}, which Studio does not read.${words}`, PROVIDER); + } +} + +function transportError(error: TransportError, context: WeaviateErrorContext): Error { + const { host, port } = context.endpoint; + const connection = (sentence: string) => new ConnectionError(sentence, PROVIDER, host, port); + switch (error.kind) { + case "timeout": + return new TimeoutError( + `The request to Weaviate did not finish within ${context.timeoutMs} ms, so Studio stopped waiting.`, + PROVIDER, + context.timeoutMs, + ); + case "unreachable": + return connection(error.message); + case "aborted": + return new QueryCancelledError("The request to Weaviate was cancelled.", PROVIDER); + case "too-large": + return new QueryError( + `Weaviate's answer is larger than the ${formatBytes(context.responseCapBytes)} Studio reads for one response, so it was not read. Ask for fewer objects, fewer properties, or no vectors.`, + PROVIDER, + ); + case "redirect": + return connection( + `Weaviate at ${endpointOf(context)} answered with a redirect, which Studio never follows. ${serverText(error.message, context.secretForms)}`, + ); + case "encoding": + return connection( + `Weaviate at ${endpointOf(context)} answered in an encoding Studio does not read. ${serverText(error.message, context.secretForms)}`, + ); + case "tls": + return connection( + `The TLS connection to Weaviate at ${endpointOf(context)} failed: check the SSL mode, the CA and the client certificate under SSL / TLS. ${error.message}`, + ); + case "network": + return connection( + `No complete answer arrived from Weaviate at ${endpointOf(context)}, and the request was not sent again. ${error.message}`, + ); + } +} + +/** + * What a person reads for a failure. A `WeaviateError` and a `TransportError` are worded by the table; any other + * error of the repository's own classes (a refusal raised before the wire) is returned as it is; anything else is a + * failure this provider did not expect, reported without its text. + */ +export function toProviderError(error: unknown, context: WeaviateErrorContext): Error { + if (error instanceof WeaviateError) return answerError(error, context); + if (error instanceof TransportError) return transportError(error, context); + if (error instanceof DatabaseError) return error; + return new QueryError("The request to Weaviate failed in a way Studio does not recognise.", PROVIDER); +} + +/** The answer when it is a success; otherwise its failure, worded, is thrown. */ +export function expectOk(answer: WeaviateAnswer, context: WeaviateErrorContext): WeaviateAnswer { + const failure = context.op === "graphql" ? graphqlFailure(answer) : answerFailure(answer); + if (failure !== undefined) throw toProviderError(failure, context); + return answer; +} diff --git a/src/lib/db/providers/vector/weaviate/execute.ts b/src/lib/db/providers/vector/weaviate/execute.ts new file mode 100644 index 0000000000..0e618dc864 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/execute.ts @@ -0,0 +1,309 @@ +import { RequestRefusal } from "@/lib/db/console/dialect"; +import { QueryCancelledError, TimeoutError } from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import type { TaggedObject } from "@/lib/db/console/tagged-json"; +import type { ProviderLimiter, RunRegistry } from "@/lib/db/utils/bounded-limiter"; +import type { QueryResult } from "@/lib/types"; +import type { WeaviateAnswer, WeaviateConsoleOp, WeaviateOp, WeaviateRequest, WeaviateSend } from "./client"; +import { answerFailure, graphqlFailure } from "./errors"; +import { encodeGraphql, encodeRest } from "./graphql"; +import { + parseWeaviateRequest, + type WeaviatePlan, + type WeaviateSearchModel, + weaviatePhase0, + weaviatePhase1, +} from "./request"; +import { weaviateResult } from "./results"; +import { WEAVIATE_BOUNDS } from "./routes"; +import { readWeaviateClass, type WeaviateCollectionFacts, weaviateCollectionFacts } from "./schema"; +import { + initialPath, + serverHas, + versionText, + type WeaviatePath, + type WeaviatePathKind, + type WeaviateVersion, +} from "./versions"; + +/** + * Runs one console request (#1566 spec 3.3, 5, W6): phase 0 with no call, then one limiter permit held for the + * whole request, and strictly one call after another: + * + * 1. the collection's definition (`GET /v1/schema/{collection}`) for every route that reads a collection, so phase 1 + * can check the tenancy rule, the properties and the vector the request names; for `GET /v1/schema/{collection}` + * itself that one read is the answer; + * 2. the tenant's own record (`GET /v1/schema/{collection}/tenants/{tenant}`) for every route that names a tenant, + * which never wakes it (spec A.4), and a refusal with no further call unless the tenant is HOT (W6); + * 3. the request itself: for a search or aggregate, over REST or GraphQL as the version decides, with the one + * fallback of spec 3.3 when the server answers that the chosen path is switched off; the path that answered is + * remembered for the session, so the next search goes straight to it. + * + * One deadline, fixed when the request arrives and before the queue: 10 s for a metadata route and 30 s for an + * object read, a search or an aggregate, at most the connection's query timeout and below Weaviate's 60 s write + * timeout (spec A.7). A run registered under its `queryId` can be cancelled; nothing is retried but the fallback, + * which is a different request and a read. + */ + +/** What failed, for errors.ts to word: a non-success answer, or what the transport threw. */ +export type WeaviateFailure = + | { readonly kind: "answer"; readonly op: WeaviateOp; readonly answer: WeaviateAnswer } + | { readonly kind: "thrown"; readonly op: WeaviateOp; readonly error: unknown }; + +/** The session's memory of which path answered, per search kind (spec 3.3). */ +export interface WeaviatePathState { + get(kind: WeaviatePathKind): WeaviatePath | undefined; + set(kind: WeaviatePathKind, path: WeaviatePath): void; +} + +export interface WeaviateExecution { + /** The client's send, narrowed to the operations a console request reaches. */ + readonly send: WeaviateSend; + readonly limiter: ProviderLimiter; + readonly runs: RunRegistry; + /** The version `GET /v1/meta` reported at connect. */ + readonly version: WeaviateVersion; + readonly paths: WeaviatePathState; + /** The Studio error for a failure (errors.ts). */ + readonly fail: (failure: WeaviateFailure) => Error; + /** The connection's query timeout in ms, which bounds every deadline; absent where none is set. */ + readonly queryTimeoutMs?: number; + /** The clock; only a test passes another. */ + readonly now?: () => number; + /** The deadline's signal; only a test passes another. */ + readonly deadline?: (ms: number) => AbortSignal; +} + +const METADATA_OPS: ReadonlySet = new Set([ + "meta", + "schema", + "collection", + "shards", + "tenants", + "tenant", + "aliases", + "alias", + "nodes", + "collection_nodes", +]); + +/** The routes that read a collection and so need its definition first. */ +const READS_COLLECTION: ReadonlySet = new Set([ + "shards", + "tenants", + "tenant", + "collection_nodes", + "objects", + "object", + "search_bm25", + "search_hybrid", + "search_near_vector", + "search_near_object", + "aggregate", +]); + +/** The statuses under which a tenant answers a read without being woken: HOT, and ACTIVE, its older name. */ +const READABLE_TENANT: ReadonlySet = new Set(["HOT", "ACTIVE"]); + +const ok = (answer: WeaviateAnswer): boolean => answer.status >= 200 && answer.status < 300; + +/** The deadline, in ms, of a request to `op`: a metadata route's or a read's, at most the query timeout. */ +export function weaviateDeadlineMs(op: WeaviateConsoleOp, queryTimeoutMs: number | undefined): number { + const own = METADATA_OPS.has(op) ? WEAVIATE_BOUNDS.metadataDeadlineMs : WEAVIATE_BOUNDS.searchDeadlineMs; + return queryTimeoutMs === undefined || queryTimeoutMs <= 0 ? own : Math.min(own, queryTimeoutMs); +} + +function refuseLater(message: string, key: string | null = null): never { + throw new RequestRefusal(message, 1, key); +} + +/** The tenant's status from its record; the record names the status `activityStatus`. */ +function tenantStatus(text: string): string { + try { + const parsed: unknown = JSON.parse(text); + const status = + typeof parsed === "object" && parsed !== null + ? (parsed as { activityStatus?: unknown }).activityStatus + : undefined; + return typeof status === "string" ? status : "UNKNOWN"; + } catch { + return "UNKNOWN"; + } +} + +function pathKindOf(op: WeaviateConsoleOp): WeaviatePathKind { + return op === "search_near_vector" ? "near-vector" : "other"; +} + +/** Whether a failed answer says the path itself is switched off on this server, the one case the other path is tried. */ +function pathSwitchedOff(answer: WeaviateAnswer, path: WeaviatePath): boolean { + const failure = path === "graphql" ? graphqlFailure(answer) : answerFailure(answer); + if (failure === undefined) return false; + return path === "graphql" + ? failure.category === "graphql-disabled" + : failure.category === "route-absent" || failure.category === "rest-search-disabled"; +} + +export async function executeWeaviate( + text: string, + queryId: string | undefined, + run: WeaviateExecution, +): Promise { + const now = run.now ?? Date.now; + const startedAt = now(); + const plan0 = weaviatePhase0(parseWeaviateRequest(text)); + const op = plan0.route.op; + const deadlineMs = weaviateDeadlineMs(op, run.queryTimeoutMs); + const deadline = (run.deadline ?? ((ms: number) => AbortSignal.timeout(ms)))(deadlineMs); + const handle = run.runs.begin(queryId, deadline); + const stopped = (): Error => { + const reason: unknown = handle.signal.reason; + if (reason instanceof QueryCancelledError) return reason; + return new TimeoutError(`The request did not finish within its ${deadlineMs / 1000} s deadline.`); + }; + /** One call; a thrown failure is worded, and an answer is handed back whatever its status. */ + const raw = async (request: WeaviateRequest): Promise => { + try { + return await run.send(request, handle.signal); + } catch (error) { + const unreachable = error instanceof TransportError && error.kind === "unreachable"; + if (handle.signal.aborted && !unreachable) throw stopped(); + throw run.fail({ kind: "thrown", op: request.op, error }); + } + }; + /** One call whose failure is the request's failure. */ + const call = async (request: WeaviateRequest): Promise => { + const answer = await raw(request); + const failed = request.op === "graphql" ? graphqlFailure(answer) !== undefined : !ok(answer); + if (failed) throw run.fail({ kind: "answer", op: request.op, answer }); + return answer; + }; + try { + let ticket: Awaited>; + try { + ticket = await run.limiter.acquire(handle.signal); + } catch (error) { + if (handle.signal.aborted) throw stopped(); + throw error; + } + try { + const collectionParams: Record = + plan0.collection === null ? {} : { collection: plan0.collection }; + let facts: WeaviateCollectionFacts | null = null; + if (plan0.collection !== null && (READS_COLLECTION.has(op) || op === "collection")) { + const answer = await call({ op: "collection", params: collectionParams, query: {} }); + if (op === "collection") { + return weaviateResult(answer.text, resultShape(plan0, null, null), { executionTime: now() - startedAt }); + } + facts = weaviateCollectionFacts(readWeaviateClass(JSON.parse(answer.text), plan0.collection)); + } + const plan = facts === null ? plan0 : weaviatePhase1(plan0, facts); + if (plan.tenant !== null && plan.collection !== null && op !== "tenant") { + const record = await call({ + op: "tenant", + params: { collection: plan.collection, tenant: plan.tenant }, + query: {}, + }); + const status = tenantStatus(record.text); + if (!READABLE_TENANT.has(status)) { + refuseLater( + `The tenant ${JSON.stringify(plan.tenant)} is ${status}. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first.`, + "tenant", + ); + } + } + const params = op === "objects" ? {} : { ...plan.request.params, ...collectionParams }; + if (plan.search === null) { + const answer = await call({ op, params, query: plan.query }); + return weaviateResult(answer.text, resultShape(plan, facts, null), { executionTime: now() - startedAt }); + } + const kind = pathKindOf(op); + const first = run.paths.get(kind) ?? initialPath(run.version, kind); + const send = (path: WeaviatePath): Promise => + raw( + path === "rest" + ? { op, params, query: {}, body: encodeRest(plan.body as TaggedObject, plan.search as WeaviateSearchModel) } + : { + op: "graphql", + params: {}, + query: {}, + body: encodeGraphql(plan.search as WeaviateSearchModel, facts as WeaviateCollectionFacts), + }, + ); + let path = first; + let answer = await send(path); + if (pathSwitchedOff(answer, path)) { + const other: WeaviatePath = path === "rest" ? "graphql" : "rest"; + const second = await send(other); + if (pathSwitchedOff(second, other)) { + refuseLater( + `This Weaviate server (${versionText(run.version)}) serves this search neither over REST search, which it lacks or keeps behind EXPERIMENTAL_REST_SEARCH_ENABLED, nor over GraphQL, which it has disabled. Browsing the collections still works.`, + ); + } + path = other; + answer = second; + } + const failed = path === "graphql" ? graphqlFailure(answer) !== undefined : !ok(answer); + if (failed) throw run.fail({ kind: "answer", op: path === "graphql" ? "graphql" : op, answer }); + run.paths.set(kind, path); + return weaviateResult(answer.text, resultShape(plan, facts, path, run.version), { + executionTime: now() - startedAt, + }); + } finally { + ticket.release(); + } + } finally { + handle.end(); + } +} + +/** Whether a where filter holds a WithinGeoRange condition at any level. */ +function holdsGeoRange(filter: unknown): boolean { + if (typeof filter !== "object" || filter === null) return false; + const node = filter as { readonly operator?: unknown; readonly operands?: unknown }; + if (node.operator === "WithinGeoRange") return true; + return Array.isArray(node.operands) && node.operands.some(holdsGeoRange); +} + +/** + * An aggregate filtered by WithinGeoRange counts 0 on the 1.37 line while Get finds the objects (measured on 1.37.4: + * 0 against 500; 1.38.22 and 1.40.2 count 500), so a count from such a server says so. + */ +function geoAggregateNote(plan: WeaviatePlan, version: WeaviateVersion | undefined) { + const search = plan.search; + if (version === undefined || search === null || search.op !== "aggregate" || !holdsGeoRange(search.where)) return []; + if (serverHas(version, GEO_AGGREGATE_SINCE)) return []; + return [ + { + message: `Weaviate ${versionText(version)} counts an aggregate filtered by WithinGeoRange as 0 even where objects match (measured on 1.37.4); read the objects with a search, or count on 1.38 or later.`, + }, + ]; +} + +/** The first line measured to count a WithinGeoRange aggregate correctly. */ +const GEO_AGGREGATE_SINCE = [1, 38, 0] as const; + +function resultShape( + plan: WeaviatePlan, + facts: WeaviateCollectionFacts | null, + path: WeaviatePath | null, + version?: WeaviateVersion, +) { + const pathNote = [ + ...(path === null ? [] : [{ message: path === "rest" ? "Answered via REST search." : "Answered via GraphQL." }]), + ...geoAggregateNote(plan, version), + ]; + return { + op: plan.route.op, + facts, + path, + model: plan.search, + // The next page is read with after, which takes neither offset nor sort: no notice for a list that names either. + limit: + plan.route.op === "objects" && !Object.hasOwn(plan.query, "offset") && !Object.hasOwn(plan.query, "sort") + ? Number(plan.query.limit) + : null, + afterGiven: Object.hasOwn(plan.query, "after"), + warnings: [...plan.warnings, ...pathNote], + }; +} diff --git a/src/lib/db/providers/vector/weaviate/execution-ui.ts b/src/lib/db/providers/vector/weaviate/execution-ui.ts new file mode 100644 index 0000000000..87d7fb536d --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/execution-ui.ts @@ -0,0 +1,8 @@ +import { SQL_COMMIT_KEYWORD } from "@/lib/db/execution-ui/shared"; +import type { ExecutionUiSpec } from "@/lib/db/execution-ui/types"; + +/** `weaviate`: the rolled-back notice names `COMMIT`, and the consent card has no deadline chip or sentence. */ +export const WEAVIATE_EXECUTION_UI: ExecutionUiSpec = { + commitKeyword: SQL_COMMIT_KEYWORD, + consentDeadline: null, +}; diff --git a/src/lib/db/providers/vector/weaviate/generators.ts b/src/lib/db/providers/vector/weaviate/generators.ts new file mode 100644 index 0000000000..2a46335959 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/generators.ts @@ -0,0 +1,98 @@ +/** + * What a tree click and Generate Request write for a Weaviate collection (#1566 spec 6.4), read through + * `DIALECT_GENERATORS.weaviate` in `src/lib/query-generators.ts`. + * + * The click runs at once: `GET /v1/objects` of the collection's first 50 objects. The generator is handed the path + * and the columns, which carry no tenancy, and a click never names a tenant, so on a multi-tenant collection phase + * 1 refuses the click with no call and names the request that lists its tenants and which are HOT (spec W6). + * Generate Request opens without running: a near-vector search + * over the first vector the columns declare with the shared probe vector when its dimension is known, then a BM25 + * search and an aggregate count as comments; when no object has shown the dimension, the BM25 search is the request + * and the near-vector search a comment, since a guessed length is a server error. + * + * A collection name reaches the text only through `encodeURIComponent` in the request line, which the console + * decodes back, and a vector name through `JSON.stringify`. Pure and browser-safe. + */ +import { toJsonText } from "@/lib/db/console/tagged-json"; +import { type ProbeVector, probeVector } from "@/lib/db/vector/probe"; +import type { ColumnSchema } from "@/lib/types"; + +/** The rows the tree click reads. */ +const WEAVIATE_CLICK_LIMIT = 50; +/** The hits Generate Request asks for, Weaviate's own default written out. */ +const WEAVIATE_GENERATED_LIMIT = 10; + +const VECTOR_TYPE = /^Vector\((\d+|\?),/; + +function collectionOf(path: readonly string[]): string { + return encodeURIComponent(path[path.length - 1]); +} + +/** The tree click: the collection's first objects. */ +export function weaviateTableQuery(path: readonly string[]): string { + return `GET /v1/objects?class=${collectionOf(path)}&limit=${WEAVIATE_CLICK_LIMIT}`; +} + +interface DeclaredVector { + readonly name: string; + readonly dimension: number | null; + readonly typeText: string; +} + +function declaredVectors(columns: readonly ColumnSchema[]): readonly DeclaredVector[] { + return columns.flatMap((column) => { + if (column.name !== "$vector" && !column.name.startsWith("$vector.")) return []; + const match = VECTOR_TYPE.exec(column.type); + // A length of 0 is no length the probe can write, so it reads as unknown, as `?` does. + const dimension = match === null || match[1] === "?" || match[1] === "0" ? null : Number(match[1]); + const name = column.name === "$vector" ? "" : column.name.slice("$vector.".length); + return [{ name, dimension, typeText: column.type }]; + }); +} + +function vectorText(dimension: number): string { + const probe = probeVector({ name: "", kind: "dense", dtype: "float32", dimension }) as ProbeVector; + const values = probe.kind === "dense" ? probe.values : []; + return `[${values.map(toJsonText).join(", ")}]`; +} + +/** Generate Request: a near-vector search over the first vector, then the other searches as comments. */ +export function weaviateSelectQuery(path: readonly string[], columns: readonly ColumnSchema[]): string { + const collection = collectionOf(path); + const vectors = declaredVectors(columns); + const keyword = [ + `// A keyword search: POST /v1/search/${collection}/bm25 {"query": "your words", "limit": ${WEAVIATE_GENERATED_LIMIT}}`, + `// A count: POST /v1/aggregate/${collection} {}`, + ]; + const chosen = vectors[0]; + if (chosen === undefined) { + return [ + `// Collection ${JSON.stringify(path[path.length - 1])} declares no vector to search.`, + `POST /v1/search/${collection}/bm25`, + `{"query": "your words", "limit": ${WEAVIATE_GENERATED_LIMIT}}`, + ].join("\n"); + } + const target = chosen.name === "" ? "" : `"targetVector": ${JSON.stringify(chosen.name)}, `; + const others = vectors + .slice(1) + .map((other) => `// Also in this collection: vector ${JSON.stringify(other.name)}, ${other.typeText}`); + if (chosen.dimension === null) { + // No length to write a probe of: a near-vector search sent with a guessed one is a server error, so the request + // that runs is the keyword search, and the vector search waits in a comment for the user's numbers. + return [ + `// A vector search needs a query vector of ${chosen.typeText}; no object has shown its length yet, so a keyword search runs instead:`, + `// POST /v1/search/${collection}/near-vector {"vector": [your numbers], ${target}"limit": ${WEAVIATE_GENERATED_LIMIT}, "returnMetadata": ["distance"]}`, + ...others, + keyword[1], + `POST /v1/search/${collection}/bm25`, + `{"query": "your words", "limit": ${WEAVIATE_GENERATED_LIMIT}}`, + ].join("\n"); + } + return [ + `// Replace vector with your query vector: ${chosen.typeText}`, + ...others, + ...keyword, + `POST /v1/search/${collection}/near-vector`, + `{"vector": ${vectorText(chosen.dimension)}, ${target}"limit": ${WEAVIATE_GENERATED_LIMIT}, "returnMetadata": ["distance"]}`, + ].join("\n"); +} diff --git a/src/lib/db/providers/vector/weaviate/graphql.ts b/src/lib/db/providers/vector/weaviate/graphql.ts new file mode 100644 index 0000000000..abc8514ae4 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/graphql.ts @@ -0,0 +1,261 @@ +/** + * The two encoders of one search model (#1566 spec 5.3) and the only producer of GraphQL text (spec W5). + * + * `encodeRest` writes the REST search or aggregate body back, a near identity after phase 0's checks. `encodeGraphql` + * writes one `Get` or `Aggregate` document for a server that serves no REST route for the request (spec 3.3), through + * the builder below, never by concatenating text a user typed: + * + * - every identifier (class, property, vector, enum word) is checked against GraphQL's name rule and Weaviate's own + * word lists here, again, though phase 0 has checked it, so a programming error cannot open the document; + * - every string is written by one function, JSON's escaping, which is GraphQL's for the characters JSON escapes, + * and a string that is not well-formed Unicode is refused, since GraphQL cannot carry a lone surrogate; + * - every number is the literal the user typed, kept by the console's tagged JSON, so neither path rounds it. + * + * The document has exactly one root field, `Get` or `Aggregate`, and one class under it. Pure. + */ +import { + isTaggedFloat, + isTaggedInt, + type TaggedJson, + type TaggedObject, + toJsonText, +} from "@/lib/db/console/tagged-json"; +import { QueryError } from "@/lib/db/errors"; +import type { DatabaseType } from "@/lib/types"; +import type { WeaviateSearchOp } from "./client"; +import type { WeaviateSearchModel } from "./request"; +import { WEAVIATE_ENUMS } from "./routes"; +import type { SelectionField, WeaviateCollectionFacts } from "./schema"; + +const PROVIDER: DatabaseType = "weaviate"; +const NAME = /^[_A-Za-z][_0-9A-Za-z]*$/; + +/** What `returnMetadata` names in REST, as GraphQL's `_additional` spells it. */ +export const GRAPHQL_METADATA: Readonly> = Object.freeze({ + distance: "distance", + certainty: "certainty", + score: "score", + explainScore: "explainScore", + creationTime: "creationTimeUnix", + lastUpdateTime: "lastUpdateTimeUnix", +}); + +/** REST's fusion words as GraphQL's enum spells them. */ +const GRAPHQL_FUSION: Readonly> = Object.freeze({ + ranked: "rankedFusion", + relativeScore: "relativeScoreFusion", +}); + +function fail(message: string): never { + throw new QueryError(message, PROVIDER); +} + +/** A GraphQL name, checked. */ +export function graphqlName(name: string): string { + if (!NAME.test(name)) fail(`${JSON.stringify(name)} cannot be written as a GraphQL name, so nothing was sent.`); + return name; +} + +/** An enum word from a closed list, checked against it. */ +function graphqlEnum(word: string, words: readonly string[]): string { + if (!words.includes(word)) fail(`${JSON.stringify(word)} is not a word this encoder writes, so nothing was sent.`); + return graphqlName(word); +} + +/** A GraphQL string: JSON's escaping, refused when the text is not well-formed Unicode. */ +export function graphqlString(text: string): string { + if (!text.isWellFormed()) + fail("A text in the request is not well-formed Unicode, so it cannot be sent over GraphQL."); + return JSON.stringify(text); +} + +/** A number the user typed, as its literal; a GraphQL Int or Float accepts every JSON number literal. */ +function graphqlNumber(value: TaggedJson): string { + if (isTaggedInt(value)) return value.digits; + if (isTaggedFloat(value)) return value.text; + if (typeof value === "number" && Number.isFinite(value)) return toJsonText(value); + return fail("A number in the request cannot be written as a GraphQL number, so nothing was sent."); +} + +/** A scalar value of a where filter or an argument: a string, a boolean or a number. */ +function graphqlScalar(value: TaggedJson): string { + if (typeof value === "string") return graphqlString(value); + if (typeof value === "boolean") return String(value); + return graphqlNumber(value); +} + +function list(values: readonly string[]): string { + return `[${values.join(",")}]`; +} + +/** An input object: `{key:value,...}`, each key a checked name, the values already written. */ +function inputObject(entries: readonly (readonly [string, string])[]): string { + return `{${entries.map(([key, value]) => `${graphqlName(key)}:${value}`).join(",")}}`; +} + +/** A where filter, as GraphQL's `where` argument writes it: the same keys, the operator as an enum. */ +export function graphqlWhere(filter: TaggedObject): string { + const entries: (readonly [string, string])[] = []; + for (const key of Object.keys(filter)) { + const value = filter[key]; + if (value === null) continue; + if (key === "operator") entries.push([key, graphqlEnum(value as string, WEAVIATE_ENUMS.operator)]); + else if (key === "operands") + entries.push([key, list((value as readonly TaggedJson[]).map((o) => graphqlWhere(o as TaggedObject)))]); + else if (key === "path") + entries.push([key, list((value as readonly TaggedJson[]).map((p) => graphqlString(p as string)))]); + else if (key === "valueGeoRange") entries.push([key, geoRange(value as TaggedObject)]); + // GraphQL has no valueArray keys: a list goes under the scalar key, so valueTextArray is written valueText + // (measured on 1.37.4, 1.38.22 and 1.40.2: "Unknown field" for valueTextArray, the REST count for valueText). + else if (Array.isArray(value)) entries.push([key.replace(/Array$/, ""), list(value.map(graphqlScalar))]); + else entries.push([key, graphqlScalar(value)]); + } + return inputObject(entries); +} + +function geoRange(range: TaggedObject): string { + const coordinates = range.geoCoordinates as TaggedObject; + const distance = range.distance as TaggedObject; + return inputObject([ + [ + "geoCoordinates", + inputObject([ + ["latitude", graphqlNumber(coordinates.latitude)], + ["longitude", graphqlNumber(coordinates.longitude)], + ]), + ], + ["distance", inputObject([["max", graphqlNumber(distance.max)]])], + ]); +} + +function selection(fields: readonly SelectionField[]): string { + return fields + .map((field) => + field.fields === undefined ? graphqlName(field.name) : `${graphqlName(field.name)}{${selection(field.fields)}}`, + ) + .join(" "); +} + +/** The properties a read selects: the ones named, or every plain property, each with the sub-selection GraphQL needs. */ +export function selectedProperties( + model: WeaviateSearchModel, + facts: WeaviateCollectionFacts, +): readonly SelectionField[] { + const names = model.returnProperties ?? facts.plainProperties; + return names.flatMap((name) => { + const field = facts.selections.get(name); + return field === undefined ? [] : [field]; + }); +} + +function targetVectors(model: WeaviateSearchModel): readonly (readonly [string, string])[] { + return model.targetVector === null ? [] : [["targetVectors", list([graphqlString(model.targetVector)])]]; +} + +function proximity(model: WeaviateSearchModel): readonly (readonly [string, string])[] { + return [ + ...(model.distance === null ? [] : [["distance", graphqlNumber(model.distance)] as const]), + ...(model.certainty === null ? [] : [["certainty", graphqlNumber(model.certainty)] as const]), + ]; +} + +/** The search argument of a Get: bm25, hybrid, nearVector or nearObject. */ +/** A search's argument; an aggregate takes none and never reaches here (encodeGraphql writes it alone). */ +function searchArgument(model: WeaviateSearchModel & { readonly op: WeaviateSearchOp }): readonly [string, string] { + switch (model.op) { + case "search_bm25": + return [ + "bm25", + inputObject([ + ["query", graphqlString(model.query as string)], + ...(model.queryProperties === null + ? [] + : [["properties", list(model.queryProperties.map(graphqlString))] as const]), + ]), + ]; + case "search_hybrid": + return [ + "hybrid", + inputObject([ + ["query", graphqlString(model.query as string)], + ["alpha", "0"], + ...(model.queryProperties === null + ? [] + : [["properties", list(model.queryProperties.map(graphqlString))] as const]), + ...(model.fusionType === null + ? [] + : [["fusionType", graphqlEnum(GRAPHQL_FUSION[model.fusionType], Object.values(GRAPHQL_FUSION))] as const]), + ...(model.maxVectorDistance === null + ? [] + : [["maxVectorDistance", graphqlNumber(model.maxVectorDistance)] as const]), + ...targetVectors(model), + ]), + ]; + case "search_near_vector": + return [ + "nearVector", + inputObject([ + ["vector", list((model.vector as readonly TaggedJson[]).map(graphqlNumber))], + ...proximity(model), + ...targetVectors(model), + ]), + ]; + case "search_near_object": + return [ + "nearObject", + inputObject([["id", graphqlString(model.id as string)], ...proximity(model), ...targetVectors(model)]), + ]; + } +} + +function commonArguments(model: WeaviateSearchModel): (readonly [string, string])[] { + return [ + ...(model.tenant === null ? [] : [["tenant", graphqlString(model.tenant)] as const]), + ...(model.where === null ? [] : [["where", graphqlWhere(model.where)] as const]), + ]; +} + +function argumentsText(entries: readonly (readonly [string, string])[]): string { + return entries.length === 0 ? "" : `(${entries.map(([key, value]) => `${graphqlName(key)}:${value}`).join(",")})`; +} + +/** The one GraphQL document for a search or aggregate model, as a request body `{"query": "..."}`. */ +export function encodeGraphql(model: WeaviateSearchModel, facts: WeaviateCollectionFacts): string { + const className = graphqlName(model.collection); + let document: string; + if (model.op === "aggregate") { + const args = [ + ...commonArguments(model), + ...(model.groupBy === null ? [] : [["groupBy", list([graphqlString(model.groupBy)])] as const]), + ...(model.limit === null ? [] : [["limit", graphqlNumber(model.limit)] as const]), + ]; + const grouped = model.groupBy === null ? "" : " groupedBy{value path}"; + document = `{Aggregate{${className}${argumentsText(args)}{meta{count}${grouped}}}}`; + } else { + const args = [ + ...commonArguments(model), + searchArgument(model as WeaviateSearchModel & { readonly op: WeaviateSearchOp }), + ...(model.limit === null ? [] : [["limit", graphqlNumber(model.limit)] as const]), + ...(model.offset === null ? [] : [["offset", graphqlNumber(model.offset)] as const]), + ...(model.autoLimit === null ? [] : [["autocut", graphqlNumber(model.autoLimit)] as const]), + ...(model.consistencyLevel === null + ? [] + : [["consistencyLevel", graphqlEnum(model.consistencyLevel, WEAVIATE_ENUMS.consistencyLevel)] as const]), + ]; + const additional = ["id", ...model.returnMetadata.map((word) => graphqlName(GRAPHQL_METADATA[word]))]; + const properties = selection(selectedProperties(model, facts)); + document = `{Get{${className}${argumentsText(args)}{${properties === "" ? "" : `${properties} `}_additional{${additional.join(" ")}}}}}`; + } + return JSON.stringify({ query: document }); +} + +/** The REST body for a search or aggregate: the body as phase 0 checked it, with the target vector phase 1 found. */ +export function encodeRest(body: TaggedObject, model: WeaviateSearchModel): string { + if (model.op === "aggregate" || model.targetVector === null || Object.hasOwn(body, "targetVector")) { + return toJsonText(body); + } + const copy: Record = Object.create(null); + for (const key of Object.keys(body)) copy[key] = body[key]; + copy.targetVector = model.targetVector; + return toJsonText(copy); +} diff --git a/src/lib/db/providers/vector/weaviate/guard.ts b/src/lib/db/providers/vector/weaviate/guard.ts new file mode 100644 index 0000000000..dd5d27e396 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/guard.ts @@ -0,0 +1,35 @@ +import { RequestRefusal } from "@/lib/db/console/dialect"; +import { parseWeaviateRequest, weaviatePhase0 } from "./request"; + +/** + * The browser's verdict on a Weaviate console text: the grammar and every rule that needs neither the schema nor the + * server, the same two functions the provider runs first, so what the editor refuses and what the server refuses for + * those rules are one reading. + * + * A text it refuses is never sent to any route and never written to query history. The tenancy rule, the tenant's + * status and a rule that reads the collection are the server's to apply. + */ + +/** The operations that ask for a confirmation: none, because every route the console runs is a read. */ +export const WEAVIATE_DESTRUCTIVE_OPERATIONS: ReadonlySet = new Set(); + +/** The sentence a statement is refused with, or undefined to send it. */ +export function weaviateRefusal(text: string): string | undefined { + try { + weaviatePhase0(parseWeaviateRequest(text)); + return undefined; + } catch (error) { + if (error instanceof RequestRefusal) return error.message; + throw error; + } +} + +/** What a text would run, for the confirmation gate: the class of its route, or undefined for a text the console refuses. */ +export function readWeaviateOperations(text: string): readonly string[] | undefined { + try { + return [weaviatePhase0(parseWeaviateRequest(text)).route.class]; + } catch (error) { + if (error instanceof RequestRefusal) return undefined; + throw error; + } +} diff --git a/src/lib/db/providers/vector/weaviate/index.ts b/src/lib/db/providers/vector/weaviate/index.ts new file mode 100644 index 0000000000..50d778b445 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/index.ts @@ -0,0 +1,383 @@ +/** + * Weaviate provider (#1566). Read-only REST access to a Weaviate server: its collections in the tree with their + * properties and vectors, a closed console of 17 read routes in the editor whose searches run over REST or GraphQL + * as the server's version decides, and the overview, Tables and index panels. + * + * COMPOSITION AND DELEGATION ONLY (spec 3.1). The wire lives in `rest-client.ts`, the connection rules in + * `connection-options.ts`, the version and the path table in `versions.ts`, the error table in `errors.ts`, a + * console request's run in `execute.ts`, the object surface and the Source in `objects.ts`, `schema.ts` and + * `source.ts`, the monitoring reads in `monitoring-reads.ts` and `monitoring.ts`, and the labels in `labels.ts`. + * What stays here is the lifecycle, the declarations, the connect read, and each surface call's permit, deadline + * and error context. + * + * One limiter covers every client call. No `queryReadOnly`, no transaction method and no maintenance operation: + * each is detected by presence, and none exists for Weaviate in this version. + */ +import { BaseDatabaseProvider } from "@/lib/db/base-provider"; +import { DatabaseConfigError, QueryError } from "@/lib/db/errors"; +import type { + ActiveSessionDetails, + Container, + DatabaseConnection, + DatabaseObject, + DatabaseOverview, + HealthInfo, + IndexStats, + KindCount, + MaintenanceResult, + ObjectDetail, + ObjectDetailBatch, + ObjectSourceDocument, + PerformanceMetrics, + PreparedQuery, + ProviderCapabilities, + ProviderExecutionContext, + ProviderLabels, + ProviderOptions, + QueryResult, + SlowQueryStats, + StorageStats, + TableStats, +} from "@/lib/db/types"; +import { + createRunRegistry, + engineLimiter, + type ProviderLimiter, + type RunRegistry, +} from "@/lib/db/utils/bounded-limiter"; +import { DEFAULT_QUERY_LIMIT } from "@/lib/db/utils/query-limiter"; +import type { QueryWarning } from "@/lib/types"; +import type { WeaviateClient, WeaviateOp, WeaviateRequest, WeaviateRouteTemplates, WeaviateSend } from "./client"; +import { + buildWeaviateConnectionOptions, + WEAVIATE_DEFAULT_PORT, + WEAVIATE_MAX_IN_FLIGHT, + type WeaviateConnectionOptions, +} from "./connection-options"; +import { answerFailure, expectOk, graphqlFailure, toProviderError, type WeaviateErrorContext } from "./errors"; +import { executeWeaviate, type WeaviateFailure, type WeaviatePathState } from "./execute"; +import { WEAVIATE_LABELS } from "./labels"; +import { + readWeaviateHealth, + readWeaviateIndexStats, + readWeaviateOverview, + readWeaviateTableStats, +} from "./monitoring-reads"; +import { + countWeaviateObjects, + describeWeaviateObject, + describeWeaviateObjects, + listWeaviateObjects, + readWeaviateObjectSource, + WEAVIATE_OBJECT_KINDS, + WEAVIATE_SURFACE_TIMEOUT_MS, + type WeaviateSurfaceContext, +} from "./objects"; +import { createRestWeaviateClient } from "./rest-client"; +import { WEAVIATE_BOUNDS, WEAVIATE_CLIENT_ROUTES } from "./routes"; +import { + belowFloorWarning, + readWeaviateVersion, + type WeaviatePath, + type WeaviatePathKind, + type WeaviateVersion, +} from "./versions"; + +/** The in-flight bounds: four per provider, the transport's sockets, sixteen per process, a queue of 64. */ +export const WEAVIATE_LIMITER_OPTIONS = { perProvider: WEAVIATE_MAX_IN_FLIGHT, perEngine: 16, queueDepth: 64 } as const; + +const weaviateLimiter = engineLimiter("weaviate", WEAVIATE_LIMITER_OPTIONS); + +/** The route table as the client takes it: each operation's method, path and query keys. */ +export const WEAVIATE_ROUTE_TEMPLATES: WeaviateRouteTemplates = WEAVIATE_CLIENT_ROUTES; + +/** What builds the provider's one client: `createRestWeaviateClient` by default, a recording client in a test. */ +export type WeaviateClientFactory = ( + options: WeaviateConnectionOptions, + routes: WeaviateRouteTemplates, +) => WeaviateClient; + +const BOUND_PARAMS_MESSAGE = "Bound params are not supported: a Weaviate request has no placeholders"; +const NO_MAINTENANCE = "Weaviate has no maintenance operation in this version of Studio, so nothing was sent."; + +function requireRoot(container: readonly string[]): void { + if (container.length !== 0) { + throw new QueryError( + `A Weaviate connection has no container level; received ${JSON.stringify(container)}`, + "weaviate", + ); + } +} + +function errorContext( + options: WeaviateConnectionOptions, + phase: WeaviateErrorContext["phase"], + op: WeaviateOp, + timeoutMs: number, +): WeaviateErrorContext { + return { + phase, + op, + endpoint: options.endpoint, + responseCapBytes: options.responseCapBytes, + timeoutMs, + secretForms: options.secretForms, + }; +} + +/** The session's memory of which path answered a search, per kind (spec 3.3); never stored with the connection. */ +function pathState(): WeaviatePathState { + const known = new Map(); + return { + get: (kind) => known.get(kind), + set: (kind, path) => { + known.set(kind, path); + }, + }; +} + +interface WeaviateSession { + readonly client: WeaviateClient; + readonly options: WeaviateConnectionOptions; + readonly version: WeaviateVersion; + readonly paths: WeaviatePathState; +} + +export class WeaviateProvider extends BaseDatabaseProvider { + private session: WeaviateSession | null = null; + private readonly limiter: ProviderLimiter = weaviateLimiter(); + private readonly runs: RunRegistry = createRunRegistry(); + + /** Validates nothing and opens nothing: the connection's rules run in `connect()`, before the factory. */ + constructor( + config: DatabaseConnection, + options: ProviderOptions = {}, + private readonly execution: ProviderExecutionContext = {}, + private readonly createClient: WeaviateClientFactory = createRestWeaviateClient, + ) { + super(config, options); + } + + /** Every member written out: the base's defaults are SQL's, so each flag here is a decision (spec 6.2). */ + public override getCapabilities(): ProviderCapabilities { + return { + // A `METHOD /v1/path` line and one JSON body; "json" means only "not SQL", and the dialect says which JSON. + queryLanguage: "json", + queryDialect: "weaviate", + supportsExplain: false, + supportsTransactions: false, + supportsInlineRowEdit: false, + supportsTestDataGeneration: false, + supportsResultPagination: false, + supportsExternalQueryLimiting: false, + supportsConnectionString: false, + declaresForeignKeys: false, + supportsMaintenance: false, + maintenanceOperations: [], + statementTerminator: "none", + defaultPort: WEAVIATE_DEFAULT_PORT, + containerLevels: [], + objectKinds: WEAVIATE_OBJECT_KINDS, + enforcesReadOnly: true, + // A Weaviate request changes no collection, so no request refreshes the schema. + schemaRefreshPattern: "(?!)", + }; + } + + public override getLabels(): ProviderLabels { + return { ...WEAVIATE_LABELS }; + } + + /** The request carries its own bounds: no limit is added, and there is no page two. */ + public override prepareQuery(query: string): PreparedQuery { + return { query, wasLimited: false, limit: DEFAULT_QUERY_LIMIT, offset: 0 }; + } + + /** + * After connection-options.ts's checks, exactly one request: `GET /v1/meta`, which authenticates (anonymous access + * off answers 401 without a key) and gives the version the path table reads. Nothing is retried, and a client that + * was built is closed on a failure. + */ + public async connect(): Promise { + let client: WeaviateClient | undefined; + try { + const options = buildWeaviateConnectionOptions(this.config, { + executionReadOnly: this.execution.readOnly === true, + queryTimeout: this.queryTimeout, + }); + client = this.createClient(options, WEAVIATE_ROUTE_TEMPLATES); + const send = this.sendFor(client, options, "connect"); + const meta = await send({ op: "meta", params: {}, query: {} }, this.surfaceSignal()); + this.session = { client, options, version: readWeaviateVersion(meta.text), paths: pathState() }; + } catch (error) { + client?.close(); + this.setError(error as Error); + throw error; + } + this.setConnected(true); + } + + /** A server older than the supported floor connects, with this one warning (spec 3.1). */ + public connectWarnings(): QueryWarning[] { + const version = this.session?.version; + const warning = version === undefined ? undefined : belowFloorWarning(version); + return warning === undefined ? [] : [{ message: warning }]; + } + + public async disconnect(): Promise { + const session = this.session; + this.session = null; + this.setConnected(false); + session?.client.close(); + } + + private requireSession(): WeaviateSession { + this.ensureConnected(); + return this.session!; + } + + /** A surface call's deadline: 10 s, and never past the connection's query timeout. */ + private surfaceSignal(): AbortSignal { + return AbortSignal.timeout(Math.min(WEAVIATE_SURFACE_TIMEOUT_MS, this.queryTimeout)); + } + + /** One read under its own limiter permit; a failed request or a failed answer raised in errors.ts's words. */ + private sendFor( + client: WeaviateClient, + options: WeaviateConnectionOptions, + phase: WeaviateErrorContext["phase"], + ): WeaviateSend { + return async (request: WeaviateRequest, signal: AbortSignal) => { + const context = errorContext( + options, + phase, + request.op, + Math.min(WEAVIATE_SURFACE_TIMEOUT_MS, this.queryTimeout), + ); + let answer: Awaited>; + try { + const ticket = await this.limiter.acquire(signal); + try { + answer = await client.send(request, signal); + } finally { + ticket.release(); + } + } catch (error) { + throw toProviderError(error, context); + } + return expectOk(answer, context); + }; + } + + private surface(): WeaviateSurfaceContext { + const session = this.requireSession(); + return { + send: this.sendFor(session.client, session.options, "request"), + signal: this.surfaceSignal(), + version: session.version, + paths: session.paths, + scoped: session.options.secretForms.length > 0, + }; + } + + public async query(text: string, params?: unknown[], queryId?: string): Promise { + // A Weaviate request has no binding, and dropping the values would run another request than the one built. + if (params !== undefined && params.length > 0) throw new DatabaseConfigError(BOUND_PARAMS_MESSAGE, this.type); + const session = this.requireSession(); + const { client, options } = session; + return executeWeaviate(text, queryId, { + send: (request, signal) => client.send(request, signal), + limiter: this.limiter, + runs: this.runs, + version: session.version, + paths: session.paths, + fail: (failure: WeaviateFailure) => { + const context = errorContext( + options, + "request", + failure.op, + Math.min(WEAVIATE_BOUNDS.searchDeadlineMs, this.queryTimeout), + ); + if (failure.kind === "thrown") return toProviderError(failure.error, context); + const answered = failure.op === "graphql" ? graphqlFailure(failure.answer) : answerFailure(failure.answer); + return toProviderError(answered, context); + }, + queryTimeoutMs: this.queryTimeout, + }); + } + + /** Aborts a running or queued request by its id and answers true; an unknown id answers false. */ + public async cancelQuery(queryId: string): Promise { + return this.runs.cancel(queryId); + } + + public async listContainers(): Promise { + this.ensureConnected(); + return []; + } + + public async countObjects(container: readonly string[]): Promise> { + requireRoot(container); + return countWeaviateObjects(this.surface()); + } + + public async listObjects(container: readonly string[], kind: string): Promise { + requireRoot(container); + return listWeaviateObjects(this.surface(), kind); + } + + public async describeObject(path: readonly string[], kind: string): Promise { + return describeWeaviateObject(this.surface(), path, kind); + } + + /** One schema read for every collection's columns: the one-round-trip contract (spec 4.2). */ + public async describeObjects(container: readonly string[], kind: string, limit?: number): Promise { + requireRoot(container); + return describeWeaviateObjects(this.surface(), kind, limit); + } + + public async readObjectSource(path: readonly string[], kind: string, limit?: number): Promise { + return readWeaviateObjectSource(this.surface(), path, kind, limit); + } + + /** `/v1/.well-known/ready`: readiness only, never evidence of the credential. */ + public async getHealth(): Promise { + return readWeaviateHealth(this.surface()); + } + + public async getOverview(): Promise { + return readWeaviateOverview(this.surface()); + } + + public async getTableStats(): Promise { + return readWeaviateTableStats(this.surface()); + } + + public async getIndexStats(): Promise { + return readWeaviateIndexStats(this.surface()); + } + + public async getPerformanceMetrics(): Promise { + this.ensureConnected(); + return {}; + } + + public async getSlowQueries(): Promise { + this.ensureConnected(); + return []; + } + + public async getActiveSessions(): Promise { + this.ensureConnected(); + return []; + } + + public async getStorageStats(): Promise { + this.ensureConnected(); + return []; + } + + public async runMaintenance(): Promise { + throw new QueryError(NO_MAINTENANCE, this.type); + } +} diff --git a/src/lib/db/providers/vector/weaviate/labels.ts b/src/lib/db/providers/vector/weaviate/labels.ts new file mode 100644 index 0000000000..a81d2ad297 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/labels.ts @@ -0,0 +1,80 @@ +/** + * The Weaviate provider's labels (#1566 spec 6.3). + * + * `statementLanguage` is what plan mode states after "Write it in" (`src/lib/agent/investigation.ts`), the one fact + * about how a request is written that its prompt carries for this engine. It is generated from the route table and + * the dialect (`routes.ts`), so the two cannot drift: every route of class `read` as `METHOD /template` in table + * order, the comment markers, how a body is written with one example, and what the console refuses. + * + * Pure and browser-safe: it imports the route table and the label type only. + */ +import type { ConsoleDialectSpec, RouteSpec } from "@/lib/db/console/dialect"; +import type { ProviderLabels } from "@/lib/db/types"; +import { WEAVIATE_CONSOLE, WEAVIATE_ROUTES } from "./routes"; + +/** The classes of requests the console refuses, in the words and the order of the sentence's refusal clause. */ +export const WEAVIATE_REFUSED_CLASSES: readonly string[] = Object.freeze([ + "object, schema, tenant and alias writes", + "batch", + "backups", + "users and roles", + "near-text and the other searches that send text or media to a model", + "generative search and rerank", + "hybrid with an alpha other than 0", + "GraphQL written by hand", +]); + +/** The example request the sentence gives, with names that fit the seeded `Article`. */ +export const WEAVIATE_STATEMENT_EXAMPLE = + 'POST /v1/search/Article/bm25 {"query": "vector search", "where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}, "limit": 5, "returnMetadata": ["score"]}'; + +function listText(items: readonly string[]): string { + return items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items[items.length - 1]}`; +} + +/** Every route of class `read`, in table order, as `METHOD /template`. */ +export function weaviateReadRoutes(spec: ConsoleDialectSpec, routes: readonly RouteSpec[]): readonly string[] { + return routes + .filter((route) => route.class === "read") + .map((route) => `${route.method} ${spec.pathPrefix}${route.template}`); +} + +/** The sentence, generated from the dialect, the route table and the refused classes. */ +export function weaviateStatementLanguage( + spec: ConsoleDialectSpec, + routes: readonly RouteSpec[], + refused: readonly string[], +): string { + return [ + `A Weaviate REST request, one per run: optional comment lines starting with ${spec.commentMarkers.join(" or ")}, then a line METHOD /path naming one of ${listText(weaviateReadRoutes(spec, routes))}, with every brace-enclosed segment replaced by a real name or id.`, + `GET routes take no body; POST routes take one JSON object with that route's Weaviate REST body, for example ${WEAVIATE_STATEMENT_EXAMPLE}.`, + "Filters are Weaviate where objects with operator, path and one value key such as valueText or valueInt; And, Or and Not take operands.", + 'A multi-tenant collection needs its tenant: ?tenant= on a GET, "tenant" in a body.', + `Not requests: ${listText(refused)}.`, + ].join(" "); +} + +export const WEAVIATE_LABELS: ProviderLabels = { + entityName: "Collection", + entityNamePlural: "Collections", + rowName: "Object", + rowNamePlural: "Objects", + selectAction: "Read Objects", + generateAction: "Generate Request", + searchPlaceholder: "Search collections...", + statementLanguage: weaviateStatementLanguage(WEAVIATE_CONSOLE, WEAVIATE_ROUTES, WEAVIATE_REFUSED_CLASSES), + slowQueriesEmptyState: "Weaviate reports no slow-query log over the routes Studio reads.", + sessionsEmptyState: + "Weaviate does not report client sessions over the routes Studio reads. For performance and storage, connect Studio to a Prometheus server that scrapes Weaviate's metrics.", + tableStatsCaption: + "The first 200 single-tenant collections, each with its exact object count (aggregate meta.count). A multi-tenant collection is counted per tenant: POST /v1/aggregate/{collection} with a tenant.", + // Never rendered: Weaviate has no maintenance operation in this version (supportsMaintenance is false). Worded true anyway. + analyzeAction: "Collection Statistics", + vacuumAction: "Compact Collection", + analyzeGlobalLabel: "Statistics", + analyzeGlobalTitle: "Not available", + analyzeGlobalDesc: "Weaviate keeps no statistics to update; the Tables tab counts each collection when it opens.", + vacuumGlobalLabel: "Compact", + vacuumGlobalTitle: "Not available", + vacuumGlobalDesc: "Studio runs no Weaviate maintenance operation; Weaviate compacts its segments on its own.", +}; diff --git a/src/lib/db/providers/vector/weaviate/migration-ddl.ts b/src/lib/db/providers/vector/weaviate/migration-ddl.ts new file mode 100644 index 0000000000..e879422e51 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/migration-ddl.ts @@ -0,0 +1,18 @@ +/** + * Not a table store (#1566 spec 3.5): a collection's properties and vectors are declared through Weaviate's own + * schema API, and this console writes nothing, so a schema diff gets no table DDL. The sentence is the one `refusal` + * prints when it declines the whole diff. + * + * The migration text carries no transaction wrapper (#284): `weaviate` text is a Weaviate console request, not SQL. + */ +import type { MigrationDdlSpec } from "@/lib/db/migration-ddl/types"; + +const REASON = + "A collection's properties and vectors are declared through Weaviate's own schema API, not SQL DDL, so there is no column definition to change."; + +export const WEAVIATE_MIGRATION_DDL: MigrationDdlSpec = { + tableDdl: "refused", + refusal: `-- Weaviate: Cannot generate table DDL. ${REASON}`, + transactionWrapper: null, + reasons: [REASON], +}; diff --git a/src/lib/db/providers/vector/weaviate/monitoring-reads.ts b/src/lib/db/providers/vector/weaviate/monitoring-reads.ts new file mode 100644 index 0000000000..ccd4e3ce3d --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/monitoring-reads.ts @@ -0,0 +1,50 @@ +/** + * The monitoring reads of #1566 spec 7: `/v1/.well-known/ready` for readiness, `/v1/meta` for the version, + * `/v1/schema` for the collections and their vector indexes, and one aggregate count per single-tenant collection + * of the first 200, one after another. monitoring.ts shapes every answer. + */ +import type { DatabaseOverview, HealthInfo, IndexStats, TableStats } from "@/lib/db/types"; +import { countWeaviateCollection, readWeaviateClasses, type WeaviateSurfaceContext } from "./objects"; +import { + toWeaviateHealth, + toWeaviateIndexStats, + toWeaviateOverview, + toWeaviateTableStats, + WEAVIATE_TABLE_STATS_LIMIT, +} from "./monitoring"; +import { readWeaviateVersion } from "./versions"; + +export async function readWeaviateHealth(context: WeaviateSurfaceContext<"ready">): Promise { + await context.send({ op: "ready", params: {}, query: {} }, context.signal); + return toWeaviateHealth(); +} + +export async function readWeaviateOverview( + context: WeaviateSurfaceContext<"meta" | "schema">, +): Promise { + const meta = await context.send({ op: "meta", params: {}, query: {} }, context.signal); + const collections = await readWeaviateClasses(context); + return toWeaviateOverview({ + version: readWeaviateVersion(meta.text).reported, + collections, + scoped: context.scoped, + }); +} + +/** One exact count per single-tenant collection of the first 200; a multi-tenant one is left out, as the caption says. */ +export async function readWeaviateTableStats( + context: WeaviateSurfaceContext<"schema" | "aggregate" | "graphql">, +): Promise { + const collections = (await readWeaviateClasses(context)).slice(0, WEAVIATE_TABLE_STATS_LIMIT); + const counts: { name: string; count: number | null }[] = []; + for (const collection of collections) { + if (collection.multiTenant) continue; + // oxlint-disable-next-line no-await-in-loop -- one count at a time, so the panel never floods the server. + counts.push({ name: collection.name, count: await countWeaviateCollection(context, collection) }); + } + return toWeaviateTableStats(counts); +} + +export async function readWeaviateIndexStats(context: WeaviateSurfaceContext<"schema">): Promise { + return toWeaviateIndexStats(await readWeaviateClasses(context)); +} diff --git a/src/lib/db/providers/vector/weaviate/monitoring.ts b/src/lib/db/providers/vector/weaviate/monitoring.ts new file mode 100644 index 0000000000..5628b70bea --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/monitoring.ts @@ -0,0 +1,74 @@ +/** + * Pure mappings from Weaviate's answers to the monitoring types (#1566 spec 7). A figure Weaviate's read routes do + * not report is left out or reads "N/A", never zero: there is no uptime, no connection count and no size on disk in + * `/v1/meta` or `/v1/schema`. `/v1/nodes` object counts are never used: they read 0 for collections that held objects + * twenty minutes after they were written (spec A.9), so counts are aggregate `meta.count`, which is exact. + * + * Pure: it receives answers and never a client; monitoring-reads.ts makes the reads. + */ +import type { DatabaseOverview, HealthInfo, IndexStats, TableStats } from "@/lib/db/types"; +import { VISIBLE_TO_CREDENTIAL } from "./objects"; +import { vectorColumnName, type WeaviateClass } from "./schema"; + +const NOT_REPORTED = "N/A"; + +/** The collections the Tables panel counts, in listing order, as Qdrant's 200. */ +export const WEAVIATE_TABLE_STATS_LIMIT = 200; + +/** Reachability and readiness only: `/v1/.well-known/ready` answers without a key. */ +export function toWeaviateHealth(): HealthInfo { + return { databaseSize: NOT_REPORTED, cacheHitRatio: NOT_REPORTED, slowQueries: [], activeSessions: [] }; +} + +export interface WeaviateOverviewInput { + readonly version: string | null; + readonly collections: readonly WeaviateClass[]; + readonly scoped: boolean; +} + +/** One vector index per vector of every collection. */ +export function weaviateIndexCount(collections: readonly WeaviateClass[]): number { + return collections.reduce((total, collection) => total + collection.vectors.length, 0); +} + +export function toWeaviateOverview(input: WeaviateOverviewInput): DatabaseOverview { + return { + version: input.version ?? NOT_REPORTED, + uptime: NOT_REPORTED, + maxConnections: 0, + databaseSize: NOT_REPORTED, + tableCount: input.collections.length, + ...(input.scoped ? { tableCountSampledFrom: VISIBLE_TO_CREDENTIAL } : {}), + indexCount: weaviateIndexCount(input.collections), + }; +} + +/** One row per counted collection, its exact count; a collection whose count was not read is left out. */ +export function toWeaviateTableStats( + counts: readonly { readonly name: string; readonly count: number | null }[], +): TableStats[] { + return counts.flatMap(({ name, count }) => + count === null + ? [] + : [{ schemaName: "", tableName: name, rowCount: count, totalSize: NOT_REPORTED, totalSizeBytes: 0 }], + ); +} + +/** One row per vector index: the collection, the vector's column, the index type with its distance and compression. */ +export function toWeaviateIndexStats(collections: readonly WeaviateClass[]): IndexStats[] { + return collections.flatMap((collection) => + collection.vectors.map( + (vector): IndexStats => ({ + schemaName: "", + tableName: collection.name, + indexName: vectorColumnName(vector.name), + indexType: [vector.indexType, vector.distance, vector.quantization].filter((part) => part !== null).join(", "), + columns: [vectorColumnName(vector.name)], + isUnique: false, + isPrimary: false, + indexSize: NOT_REPORTED, + scans: 0, + }), + ), + ); +} diff --git a/src/lib/db/providers/vector/weaviate/objects.ts b/src/lib/db/providers/vector/weaviate/objects.ts new file mode 100644 index 0000000000..3d42ae2563 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/objects.ts @@ -0,0 +1,332 @@ +/** + * The Weaviate object surface (#1566 spec 4): one kind, the collection, with no container level (`containerLevels: + * []`, the Qdrant shape). Tenants and aliases are details of a collection, in its Source and in the console, never + * tree rows, by the precedent of Milvus's partitions and Qdrant's aliases (spec 4.1). + * + * The listing is one `GET /v1/schema`, which also answers every collection's columns, so `describeObjects` keeps the + * one-round-trip contract. `describeObject` adds one object read with `include=vector` to a single-tenant collection + * to spell its vectors' dimensions, which the schema does not declare (spec 4.2); a multi-tenant collection is never + * read past its schema, so no tenant is touched (W6). + * + * Every read goes through the `send` the surface is handed: index.ts gives each call its own limiter permit and the + * surface's deadline, and raises a failure in errors.ts's words, so nothing here retries or words an HTTP failure. + */ +import { QueryError } from "@/lib/db/errors"; +import { callerBoundTruncationReason } from "@/lib/db/object-kinds"; +import type { + DatabaseObject, + KindCount, + ObjectDetail, + ObjectDetailBatch, + ObjectKindSpec, + ObjectSourceDocument, +} from "@/lib/db/types"; +import type { DatabaseType } from "@/lib/types"; +import type { WeaviateAnswer, WeaviateOp, WeaviateSend } from "./client"; +import { encodeGraphql } from "./graphql"; +import type { WeaviatePathState } from "./execute"; +import type { WeaviateSearchModel } from "./request"; +import { + readWeaviateClass, + readWeaviateSchema, + type WeaviateClass, + weaviateCollectionFacts, + weaviateColumns, + weaviateIndexes, +} from "./schema"; +import { weaviateSourceParts } from "./source"; +import { initialPath, type WeaviateVersion } from "./versions"; + +const PROVIDER: DatabaseType = "weaviate"; + +const WEAVIATE_COLLECTION_KIND = "collection"; + +export const WEAVIATE_OBJECT_KINDS: readonly ObjectKindSpec[] = Object.freeze([ + { + id: WEAVIATE_COLLECTION_KIND, + role: "relation", + label: "Collection", + labelPlural: "Collections", + hasColumns: true, + hasSource: true, + sourceLanguage: "json", + countIsListing: true, + }, +]); + +/** The deadline of a call outside a console request: connect, the tree, the Source, monitoring. */ +export const WEAVIATE_SURFACE_TIMEOUT_MS = 10_000; + +/** What a listing shows where a credential is configured: RBAC lists the collections the role may read. */ +export const VISIBLE_TO_CREDENTIAL = "the collections visible to this credential"; + +export const NO_COLLECTIONS_VISIBLE = + "No collections are visible to this credential: the server holds none, or its role may read none of them."; + +/** The reads the object surface sends, and nothing else. */ +export type WeaviateObjectOp = + | "schema" + | "collection" + | "objects" + | "aliases" + | "shards" + | "tenants" + | "aggregate" + | "graphql"; + +/** What one surface call runs with; index.ts builds one per call. */ +export interface WeaviateSurfaceContext { + readonly send: WeaviateSend; + readonly signal: AbortSignal; + readonly version: WeaviateVersion; + readonly paths: WeaviatePathState; + /** A credential is configured, so a listing holds what it may see rather than every collection. */ + readonly scoped: boolean; +} + +export type WeaviateObjectContext = WeaviateSurfaceContext; + +export function parseAnswer(answer: WeaviateAnswer, what: string): unknown { + try { + return JSON.parse(answer.text); + } catch { + throw new QueryError(`Weaviate's answer to ${what} is not JSON Studio can read.`, PROVIDER); + } +} + +/** + * Every class the credential may see, by name. Weaviate lists them in no stable order (measured: the same seeded + * server answered three orders), so they are sorted, and the tree, the Tables panel and their 200 bound agree. + */ +export async function readWeaviateClasses( + context: WeaviateSurfaceContext<"schema">, +): Promise { + const answer = await context.send({ op: "schema", params: {}, query: {} }, context.signal); + return [...readWeaviateSchema(parseAnswer(answer, "the schema"))].sort((a, b) => + a.name < b.name ? -1 : a.name > b.name ? 1 : 0, + ); +} + +function namedRefusal(error: unknown, name: string): unknown { + if (!(error instanceof QueryError) || Object.getPrototypeOf(error) !== QueryError.prototype) return error; + if (error.message.includes(name)) return error; + return new QueryError(`Collection ${JSON.stringify(name)}: ${error.message}`, PROVIDER); +} + +export async function readWeaviateCollection( + context: WeaviateSurfaceContext<"collection">, + name: string, +): Promise { + try { + const answer = await context.send({ op: "collection", params: { collection: name }, query: {} }, context.signal); + return readWeaviateClass(parseAnswer(answer, `the definition of collection ${JSON.stringify(name)}`), name); + } catch (error) { + throw namedRefusal(error, name); + } +} + +function requireKind(kind: string): void { + if (kind !== WEAVIATE_COLLECTION_KIND) throw new QueryError(`Weaviate declares no object kind "${kind}"`, PROVIDER); +} + +function collectionOf(path: readonly string[], kind: string): string { + requireKind(kind); + if (path.length !== 1) { + throw new QueryError(`A Weaviate "${kind}" path is [name], received ${JSON.stringify(path)}`, PROVIDER); + } + return path[0]; +} + +export async function countWeaviateObjects( + context: WeaviateSurfaceContext<"schema">, +): Promise> { + const classes = await readWeaviateClasses(context); + const count: KindCount = + classes.length === 0 + ? { unavailable: NO_COLLECTIONS_VISIBLE } + : context.scoped + ? { count: classes.length, sampledFrom: VISIBLE_TO_CREDENTIAL } + : { count: classes.length }; + return { [WEAVIATE_COLLECTION_KIND]: count }; +} + +/** The collections, names only: no row count and no status badge read on a listing (spec 4.3). */ +export async function listWeaviateObjects( + context: WeaviateSurfaceContext<"schema">, + kind: string, +): Promise { + requireKind(kind); + return (await readWeaviateClasses(context)).map((definition) => ({ + path: [definition.name], + name: definition.name, + kind: WEAVIATE_COLLECTION_KIND, + })); +} + +/** One object's vector lengths, by vector name: what spells a dimension the schema does not declare. */ +async function sampledDimensions( + context: WeaviateSurfaceContext<"objects">, + definition: WeaviateClass, +): Promise> { + if (definition.multiTenant || definition.vectors.length === 0) return new Map(); + const answer = await context.send( + { op: "objects", params: {}, query: { class: definition.name, limit: "1", include: "vector" } }, + context.signal, + ); + const parsed = parseAnswer(answer, `an object of ${JSON.stringify(definition.name)}`); + const objects = typeof parsed === "object" && parsed !== null ? (parsed as { objects?: unknown }).objects : undefined; + const first = Array.isArray(objects) && objects.length > 0 ? (objects[0] as Record) : undefined; + const dimensions = new Map(); + if (first === undefined) return dimensions; + if (Array.isArray(first.vector) && first.vector.length > 0) dimensions.set("", first.vector.length); + if (typeof first.vectors === "object" && first.vectors !== null) { + for (const [name, value] of Object.entries(first.vectors as Record)) { + if (Array.isArray(value) && value.length > 0) dimensions.set(name, value.length); + } + } + return dimensions; +} + +/** A collection's columns and indexes: its definition, and one object read for its vectors' dimensions. */ +export async function describeWeaviateObject( + context: WeaviateSurfaceContext<"collection" | "objects">, + path: readonly string[], + kind: string, +): Promise { + const definition = await readWeaviateCollection(context, collectionOf(path, kind)); + const dimensions = await sampledDimensions(context, definition); + return { + path: [definition.name], + columns: [...weaviateColumns(definition, dimensions)], + indexes: [...weaviateIndexes(definition)], + foreignKeys: [], + }; +} + +/** Every listed collection's columns from the one schema read: one round trip, the caller's limit applied after. */ +export async function describeWeaviateObjects( + context: WeaviateSurfaceContext<"schema">, + kind: string, + limit?: number, +): Promise { + requireKind(kind); + const classes = await readWeaviateClasses(context); + const cut = limit !== undefined && classes.length > limit; + const details = (cut ? classes.slice(0, limit) : classes).map( + (definition): ObjectDetail => ({ + path: [definition.name], + columns: [...weaviateColumns(definition)], + indexes: [...weaviateIndexes(definition)], + foreignKeys: [], + }), + ); + return cut ? { details, truncated: { limit, reason: callerBoundTruncationReason(limit) } } : { details }; +} + +/** The aggregate model of a plain count, the one both encoders write for the Source and the Tables panel. */ +function countModel(collection: string): WeaviateSearchModel { + return { + op: "aggregate", + collection, + tenant: null, + where: null, + limit: null, + offset: null, + autoLimit: null, + consistencyLevel: null, + returnProperties: null, + returnMetadata: [], + query: null, + queryProperties: null, + fusionType: null, + maxVectorDistance: null, + vector: null, + id: null, + targetVector: null, + distance: null, + certainty: null, + groupBy: null, + }; +} + +function countOf(parsed: unknown, path: "rest" | "graphql", collection: string): number | null { + if (typeof parsed !== "object" || parsed === null) return null; + if (path === "rest") { + const count = (parsed as { count?: unknown }).count; + return typeof count === "number" ? count : null; + } + const rows = (parsed as { data?: { Aggregate?: Record } }).data?.Aggregate?.[collection]; + const first = Array.isArray(rows) ? (rows[0] as { meta?: { count?: unknown } } | undefined) : undefined; + return typeof first?.meta?.count === "number" ? first.meta.count : null; +} + +/** + * A single-tenant collection's exact object count, aggregate `meta.count`, over the path the version decides (spec + * 4.3). A failure answers null with no second attempt: a count is a detail, never the reason a Source fails. + */ +export async function countWeaviateCollection( + context: WeaviateSurfaceContext<"aggregate" | "graphql">, + definition: WeaviateClass, +): Promise { + if (definition.multiTenant) return null; + const path = context.paths.get("other") ?? initialPath(context.version, "other"); + try { + const answer = + path === "rest" + ? await context.send( + { op: "aggregate", params: { collection: definition.name }, query: {}, body: "{}" }, + context.signal, + ) + : await context.send( + { + op: "graphql", + params: {}, + query: {}, + body: encodeGraphql(countModel(definition.name), weaviateCollectionFacts(definition)), + }, + context.signal, + ); + return countOf(JSON.parse(answer.text), path, definition.name); + } catch { + return null; + } +} + +/** + * The Source: the definition, the aliases, then for a single-tenant collection its shards and its exact count, and + * for a multi-tenant one its tenants with their statuses, which reading never changes (spec A.4). + */ +export async function readWeaviateObjectSource( + context: WeaviateObjectContext, + path: readonly string[], + kind: string, + limit?: number, +): Promise { + const name = collectionOf(path, kind); + const definition = await readWeaviateCollection(context, name); + const aliases = parseAnswer( + await context.send({ op: "aliases", params: {}, query: {} }, context.signal), + "the alias list", + ); + const params = { collection: definition.name }; + let shards: unknown = null; + let tenants: unknown = null; + let count: number | null = null; + if (definition.multiTenant) { + tenants = parseAnswer( + await context.send({ op: "tenants", params, query: {} }, context.signal), + `the tenants of ${JSON.stringify(definition.name)}`, + ); + } else { + shards = parseAnswer( + await context.send({ op: "shards", params, query: {} }, context.signal), + `the shards of ${JSON.stringify(definition.name)}`, + ); + count = await countWeaviateCollection(context, definition); + } + return { + path: [definition.name], + kind, + parts: weaviateSourceParts({ definition, aliases, shards, tenants, count }, limit), + }; +} diff --git a/src/lib/db/providers/vector/weaviate/request.ts b/src/lib/db/providers/vector/weaviate/request.ts new file mode 100644 index 0000000000..7c79391a47 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/request.ts @@ -0,0 +1,682 @@ +import { parseConsole, type ConsoleRequest, ConsoleRefusal, consoleTokens } from "@/lib/db/console/parser"; +import { RequestRefusal } from "@/lib/db/console/dialect"; +import { utf8ByteLength } from "@/lib/db/console/bounds"; +import { + checkIntRange, + isTaggedFloat, + isTaggedInt, + type TaggedJson, + type TaggedObject, + taggedNumber, + toJsonText, +} from "@/lib/db/console/tagged-json"; +import { checkDenseElements, vectorNumbers } from "@/lib/db/vector/dense"; +import type { QueryWarning } from "@/lib/types"; +import type { WeaviateConsoleOp, WeaviateEncodedOp } from "./client"; +import { + refusedRouteSentence, + WEAVIATE_BOUNDS, + WEAVIATE_CONSOLE, + WEAVIATE_ENUMS, + WEAVIATE_KEYS, + WEAVIATE_REFUSED_KEYS, + WEAVIATE_ROUTES, + type WeaviateObjectName, + type WeaviateRoute, +} from "./routes"; +import type { WeaviateCollectionFacts } from "./schema"; + +/** + * The Weaviate console's request rules (#1566 spec 5.1, W1, W3, W4, W6): one console text to one typed request, in + * the phases every vector console validates in. + * + * Phase 0 reads the text alone and makes no call: the grammar (`parseWeaviateRequest`), then every rule that needs no + * schema (`weaviatePhase0`): names, closed keys at every level, ids, the inference rule, enumerations, bounds, and the + * defaults written in, so the REST and the GraphQL paths answer the same rows. Phase 1 (`weaviatePhase1`) reads the + * collection's definition: the tenancy rule, every property and vector the request names, and the query vector's + * numbers. The tenant's status (W6) is read by `execute.ts` after phase 1, since only the server holds it. + * + * Nothing here sends anything. The first two functions are what the browser runs before a statement leaves it. + */ + +/** Weaviate's own name rules (`entities/schema/validation.go`, v1.40.2). A class name's first letter is capitalised by the server. */ +const CLASS_NAME = /^[A-Za-z][_0-9A-Za-z]{0,254}$/; +const TENANT_NAME = /^[A-Za-z0-9_-]{1,64}$/; +const PROPERTY_NAME = /^[_A-Za-z][_0-9A-Za-z]{0,230}$/; +/** A BM25 or hybrid property with an optional boost, `title^2`. */ +const BOOSTED_PROPERTY = /^([_A-Za-z][_0-9A-Za-z]{0,230})(?:\^[0-9]+(?:\.[0-9]+)?)?$/; +const VECTOR_NAME = /^[_A-Za-z][_0-9A-Za-z]{0,230}$/; +const UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/; +const SHOWN = 80; + +/** A search's target: the vector it searches, or none for BM25. */ +export type SearchKind = "bm25" | "hybrid" | "near-vector" | "near-object"; + +const SEARCH_KIND: Readonly, SearchKind>> = { + search_bm25: "bm25", + search_hybrid: "hybrid", + search_near_vector: "near-vector", + search_near_object: "near-object", +}; + +/** + * One search or aggregate as both encoders read it (spec 5.3). Every value is as the user wrote it, already checked: + * a number keeps its literal text, so neither path rounds it. + */ +export interface WeaviateSearchModel { + readonly op: WeaviateEncodedOp; + readonly collection: string; + readonly tenant: string | null; + readonly where: TaggedObject | null; + readonly limit: TaggedJson | null; + readonly offset: TaggedJson | null; + readonly autoLimit: TaggedJson | null; + readonly consistencyLevel: string | null; + /** The properties asked for, or null for every plain property. */ + readonly returnProperties: readonly string[] | null; + readonly returnMetadata: readonly string[]; + /** BM25 and hybrid. */ + readonly query: string | null; + readonly queryProperties: readonly string[] | null; + /** Hybrid. */ + readonly fusionType: string | null; + readonly maxVectorDistance: TaggedJson | null; + /** near-vector: the vector's numbers as written. */ + readonly vector: readonly TaggedJson[] | null; + /** near-object. */ + readonly id: string | null; + readonly targetVector: string | null; + readonly distance: TaggedJson | null; + readonly certainty: TaggedJson | null; + /** Aggregate. */ + readonly groupBy: string | null; +} + +/** A request phase 0 accepted. */ +export interface WeaviatePlan { + readonly request: ConsoleRequest; + readonly route: WeaviateRoute; + /** The collection the request reads, its first letter as the server spells it; null where it names none. */ + readonly collection: string | null; + /** The tenant the request names, in the query string or the body; null where it names none. */ + readonly tenant: string | null; + /** The query keys, with the defaults written in. */ + readonly query: Readonly>; + /** The body with the defaults written in, or null where the route takes none. */ + readonly body: TaggedObject | null; + /** The search model of a search or aggregate route; null for every other route. */ + readonly search: WeaviateSearchModel | null; + readonly warnings: readonly QueryWarning[]; +} + +function refuse(message: string, key: string | null = null): never { + throw new RequestRefusal(message, 0, key); +} + +function refuseLater(message: string, key: string | null = null): never { + throw new RequestRefusal(message, 1, key); +} + +function shown(text: string): string { + return JSON.stringify(text.length > SHOWN ? `${text.slice(0, SHOWN)}...` : text); +} + +function kindOf(value: TaggedJson | undefined): string { + if (value === undefined) return "nothing"; + if (value === null) return "null"; + if (Array.isArray(value)) return "a list"; + if (isTaggedInt(value) || isTaggedFloat(value)) return "a number"; + if (typeof value === "object") return "an object"; + return typeof value === "boolean" ? "a boolean" : `a ${typeof value}`; +} + +const isObject = (value: TaggedJson | undefined): value is TaggedObject => + typeof value === "object" && value !== null && !Array.isArray(value) && !isTaggedInt(value) && !isTaggedFloat(value); + +const has = (object: TaggedObject, key: string): boolean => Object.hasOwn(object, key) && object[key] !== null; + +function objectAt(value: TaggedJson | undefined, where: string): TaggedObject { + if (!isObject(value)) return refuse(`${where} must be an object, found ${kindOf(value)}.`, where); + return value; +} + +function listAt(value: TaggedJson | undefined, where: string): readonly TaggedJson[] { + if (!Array.isArray(value)) return refuse(`${where} must be a list, found ${kindOf(value)}.`, where); + return value; +} + +function stringAt(value: TaggedJson | undefined, where: string): string { + if (typeof value !== "string") return refuse(`${where} must be a string, found ${kindOf(value)}.`, where); + return value; +} + +function booleanAt(value: TaggedJson | undefined, where: string): boolean { + if (typeof value !== "boolean") return refuse(`${where} must be true or false, found ${kindOf(value)}.`, where); + return value; +} + +/** The object's keys against the closed set of its schema: a refused key with its reason, an unknown key and a missing required key, each by name. */ +function closed(object: TaggedObject, name: WeaviateObjectName, where: string): void { + const set = WEAVIATE_KEYS[name]; + const keys: readonly string[] = set.keys; + for (const key of Object.keys(object)) { + if (keys.includes(key)) continue; + if (Object.hasOwn(WEAVIATE_REFUSED_KEYS, key)) { + refuse(`${where} takes no key ${shown(key)} in this console: ${WEAVIATE_REFUSED_KEYS[key]}.`, key); + } + refuse(`${where} takes no key ${shown(key)}: Weaviate reads ${keys.join(", ")} there and nothing else.`, key); + } + for (const key of set.required) { + if (!has(object, key)) refuse(`${where} needs the key ${key}.`, key); + } +} + +function integerAt(value: TaggedJson | undefined, where: string, min: number, max: number): number { + if (value === undefined || !isTaggedInt(value)) { + return refuse(`${where} must be an integer, found ${kindOf(value)}.`, where); + } + if (!checkIntRange(value, "safe") || Number(value.digits) < min || Number(value.digits) > max) { + return refuse(`${where} is ${value.digits}; it takes an integer from ${min} to ${max}.`, where); + } + return Number(value.digits); +} + +function numberAt(value: TaggedJson | undefined, where: string): number { + if (value !== undefined && isTaggedFloat(value)) return Number(value.text); + if (value !== undefined && isTaggedInt(value)) return Number(value.digits); + return refuse(`${where} must be a number, found ${kindOf(value)}.`, where); +} + +function wordAt(value: TaggedJson | undefined, where: string, words: readonly string[]): string { + if (typeof value !== "string" || !words.includes(value)) { + return refuse( + `${where} takes one of ${words.join(", ")}, not ${typeof value === "string" ? shown(value) : kindOf(value)}.`, + where, + ); + } + return value; +} + +/** Why a collection or alias name cannot reach a path or a GraphQL document, or undefined (spec W1). */ +export function weaviateClassNameRefusal(name: string): string | undefined { + if (CLASS_NAME.test(name)) return undefined; + if (name === "") return "A collection name cannot be empty."; + return `${shown(name)} is not a Weaviate collection name: it starts with a letter and holds only letters, digits and _, at most 255 characters.`; +} + +export function weaviateTenantNameRefusal(name: string): string | undefined { + if (TENANT_NAME.test(name)) return undefined; + return `${shown(name)} is not a Weaviate tenant name: it holds only letters, digits, - and _, 1 to 64 characters.`; +} + +/** The name as the server spells it: the first letter capitalised, as Weaviate does with every class name. */ +export function serverClassName(name: string): string { + return `${name.charAt(0).toUpperCase()}${name.slice(1)}`; +} + +function classNameAt(value: string, where: string): string { + const refusal = weaviateClassNameRefusal(value); + return refusal === undefined ? serverClassName(value) : refuse(`${where}: ${refusal}`, where); +} + +function tenantAt(value: TaggedJson | string | undefined, where: string): string { + const name = typeof value === "string" ? value : stringAt(value, where); + const refusal = weaviateTenantNameRefusal(name); + return refusal === undefined ? name : refuse(`${where}: ${refusal}`, where); +} + +function propertyNameAt(value: TaggedJson | string | undefined, where: string): string { + const name = typeof value === "string" ? value : stringAt(value, where); + if (!PROPERTY_NAME.test(name)) { + refuse(`${where} is ${shown(name)}, which is not a Weaviate property name.`, where); + } + return name; +} + +function uuidAt(value: TaggedJson | string | undefined, where: string): string { + const id = typeof value === "string" ? value : stringAt(value, where); + if (!UUID.test(id)) refuse(`${where} is ${shown(id)}, which is not a UUID: Weaviate's object ids are UUIDs.`, where); + return id; +} + +function propertyListAt(value: TaggedJson | undefined, where: string, boosted: boolean): readonly string[] { + const list = listAt(value, where); + if (list.length === 0 || list.length > WEAVIATE_BOUNDS.maxPropertyList) { + refuse(`${where} holds ${list.length} properties; it takes 1 to ${WEAVIATE_BOUNDS.maxPropertyList}.`, where); + } + const seen = new Set(); + return list.map((entry, index) => { + const name = stringAt(entry, `${where}[${index}]`); + const match = boosted ? BOOSTED_PROPERTY.exec(name) : PROPERTY_NAME.test(name) ? [name, name] : null; + if (match === null) refuse(`${where}[${index}] is ${shown(name)}, which is not a Weaviate property name.`, where); + if (seen.has(name)) refuse(`${where} names ${shown(name)} twice.`, where); + seen.add(name); + return name; + }); +} + +/** What phase 0 counts while it walks a where filter. */ +interface FilterWalk { + conditions: number; +} + +const LOGICAL = new Set(["And", "Or", "Not"]); +const VALUE_KEYS: Readonly> = { + valueInt: "int", + valueNumber: "number", + valueBoolean: "boolean", + valueString: "text", + valueText: "text", + valueDate: "date", + valueIntArray: "int", + valueNumberArray: "number", + valueBooleanArray: "boolean", + valueStringArray: "text", + valueTextArray: "text", + valueDateArray: "date", + valueGeoRange: "geo", +}; + +function checkScalar(value: TaggedJson, kind: string, where: string): void { + if (kind === "int") integerAt(value, where, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); + else if (kind === "number") numberAt(value, where); + else if (kind === "boolean") booleanAt(value, where); + else stringAt(value, where); +} + +function readGeoRange(value: TaggedJson, where: string): void { + const range = objectAt(value, where); + closed(range, "WhereFilterGeoRange", where); + const coordinates = objectAt(range.geoCoordinates, `${where}.geoCoordinates`); + closed(coordinates, "GeoCoordinates", `${where}.geoCoordinates`); + const latitude = numberAt(coordinates.latitude, `${where}.geoCoordinates.latitude`); + const longitude = numberAt(coordinates.longitude, `${where}.geoCoordinates.longitude`); + if (latitude < -90 || latitude > 90) refuse(`${where}.geoCoordinates.latitude is outside -90 to 90.`, where); + if (longitude < -180 || longitude > 180) refuse(`${where}.geoCoordinates.longitude is outside -180 to 180.`, where); + const distance = objectAt(range.distance, `${where}.distance`); + closed(distance, "GeoDistance", `${where}.distance`); + if (numberAt(distance.max, `${where}.distance.max`) < 0) refuse(`${where}.distance.max cannot be negative.`, where); +} + +/** A where filter (spec W4): every level closed, every operator's operands or path and one value, bounded. */ +function readWhere(value: TaggedJson, where: string, walk: FilterWalk, depth: number): void { + if (depth > WEAVIATE_BOUNDS.maxFilterDepth) { + refuse(`${where} nests filters deeper than ${WEAVIATE_BOUNDS.maxFilterDepth} levels.`, "where"); + } + walk.conditions += 1; + if (walk.conditions > WEAVIATE_BOUNDS.maxFilterConditions) { + refuse(`The filter holds more than ${WEAVIATE_BOUNDS.maxFilterConditions} conditions.`, "where"); + } + const filter = objectAt(value, where); + closed(filter, "WhereFilter", where); + const operator = wordAt(filter.operator, `${where}.operator`, WEAVIATE_ENUMS.operator); + const values = Object.keys(filter).filter((key) => Object.hasOwn(VALUE_KEYS, key) && has(filter, key)); + if (LOGICAL.has(operator)) { + if (has(filter, "path") || values.length > 0) { + refuse(`${where}: ${operator} takes operands only, never a path or a value.`, where); + } + const operands = listAt(filter.operands, `${where}.operands`); + if (operands.length === 0) refuse(`${where}.operands: ${operator} needs at least one operand.`, where); + if (operator === "Not" && operands.length !== 1) refuse(`${where}.operands: Not takes exactly one operand.`, where); + operands.forEach((operand, index) => { + readWhere(operand, `${where}.operands[${index}]`, walk, depth + 1); + }); + return; + } + if (has(filter, "operands")) refuse(`${where}: ${operator} takes a path and a value, never operands.`, where); + const path = listAt(filter.path, `${where}.path`); + if (path.length === 0) refuse(`${where}.path names no property.`, where); + path.forEach((segment, index) => { + const name = stringAt(segment, `${where}.path[${index}]`); + // A path through a cross-reference names the property, the target class, then the target's property. + if (!PROPERTY_NAME.test(name) && !CLASS_NAME.test(name)) { + refuse(`${where}.path[${index}] is ${shown(name)}, which is not a property or class name.`, where); + } + }); + if (values.length !== 1) { + refuse( + `${where}: ${operator} takes exactly one value key (valueText, valueInt and the rest), found ${values.length}.`, + where, + ); + } + const key = values[0]; + const kind = VALUE_KEYS[key]; + if (operator === "WithinGeoRange" ? key !== "valueGeoRange" : key === "valueGeoRange") { + refuse(`${where}: WithinGeoRange takes valueGeoRange, and valueGeoRange takes WithinGeoRange.`, where); + } + if (operator === "IsNull" && key !== "valueBoolean") refuse(`${where}: IsNull takes valueBoolean.`, where); + if (kind === "geo") readGeoRange(filter[key], `${where}.${key}`); + else if (key.endsWith("Array")) { + const entries = listAt(filter[key], `${where}.${key}`); + if (entries.length > WEAVIATE_BOUNDS.maxFilterListEntries) { + refuse(`${where}.${key} holds ${entries.length} entries, above ${WEAVIATE_BOUNDS.maxFilterListEntries}.`, where); + } + entries.forEach((entry, index) => { + checkScalar(entry, kind, `${where}.${key}[${index}]`); + }); + } else checkScalar(filter[key], kind, `${where}.${key}`); +} + +function readFilter(value: TaggedJson): TaggedObject { + const bytes = utf8ByteLength(toJsonText(value)); + if (bytes > WEAVIATE_BOUNDS.maxFilterBytes) { + refuse(`The filter is ${bytes} bytes, above the bound of ${WEAVIATE_BOUNDS.maxFilterBytes}.`, "where"); + } + readWhere(value, "where", { conditions: 0 }, 1); + return value as TaggedObject; +} + +const integer = (value: number): TaggedJson => taggedNumber(String(value)); + +function withDefaults(body: TaggedObject, defaults: Readonly>): TaggedObject { + const copy: Record = Object.create(null); + for (const key of Object.keys(body)) if (body[key] !== null) copy[key] = body[key]; + for (const [key, value] of Object.entries(defaults)) if (!Object.hasOwn(copy, key)) copy[key] = value; + return Object.freeze(copy); +} + +/** The rows a request asks for: its limit plus its offset, at most the console's bound (below QUERY_MAXIMUM_RESULTS). */ +function rowsAt(limit: TaggedJson | undefined, offset: TaggedJson | undefined, defaultLimit: number): void { + const rows = limit === undefined ? defaultLimit : integerAt(limit, "limit", 1, WEAVIATE_BOUNDS.maxRows); + const skip = offset === undefined ? 0 : integerAt(offset, "offset", 0, WEAVIATE_BOUNDS.maxRows); + if (rows + skip > WEAVIATE_BOUNDS.maxRows) { + refuse(`limit plus offset is ${rows + skip}, above the bound of ${WEAVIATE_BOUNDS.maxRows} rows.`, "limit"); + } +} + +/** Phase 0 of the four searches: the closed body, the inference rule, every value, the defaults (spec 5.1). */ +function readSearchBody(route: WeaviateRoute, body: TaggedObject, collection: string): WeaviateSearchModel { + const schema = route.schema as WeaviateObjectName; + closed(body, schema, "The body"); + const value = (key: string): TaggedJson | undefined => (has(body, key) ? body[key] : undefined); + rowsAt(value("limit"), value("offset"), WEAVIATE_BOUNDS.defaultSearchLimit); + if (value("autoLimit") !== undefined) integerAt(body.autoLimit, "autoLimit", 1, WEAVIATE_BOUNDS.maxRows); + const returnProperties = + value("returnProperties") === undefined ? null : propertyListAt(body.returnProperties, "returnProperties", false); + const returnMetadata = + value("returnMetadata") === undefined + ? [] + : listAt(body.returnMetadata, "returnMetadata").map((entry, index) => + wordAt(entry, `returnMetadata[${index}]`, WEAVIATE_ENUMS.returnMetadata), + ); + const consistencyLevel = + value("consistencyLevel") === undefined + ? null + : wordAt(body.consistencyLevel, "consistencyLevel", WEAVIATE_ENUMS.consistencyLevel); + const tenant = value("tenant") === undefined ? null : tenantAt(body.tenant, "tenant"); + const where = value("where") === undefined ? null : readFilter(body.where); + const op = route.op as Exclude; + const kind = SEARCH_KIND[op]; + let query: string | null = null; + let queryProperties: readonly string[] | null = null; + if (kind === "bm25" || kind === "hybrid") { + query = stringAt(body.query, "query"); + if (query.trim() === "") refuse("query is empty: a keyword search needs words.", "query"); + if (value("queryProperties") !== undefined) + queryProperties = propertyListAt(body.queryProperties, "queryProperties", true); + } + if (kind === "hybrid") { + // The server's default alpha is 0.7, which embeds the query text with the collection's vectorizer (spec W3). + if (numberAt(body.alpha, "alpha") !== 0) { + refuse( + 'alpha must be 0 in this console: any other value makes Weaviate embed the query text with the collection\'s vectorizer, which sends it to a model provider. Write "alpha": 0 for a keyword-only hybrid search.', + "alpha", + ); + } + } + const fusionType = + value("fusionType") === undefined ? null : wordAt(body.fusionType, "fusionType", WEAVIATE_ENUMS.fusionType); + const maxVectorDistance = value("maxVectorDistance") ?? null; + if (maxVectorDistance !== null) numberAt(maxVectorDistance, "maxVectorDistance"); + const targetVector = value("targetVector") === undefined ? null : stringAt(body.targetVector, "targetVector"); + if (targetVector !== null && !VECTOR_NAME.test(targetVector)) { + refuse(`targetVector is ${shown(targetVector)}, which is not a Weaviate vector name.`, "targetVector"); + } + const distance = value("distance") ?? null; + const certainty = value("certainty") ?? null; + if (distance !== null) numberAt(distance, "distance"); + if (certainty !== null) { + const level = numberAt(certainty, "certainty"); + if (level < 0 || level > 1) refuse("certainty takes a number from 0 to 1.", "certainty"); + } + if (distance !== null && certainty !== null) refuse("A search takes distance or certainty, not both.", "distance"); + let vector: readonly TaggedJson[] | null = null; + if (kind === "near-vector") { + vector = listAt(body.vector, "vector"); + if (vector.some((element) => Array.isArray(element))) { + refuse("vector is a list of lists: this console searches with one dense vector, a list of numbers.", "vector"); + } + if (vector.length === 0 || vector.length > WEAVIATE_BOUNDS.maxDenseSize) { + refuse(`vector holds ${vector.length} numbers; it takes 1 to ${WEAVIATE_BOUNDS.maxDenseSize}.`, "vector"); + } + vector.forEach((element, index) => { + numberAt(element, `vector[${index}]`); + }); + } + const id = kind === "near-object" ? uuidAt(body.id, "id") : null; + return { + op, + collection, + tenant, + where, + limit: value("limit") ?? integer(WEAVIATE_BOUNDS.defaultSearchLimit), + offset: value("offset") ?? null, + autoLimit: value("autoLimit") ?? null, + consistencyLevel, + returnProperties, + returnMetadata, + query, + queryProperties, + fusionType, + maxVectorDistance, + vector, + id, + targetVector, + distance, + certainty, + groupBy: null, + }; +} + +function readAggregateBody(body: TaggedObject, collection: string): WeaviateSearchModel { + closed(body, "AggregateRequest", "The body"); + const value = (key: string): TaggedJson | undefined => (has(body, key) ? body[key] : undefined); + if (value("returnMetrics") !== undefined) { + listAt(body.returnMetrics, "returnMetrics").forEach((entry, index) => { + wordAt(entry, `returnMetrics[${index}]`, WEAVIATE_ENUMS.returnMetrics); + }); + } + const groupBy = value("groupBy") === undefined ? null : propertyNameAt(body.groupBy, "groupBy"); + if (value("limit") !== undefined) { + if (groupBy === null) + refuse("limit bounds the groups of a groupBy; an aggregate without groupBy has one row.", "limit"); + integerAt(body.limit, "limit", 1, WEAVIATE_BOUNDS.maxRows); + } + return { + op: "aggregate", + collection, + tenant: value("tenant") === undefined ? null : tenantAt(body.tenant, "tenant"), + where: value("where") === undefined ? null : readFilter(body.where), + // Both paths answer at most 100 groups when no limit is given (measured on 1.37.4 and 1.40.2), so the bound is + // written out and results.ts can say when the groups reached it. + limit: value("limit") ?? (groupBy === null ? null : integer(WEAVIATE_BOUNDS.defaultGroupsLimit)), + offset: null, + autoLimit: null, + consistencyLevel: null, + returnProperties: null, + returnMetadata: [], + query: null, + queryProperties: null, + fusionType: null, + maxVectorDistance: null, + vector: null, + id: null, + targetVector: null, + distance: null, + certainty: null, + groupBy, + }; +} + +/** The grammar's verdict on one console text, with the console's own sentence for a route it does not run. */ +export function parseWeaviateRequest(text: string): ConsoleRequest { + try { + return parseConsole(WEAVIATE_CONSOLE, WEAVIATE_ROUTES, text); + } catch (error) { + if (!(error instanceof ConsoleRefusal) || (error.reason !== "unknown-route" && error.reason !== "unknown-method")) { + throw error; + } + const { method, target } = consoleTokens(WEAVIATE_CONSOLE, text).request; + if (target === "") throw error; + throw new ConsoleRefusal(error.reason, refusedRouteSentence(method, target), error.line, error.column); + } +} + +/** Phase 0 of `GET /v1/objects`: the class, the paging pair and the defaults (spec 5.1). */ +function readObjectsQuery(query: Readonly>): Readonly> { + if (!Object.hasOwn(query, "class")) { + refuse("GET /v1/objects needs ?class=: without it Weaviate answers no objects.", "class"); + } + if (Object.hasOwn(query, "after") && (Object.hasOwn(query, "offset") || Object.hasOwn(query, "sort"))) { + refuse("after pages by id, so it takes neither offset nor sort.", "after"); + } + if (Object.hasOwn(query, "order") && !Object.hasOwn(query, "sort")) refuse("order needs sort.", "order"); + if (Object.hasOwn(query, "sort")) { + query.sort.split(",").forEach((name, index) => { + propertyNameAt(name, `sort[${index}]`); + }); + } + if (Object.hasOwn(query, "after")) uuidAt(query.after, "after"); + if (Object.hasOwn(query, "tenant")) tenantAt(query.tenant, "tenant"); + const limit = Object.hasOwn(query, "limit") ? Number(query.limit) : WEAVIATE_BOUNDS.defaultObjectsLimit; + if (Object.hasOwn(query, "offset") && !/^(0|[1-9][0-9]*)$/.test(query.offset)) { + refuse(`offset is ${shown(query.offset)}; it takes an integer from 0 to ${WEAVIATE_BOUNDS.maxRows}.`, "offset"); + } + const offset = Object.hasOwn(query, "offset") ? Number(query.offset) : 0; + if (limit > WEAVIATE_BOUNDS.maxRows || limit + offset > WEAVIATE_BOUNDS.maxRows) { + refuse(`limit plus offset is ${limit + offset}, above the bound of ${WEAVIATE_BOUNDS.maxRows} rows.`, "limit"); + } + return Object.freeze({ ...query, limit: String(limit) }); +} + +/** + * Every rule that needs neither the schema nor the server. Throws a phase 0 `RequestRefusal` naming the first rule + * the request breaks; makes no call. + */ +export function weaviatePhase0(request: ConsoleRequest): WeaviatePlan { + const route = WEAVIATE_ROUTES.find((entry) => entry.op === request.route.op) as WeaviateRoute; + const params = request.params; + let collection: string | null = Object.hasOwn(params, "collection") + ? classNameAt(params.collection, "collection") + : null; + if (Object.hasOwn(params, "alias")) classNameAt(params.alias, "alias"); + let tenant: string | null = Object.hasOwn(params, "tenant") ? tenantAt(params.tenant, "tenant") : null; + if (Object.hasOwn(params, "id")) uuidAt(params.id, "id"); + let query = request.query; + if (route.op === "objects") { + query = readObjectsQuery(query); + collection = classNameAt(query.class, "class"); + } + if (Object.hasOwn(query, "output") && query.output.includes(",")) + refuse("output takes one of minimal or verbose.", "output"); + if (tenant === null && Object.hasOwn(query, "tenant")) tenant = tenantAt(query.tenant, "tenant"); + let body: TaggedObject | null = null; + let search: WeaviateSearchModel | null = null; + if (route.schema === "AggregateRequest") { + search = readAggregateBody(request.body, collection as string); + body = search.limit === null ? request.body : withDefaults(request.body, { limit: search.limit }); + } else if (route.schema !== null) { + search = readSearchBody(route, request.body, collection as string); + body = withDefaults(request.body, { limit: search.limit as TaggedJson }); + } + if (search !== null && search.tenant !== null) tenant = search.tenant; + return { request, route, collection, tenant, query, body, search, warnings: [] }; +} + +function present(facts: WeaviateCollectionFacts): string { + const names = facts.vectors.map((vector) => (vector.name === "" ? "the unnamed vector" : vector.name)); + return names.length === 0 ? "it has no vector" : `it has ${names.join(", ")}`; +} + +/** The vector a search targets: the one it names, or the collection's only vector. */ +function targetOf(plan: WeaviatePlan, facts: WeaviateCollectionFacts): string | null { + const search = plan.search as WeaviateSearchModel; + // A BM25 search reads no vector, and its body takes no targetVector (phase 0 refuses one), so none is sent. + if (search.op === "search_bm25") return null; + if (search.targetVector !== null) { + if (!facts.vectors.some((vector) => vector.name === search.targetVector)) { + refuseLater( + `targetVector names ${shown(search.targetVector)}, which is no vector of ${shown(facts.name)}: ${present(facts)}.`, + "targetVector", + ); + } + return search.targetVector; + } + if (facts.vectors.length === 0) { + refuseLater(`The collection ${shown(facts.name)} has no vector to search.`, "targetVector"); + } + if (facts.vectors.length > 1) { + refuseLater( + `The collection ${shown(facts.name)} has more than one vector, so the search needs targetVector: ${present(facts)}.`, + "targetVector", + ); + } + return facts.vectors[0].name; +} + +/** + * Phase 1: the rules that read the collection's definition, described for this request. Throws a phase 1 + * `RequestRefusal`; makes no call. Answers the plan with the target vector's name filled in for the encoders. + */ +/** The routes that read a whole multi-tenant collection's own record, and so name no tenant. */ +const COLLECTION_RECORD_OPS: ReadonlySet = new Set(["collection", "tenants", "collection_nodes"]); + +export function weaviatePhase1(plan: WeaviatePlan, facts: WeaviateCollectionFacts): WeaviatePlan { + if (facts.multiTenant && plan.tenant === null && !COLLECTION_RECORD_OPS.has(plan.route.op)) { + refuseLater( + `The collection ${shown(facts.name)} is multi-tenant, so the request needs a tenant${plan.route.body === "none" ? " (?tenant=...)" : ' ("tenant": "...")'}. Nothing was read: GET /v1/schema/${facts.name}/tenants lists its tenants and which are HOT, without waking any.`, + "tenant", + ); + } + if (!facts.multiTenant && plan.tenant !== null && plan.route.op !== "tenant") { + refuseLater(`The collection ${shown(facts.name)} is not multi-tenant, so the request takes no tenant.`, "tenant"); + } + const search = plan.search; + if (search === null) return plan; + const known = new Set([...facts.plainProperties, ...facts.referenceProperties]); + const check = (names: readonly string[] | null, where: string, strip: boolean) => { + for (const written of names ?? []) { + const name = strip ? written.replace(/\^.*$/, "") : written; + if (!known.has(name)) + refuseLater(`${where} names ${shown(name)}, which is no property of ${shown(facts.name)}.`, where); + if (facts.referenceProperties.has(name)) { + refuseLater( + `${where} names ${shown(name)}, a cross-reference: returning cross-references is outside this version of the console.`, + where, + ); + } + } + }; + check(search.returnProperties, "returnProperties", false); + check(search.queryProperties, "queryProperties", true); + if (search.groupBy !== null) check([search.groupBy], "groupBy", false); + if (search.op === "aggregate") return plan; + const target = targetOf(plan, facts); + // Hybrid at alpha 0 opens on a vectorized collection too (spec W3, WM1). MEASURED on 2026-10-23 with the egress + // fixture, a collection whose `text2vec-openai` base URL is a listener on the bridge gateway: hybrid at alpha 0 sent + // the listener nothing over REST on 1.40.2 and over GraphQL on 1.37.4 and 1.40.2, while alpha 0.5 and a nearText + // control each sent it one request. A later release that embeds at alpha 0 brings this refusal back here. + if (search.vector !== null) { + const numbers = vectorNumbers( + { name: target ?? "", kind: "dense", dtype: "float32", dimension: null }, + search.vector, + ); + if (!Array.isArray(numbers)) refuseLater(`vector: ${(numbers as { sentence: string }).sentence}`, "vector"); + const refused = checkDenseElements( + { name: target ?? "", kind: "dense", dtype: "float32", dimension: null }, + numbers as readonly number[], + ); + if (refused !== null) refuseLater(`vector: ${refused.sentence}`, "vector"); + } + return { ...plan, search: { ...search, targetVector: target === "" ? null : target } }; +} diff --git a/src/lib/db/providers/vector/weaviate/rest-client.ts b/src/lib/db/providers/vector/weaviate/rest-client.ts new file mode 100644 index 0000000000..408bd7f1cd --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/rest-client.ts @@ -0,0 +1,198 @@ +/** + * The Weaviate REST client (#1566 spec 3.2): the one implementation of `WeaviateClient`, and the only file of the + * provider that builds a path (spec W7). + * + * It is given the route table when it is built and sends through the shared transport, one keep-alive Agent per + * connection with the `Authorization` header set once, so every rule of that transport holds for every request: no + * proxy variable, no redirect followed, no global agent, no `fetch`, a byte cap on every answer and nothing sent + * twice. The transport closes a pooled socket after 4 s idle, below Weaviate's 10 s idle close (spec A.7). + * + * What it can send is closed three ways. The table must name exactly the operations of `WEAVIATE_OPS`, so there is + * no operation for a write, a backup or a user route. A request may fill only the parameters its route's template + * declares and carry only the query keys its route declares. And a `GET` takes no body, while a `POST` takes one. + * Each refusal is raised before the wire. + * + * A path parameter is refused when it is empty, `.` or `..`, holds `/` or a NUL, or is longer than 255 characters, + * as written or once percent-decoded, because URL parsing would turn a dot segment into another route; phase 0 has + * already held every name to Weaviate's own rule (spec W1), so this is the last line, not the first. It logs nothing. + */ +import { QueryError } from "@/lib/db/errors"; +import { endpointUrl } from "@/lib/db/http/endpoint"; +import { createNodeTransport, type NodeTransport, type NodeTransportOptions } from "@/lib/db/http/node-transport"; +import type { DatabaseType } from "@/lib/types"; +import { + WEAVIATE_OPS, + type WeaviateAnswer, + type WeaviateClient, + type WeaviateOp, + type WeaviateRequest, + type WeaviateRouteTemplate, + type WeaviateRouteTemplates, +} from "./client"; +import type { WeaviateConnectionOptions } from "./connection-options"; + +/** How the client gets its transport; a test hands in a recording one. */ +export type WeaviateTransportFactory = (options: NodeTransportOptions) => NodeTransport; + +const PROVIDER: DatabaseType = "weaviate"; +const MAX_NAME_LENGTH = 255; +const PARAMETER = /^\{([a-z_]+)\}$/; +/** A literal segment: `v1`, `schema`, `near-vector`, `.well-known`. */ +const LITERAL = /^[a-z0-9.-]+$/; +const QUERY_KEY = /^[a-z_]+$/; + +const INVALID_NAME = + "A name in the request path is empty, `.` or `..`, holds `/` or a NUL character, as written or once percent-decoded, or is longer than 255 characters, so nothing was sent."; + +const MALFORMED_NAME = "A name in the request path is not well-formed Unicode text, so nothing was sent."; + +type Segment = { readonly literal: string } | { readonly parameter: string }; + +interface Route { + readonly method: "GET" | "POST"; + readonly segments: readonly Segment[]; + readonly parameters: ReadonlySet; + readonly query: ReadonlySet; +} + +function compile(op: string, template: WeaviateRouteTemplate): Route { + if (template.method !== "GET" && template.method !== "POST") { + throw new TypeError(`The Weaviate route table gives ${op} a method that is neither GET nor POST`); + } + if (!template.path.startsWith("/")) + throw new TypeError(`The Weaviate route table gives ${op} a path that is not absolute`); + const segments = template.path + .split("/") + .slice(1) + .map((segment): Segment => { + const parameter = PARAMETER.exec(segment)?.[1]; + if (parameter !== undefined) return { parameter }; + if (!LITERAL.test(segment) || segment === "." || segment === "..") { + throw new TypeError(`The Weaviate route table gives ${op} a path segment this client cannot read`); + } + return { literal: segment }; + }); + for (const key of template.query) { + if (!QUERY_KEY.test(key)) + throw new TypeError(`The Weaviate route table gives ${op} a query key this client cannot read`); + } + return { + method: template.method, + segments, + parameters: new Set(segments.flatMap((segment) => ("parameter" in segment ? [segment.parameter] : []))), + query: new Set(template.query), + }; +} + +/** The route table, held to exactly the operations of `WEAVIATE_OPS`: one more or one fewer is a programming error. */ +function compileRoutes(routes: WeaviateRouteTemplates): ReadonlyMap { + const given = new Set(Object.keys(routes)); + if (given.size !== WEAVIATE_OPS.length || WEAVIATE_OPS.some((op) => !given.has(op))) { + throw new TypeError(`The Weaviate route table must name exactly the ${WEAVIATE_OPS.length} operations`); + } + return new Map(WEAVIATE_OPS.map((op) => [op, compile(op, routes[op])])); +} + +function refuse(message: string): never { + throw new QueryError(message, PROVIDER); +} + +function escapesItsSegment(value: string): boolean { + return value === "." || value === ".." || value.includes("/") || value.includes("\0"); +} + +function percentDecoded(value: string): string { + try { + return decodeURIComponent(value); + } catch { + return value; + } +} + +function segmentOf(value: unknown): string { + if ( + typeof value !== "string" || + value === "" || + [...value].length > MAX_NAME_LENGTH || + escapesItsSegment(value) || + escapesItsSegment(percentDecoded(value)) + ) { + refuse(INVALID_NAME); + } + try { + return encodeURIComponent(value); + } catch { + refuse(MALFORMED_NAME); + } +} + +function pathOf(route: Route, request: WeaviateRequest): string { + for (const name of Object.keys(request.params)) { + if (!route.parameters.has(name)) + refuse("The request names a path parameter its route does not declare, so nothing was sent."); + } + const segments = route.segments.map((segment) => + "literal" in segment + ? segment.literal + : segmentOf(Object.hasOwn(request.params, segment.parameter) ? request.params[segment.parameter] : undefined), + ); + return `/${segments.join("/")}`; +} + +function queryOf(route: Route, request: WeaviateRequest): URLSearchParams | undefined { + const entries = Object.entries(request.query); + if (entries.length === 0) return undefined; + const params = new URLSearchParams(); + for (const [key, value] of entries) { + if (!route.query.has(key)) + refuse("The request carries a query key its route does not declare, so nothing was sent."); + if (typeof value !== "string") refuse("The request carries a query value that is not text, so nothing was sent."); + params.set(key, value); + } + return params; +} + +export function createRestWeaviateClient( + options: WeaviateConnectionOptions, + routes: WeaviateRouteTemplates, + createTransport: WeaviateTransportFactory = createNodeTransport, +): WeaviateClient { + const table = compileRoutes(routes); + const transport = createTransport({ + origin: options.origin, + tls: options.tls, + maxSockets: options.maxSockets, + headers: options.headers, + // A connect that never completes names the host, the port and the seconds waited, as a ConnectionError. + reportsUnreachable: true, + }); + return { + async send(request: WeaviateRequest, signal: AbortSignal): Promise { + const route = table.get(request.op as WeaviateOp); + if (route === undefined) refuse("The request names an operation this client does not send, so nothing was sent."); + if (route.method === "GET" && request.body !== undefined) { + refuse("The request gives a body to a route that takes none, so nothing was sent."); + } + if (route.method === "POST" && typeof request.body !== "string") { + refuse("The request gives a POST route no JSON text, so nothing was sent."); + } + const url = endpointUrl(options.origin, pathOf(route, request), queryOf(route, request)); + const answer = await transport.request({ + method: route.method, + url, + ...(request.body === undefined ? {} : { body: request.body }), + signal, + maxResponseBytes: options.responseCapBytes, + }); + return { + status: answer.status, + contentType: answer.contentType, + retryAfter: answer.retryAfter, + text: answer.text, + }; + }, + close(): void { + transport.close(); + }, + }; +} diff --git a/src/lib/db/providers/vector/weaviate/results.ts b/src/lib/db/providers/vector/weaviate/results.ts new file mode 100644 index 0000000000..8b9a277a79 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/results.ts @@ -0,0 +1,466 @@ +/** + * A Weaviate answer to a `QueryResult` (#1566 spec 5.2): one row per object for the object reads and the searches, + * whichever path answered, one row for an aggregate count or one per group, and one row per entry for the metadata + * reads. + * + * A search row has the same columns on both paths: `$id`, the properties asked for (every plain property when none + * is named, which is what REST answers), then `$distance`, `$certainty`, `$score`, `$explainScore`, `$creationTime` + * and `$lastUpdateTime` as asked, the two times as milliseconds since the epoch on both paths (REST answers a number, + * GraphQL a string). Neither search path returns a vector (REST has no metadata for it, spec A.10); an object read + * with `include=vector` does, as `$vector` and `$vector.` columns the grid draws as vectors. + * + * Weaviate stores an `int` property as a float64 (spec A.3), so a plain parse loses nothing the server has. On the + * GraphQL path an int outside int32 answers null, 2^53 - 1 included, so a null in an `int` column there is counted + * and the result says it may be such a value. Rows are built on `Object.create(null)`; the conversion stops at the + * byte budget and drops the rest whole; text cells are cut at their bound with a marker; vector cells never are. + */ +import { utf8ByteLength } from "@/lib/db/console/bounds"; +import { QueryError } from "@/lib/db/errors"; +import { countLabel } from "@/lib/db/vector/count"; +import type { VectorColumn } from "@/lib/db/vector/types"; +import type { DatabaseType, QueryResult, QueryWarning } from "@/lib/types"; +import type { WeaviateConsoleOp } from "./client"; +import { GRAPHQL_METADATA } from "./graphql"; +import type { WeaviateSearchModel } from "./request"; +import { WEAVIATE_BOUNDS } from "./routes"; +import { vectorColumnName, type WeaviateCollectionFacts } from "./schema"; +import type { WeaviatePath } from "./versions"; + +const PROVIDER: DatabaseType = "weaviate"; + +export interface WeaviateResultOptions { + readonly executionTime: number; + /** The byte budget; only a test passes another. */ + readonly budgetBytes?: number; +} + +/** What a result needs to know about the request that asked for it. */ +export interface WeaviateResultShape { + readonly op: WeaviateConsoleOp; + /** The collection the request read, or null where it reads none. */ + readonly facts: WeaviateCollectionFacts | null; + /** The path that answered a search or aggregate; null for every other route. */ + readonly path: WeaviatePath | null; + readonly model: WeaviateSearchModel | null; + /** The object list's limit, for the next-page notice; null where the list names offset or sort. */ + readonly limit: number | null; + /** The object list already names after, so the notice says to replace it rather than add one. */ + readonly afterGiven?: boolean; + readonly warnings: readonly QueryWarning[]; +} + +type Json = null | boolean | number | string | readonly Json[] | { readonly [key: string]: Json }; +type JsonObject = { readonly [key: string]: Json }; + +function isObject(value: Json | undefined): value is JsonObject { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function parsed(text: string): Json { + try { + return JSON.parse(text) as Json; + } catch { + throw new QueryError("Weaviate answered with a body that is not JSON.", PROVIDER); + } +} + +function listOf(value: Json | undefined, what: string): readonly Json[] { + if (value === null || value === undefined) return []; + if (!Array.isArray(value)) throw new QueryError(`Weaviate answered with no list of ${what}.`, PROVIDER); + return value; +} + +/** The notes a conversion gathers, written as warnings once it ends. */ +class Notes { + cutCells = 0; + int32Nulls = new Set(); + + text(value: string): string { + const limit = WEAVIATE_BOUNDS.stringCellUnits; + if (value.length <= limit) return value; + const high = value.charCodeAt(limit - 1); + const end = high >= 0xd800 && high <= 0xdbff ? limit - 1 : limit; + this.cutCells += 1; + return `${value.slice(0, end)}...[cut: ${end} of ${value.length} characters shown]`; + } + + cell(value: Json | undefined): Json { + if (value === undefined) return null; + return typeof value === "string" ? this.text(value) : value; + } + + warnings(): QueryWarning[] { + const warnings: QueryWarning[] = []; + if (this.int32Nulls.size > 0) { + warnings.push({ + message: `GraphQL answers null for an int outside the 32-bit range, so a null in ${[...this.int32Nulls].join(", ")} may be such a value; Weaviate 1.39.7 and later answer it over REST.`, + }); + } + if (this.cutCells > 0) { + warnings.push({ + message: `${this.cutCells} text cells were longer than ${WEAVIATE_BOUNDS.stringCellUnits} characters and are cut, with a marker.`, + }); + } + return warnings; + } +} + +/** The rows within the byte budget, whole; the rest dropped, with a warning naming the bound. */ +function budgeted( + rows: readonly Record[], + options: WeaviateResultOptions, +): { readonly kept: readonly Record[]; readonly warning?: QueryWarning } { + const budget = options.budgetBytes ?? WEAVIATE_BOUNDS.resultBudgetBytes; + let bytes = 0; + for (let index = 0; index < rows.length; index++) { + bytes += utf8ByteLength(JSON.stringify(rows[index])); + if (bytes > budget) { + const bound = budget >= 1_048_576 ? `${budget / 1_048_576} MiB` : `${budget}-byte`; + return { + kept: rows.slice(0, index), + warning: { + message: `The result reached Studio's ${bound} result budget after ${index} rows; the remaining ${rows.length - index} rows are not shown. Lower the limit, or ask for fewer properties.`, + }, + }; + } + } + return { kept: rows }; +} + +interface Built { + readonly fields: readonly string[]; + readonly rows: readonly Record[]; + readonly columnTypes: Readonly>; + readonly warnings: readonly QueryWarning[]; + readonly vectorColumns?: Readonly>; + /** An object list that filled its limit: the next page starts after the last row shown. */ + readonly nextPage?: { readonly limit: number; readonly afterGiven: boolean }; +} + +/** + * The next-page notice, from the rows the budget kept: after the budget drops the tail of a page, the next page has + * to start after the last row shown, or the dropped rows are never read. + */ +function nextPageNotice(built: Built, kept: readonly Record[]): QueryWarning[] { + if (built.nextPage === undefined || kept.length === 0) return []; + const { limit, afterGiven } = built.nextPage; + return [ + { + message: `More objects may follow: ${afterGiven ? "set after" : "add &after"}=${String(kept[kept.length - 1].$id)} to read the next ${limit}.`, + }, + ]; +} + +function result(built: Built, options: WeaviateResultOptions): QueryResult { + const { kept, warning } = budgeted(built.rows, options); + // A result always names a column, so an empty answer still shows what it would have held. + const fields = built.fields.length === 0 ? ["$id"] : [...built.fields]; + const rows = kept.map((row) => { + const ordered: Record = Object.create(null); + for (const field of fields) ordered[field] = Object.hasOwn(row, field) ? row[field] : null; + return ordered; + }); + const notices = [...built.warnings, ...nextPageNotice(built, kept)]; + const warnings = warning === undefined ? notices : [...notices, warning]; + return { + rows, + fields, + rowCount: rows.length, + executionTime: options.executionTime, + columnTypes: { ...built.columnTypes }, + ...(warnings.length === 0 ? {} : { warnings }), + ...(built.vectorColumns === undefined || Object.keys(built.vectorColumns).length === 0 + ? {} + : { vectorColumns: built.vectorColumns }), + ...(warning === undefined + ? {} + : { + pagination: { limit: rows.length, offset: 0, hasMore: false, totalReturned: rows.length, wasLimited: true }, + }), + }; +} + +/** Rows of a list of objects, one column per top-level key, in first-seen order: the metadata reads. */ +function listRows( + items: readonly Json[], + options: WeaviateResultOptions, + warnings: readonly QueryWarning[], +): QueryResult { + const notes = new Notes(); + const fields = new Set(); + const rows = items.map((item) => { + if (!isObject(item)) throw new QueryError("Weaviate answered with no object where one was expected.", PROVIDER); + const row: Record = Object.create(null); + for (const key of Object.keys(item)) { + fields.add(key); + row[key] = notes.cell(item[key]); + } + return row; + }); + return result({ fields: [...fields], rows, columnTypes: {}, warnings: [...warnings, ...notes.warnings()] }, options); +} + +const OBJECT_TIMES: readonly (readonly [string, string])[] = [ + ["creationTimeUnix", "$creationTime"], + ["lastUpdateTimeUnix", "$lastUpdateTime"], +]; + +/** One object of `GET /v1/objects` or `GET /v1/objects/{c}/{id}` as a row: id, properties, vectors, times. */ +function objectRow( + object: Json, + notes: Notes, + columns: { readonly properties: Set; readonly vectors: Map }, +): Record { + if (!isObject(object) || typeof object.id !== "string") { + throw new QueryError("Weaviate answered an object with no id.", PROVIDER); + } + const row: Record = Object.create(null); + row.$id = object.id; + if (isObject(object.properties)) { + for (const key of Object.keys(object.properties)) { + columns.properties.add(key); + row[key] = notes.cell(object.properties[key]); + } + } + const vector = (name: string, value: Json | undefined) => { + if (!Array.isArray(value)) return; + const column = vectorColumnName(name); + columns.vectors.set(column, value.length); + row[column] = value; + }; + if (Array.isArray(object.vector) && object.vector.length > 0) vector("", object.vector); + if (isObject(object.vectors)) for (const name of Object.keys(object.vectors)) vector(name, object.vectors[name]); + for (const [key, column] of OBJECT_TIMES) { + if (typeof object[key] === "number") row[column] = object[key]; + } + return row; +} + +function objectRows(objects: readonly Json[], shape: WeaviateResultShape, options: WeaviateResultOptions): QueryResult { + const notes = new Notes(); + const columns = { properties: new Set(), vectors: new Map() }; + const rows = objects.map((object) => objectRow(object, notes, columns)); + const declared = shape.facts?.plainProperties ?? []; + const properties = [...declared.filter((name) => columns.properties.has(name))]; + for (const name of columns.properties) if (!properties.includes(name)) properties.push(name); + const times = OBJECT_TIMES.map(([, column]) => column).filter((column) => + rows.some((row) => Object.hasOwn(row, column)), + ); + const vectorColumns: Record = {}; + for (const [column, dimension] of columns.vectors) + vectorColumns[column] = { kind: "dense", dtype: "float32", dimension }; + const warnings = [...shape.warnings, ...notes.warnings()]; + return result( + { + fields: ["$id", ...properties, ...columns.vectors.keys(), ...times], + rows, + columnTypes: { + $id: "uuid", + ...(times.length === 0 ? {} : Object.fromEntries(times.map((t) => [t, "epoch ms"]))), + }, + warnings, + vectorColumns, + // A full page says more may follow; result() writes the notice from the rows it keeps (see nextPageNotice). + ...(shape.op === "objects" && shape.limit !== null && rows.length === shape.limit && rows.length > 0 + ? { nextPage: { limit: shape.limit, afterGiven: shape.afterGiven === true } } + : {}), + }, + options, + ); +} + +/** A search hit as its id, its properties and its metadata, read from either path's answer. */ +interface Hit { + readonly id: string; + readonly properties: JsonObject; + readonly metadata: JsonObject; +} + +function restHits(answer: Json): readonly Hit[] { + const results = isObject(answer) ? answer.results : undefined; + return listOf(results, "results").map((entry) => { + if (!isObject(entry) || typeof entry.id !== "string") + throw new QueryError("Weaviate answered a result with no id.", PROVIDER); + return { + id: entry.id, + properties: isObject(entry.properties) ? entry.properties : {}, + metadata: isObject(entry.metadata) ? entry.metadata : {}, + }; + }); +} + +/** GraphQL's `data.Get.` as hits: `_additional` is the metadata, the rest the properties. */ +/** + * GraphQL answers the two times as integer strings and the BM25 and hybrid score as a decimal string, where REST + * answers numbers, so the same search shows the same cell types on both paths (spec 5.6). + */ +function graphqlMetadataValue(rest: string, value: Json): Json { + if (typeof value !== "string") return value; + if (rest.endsWith("Time") && /^[0-9]+$/.test(value)) return Number(value); + if (rest === "score" && /^-?[0-9]+(?:\.[0-9]+)?(?:[eE][-+]?[0-9]+)?$/.test(value)) return Number(value); + return value; +} + +function graphqlHits(answer: Json, collection: string): readonly Hit[] { + const data = isObject(answer) && isObject(answer.data) ? answer.data : undefined; + const get = data !== undefined && isObject(data.Get) ? data.Get : undefined; + return listOf(get?.[collection], "results").map((entry) => { + if (!isObject(entry) || !isObject(entry._additional) || typeof entry._additional.id !== "string") { + throw new QueryError("Weaviate answered a result with no id.", PROVIDER); + } + const { _additional: additional, ...properties } = entry; + const metadata: Record = {}; + for (const [rest, graphql] of Object.entries(GRAPHQL_METADATA)) { + const value = (additional as JsonObject)[graphql]; + if (value === undefined) continue; + metadata[rest] = graphqlMetadataValue(rest, value); + } + return { id: additional.id as string, properties, metadata }; + }); +} + +const METADATA_TYPES: Readonly> = { + distance: "distance, lower is closer", + certainty: "certainty, higher is closer", + score: "score, higher is better", + explainScore: "text", + creationTime: "epoch ms", + lastUpdateTime: "epoch ms", +}; + +function searchRows(answer: Json, shape: WeaviateResultShape, options: WeaviateResultOptions): QueryResult { + const model = shape.model as WeaviateSearchModel; + const facts = shape.facts as WeaviateCollectionFacts; + const hits = shape.path === "graphql" ? graphqlHits(answer, model.collection) : restHits(answer); + const notes = new Notes(); + const properties = [...(model.returnProperties ?? facts.plainProperties)]; + for (const hit of hits) + for (const key of Object.keys(hit.properties)) if (!properties.includes(key)) properties.push(key); + const metadata = model.returnMetadata.map((word) => `$${word}`); + const rows = hits.map((hit) => { + const row: Record = Object.create(null); + row.$id = hit.id; + for (const name of properties) { + const value = hit.properties[name]; + if (shape.path === "graphql" && value === null && facts.intProperties.has(name)) notes.int32Nulls.add(name); + row[name] = notes.cell(value); + } + for (const word of model.returnMetadata) row[`$${word}`] = notes.cell(hit.metadata[word]); + return row; + }); + const warnings = [...shape.warnings, ...notes.warnings()]; + const vector = facts.vectors.find((entry) => entry.name === (model.targetVector ?? "")); + if (rows.length === 0 && model.op === "search_near_vector" && vector !== undefined && vector.quantization !== null) { + warnings.push({ + message: `No results. The vector index is ${vector.quantization}-compressed, and Weaviate answers an empty result rather than an error when a query vector's length differs from the stored vectors', so check the vector's length.`, + }); + } + return result( + { + fields: ["$id", ...properties, ...metadata], + rows, + columnTypes: { + $id: "uuid", + ...Object.fromEntries(model.returnMetadata.map((word) => [`$${word}`, METADATA_TYPES[word]])), + }, + warnings, + }, + options, + ); +} + +/** An aggregate's group limit as a number: written by phase 0 for every groupBy, an integer phase 0 has checked. */ +function groupBound(model: WeaviateSearchModel): number | null { + const limit = model.limit as { readonly digits?: string } | null; + return limit === null || typeof limit.digits !== "string" ? null : Number(limit.digits); +} + +function aggregateRows(answer: Json, shape: WeaviateResultShape, options: WeaviateResultOptions): QueryResult { + const model = shape.model as WeaviateSearchModel; + const groups: { readonly value: Json; readonly count: Json }[] = []; + let total: Json | undefined; + if (shape.path === "graphql") { + const data = isObject(answer) && isObject(answer.data) ? answer.data : undefined; + const aggregate = data !== undefined && isObject(data.Aggregate) ? data.Aggregate : undefined; + for (const entry of listOf(aggregate?.[model.collection], "aggregates")) { + if (!isObject(entry)) continue; + const count = isObject(entry.meta) ? entry.meta.count : null; + if (model.groupBy === null) total = count; + else groups.push({ value: isObject(entry.groupedBy) ? entry.groupedBy.value : null, count }); + } + } else if (isObject(answer)) { + if (model.groupBy === null) total = answer.count; + else { + for (const entry of listOf(answer.groups, "groups")) { + if (!isObject(entry)) continue; + groups.push({ value: isObject(entry.groupedBy) ? entry.groupedBy.value : null, count: entry.count }); + } + } + } + const countType = countLabel("exact"); + if (model.groupBy === null) { + if (typeof total !== "number") throw new QueryError("Weaviate answered an aggregate with no count.", PROVIDER); + return result( + { + fields: ["count"], + rows: [Object.assign(Object.create(null), { count: total })], + columnTypes: { count: countType }, + warnings: shape.warnings, + }, + options, + ); + } + const column = model.groupBy; + const bound = groupBound(model); + const reached = + bound !== null && groups.length >= bound + ? [ + { + message: `Weaviate answered the ${bound} groups the limit allows; more may exist: raise limit (at most ${WEAVIATE_BOUNDS.maxRows}).`, + }, + ] + : []; + return result( + { + fields: [column, "count"], + rows: groups.map((group) => Object.assign(Object.create(null), { [column]: group.value, count: group.count })), + columnTypes: { count: countType }, + warnings: [...shape.warnings, ...reached], + }, + options, + ); +} + +/** The answer of a request phase 1 accepted, as the result the grid shows. */ +export function weaviateResult(text: string, shape: WeaviateResultShape, options: WeaviateResultOptions): QueryResult { + const answer = parsed(text); + const field = (key: string): Json | undefined => (isObject(answer) ? answer[key] : undefined); + switch (shape.op) { + case "meta": + case "collection": + case "tenant": + case "alias": + return listRows([answer], options, shape.warnings); + case "schema": + return listRows(listOf(field("classes"), "classes"), options, shape.warnings); + case "shards": + case "tenants": + return listRows(listOf(answer, "entries"), options, shape.warnings); + case "aliases": + return listRows(listOf(field("aliases"), "aliases"), options, shape.warnings); + case "nodes": + case "collection_nodes": + return listRows(listOf(field("nodes"), "nodes"), options, shape.warnings); + case "objects": + return objectRows(listOf(field("objects"), "objects"), shape, options); + case "object": + return objectRows([answer], shape, options); + case "search_bm25": + case "search_hybrid": + case "search_near_vector": + case "search_near_object": + return searchRows(answer, shape, options); + case "aggregate": + return aggregateRows(answer, shape, options); + } +} diff --git a/src/lib/db/providers/vector/weaviate/routes.ts b/src/lib/db/providers/vector/weaviate/routes.ts new file mode 100644 index 0000000000..7f4e86deba --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/routes.ts @@ -0,0 +1,362 @@ +import type { ConsoleDialectSpec, QueryKeySpec, RouteSpec } from "@/lib/db/console/dialect"; +import type { WeaviateConsoleOp, WeaviateOp } from "./client"; + +/** + * The Weaviate console as data (#1566 spec 5.1): its dialect, its route table, the closed key sets of every request + * body, its bounds and the sentences it refuses a route with. + * + * The console text is a Weaviate REST request line and one JSON body, the form Weaviate's own REST reference prints. + * Every search is written in the REST search shape on every server, and `execute.ts` runs it over REST or GraphQL as + * the server's version decides (spec 3.3). Every body key is closed: a key the OpenAPI document (v1.40.2; the top + * level is the same on 1.38.22 and 1.39.8) does not declare at its level is refused by name, because the server + * reads past an unknown key without a word, so a misspelled `where` returns unfiltered results (measured, spec A.6). + * + * Nothing here is derived at run time. Browser-safe: it imports types only. + */ + +export const WEAVIATE_CONSOLE: ConsoleDialectSpec = Object.freeze({ + id: "weaviate", + methods: Object.freeze(["GET", "POST"]), + pathPrefix: "/v1/", + shortForm: true, + commentMarkers: Object.freeze(["//", "#"]), + bodyComments: true, + maxTextBytes: 1_048_576, + maxDepth: 32, + maxNodes: 4_096, + maxNumericLeaves: 262_144, + maxScalarLeaves: 32_768, +}); + +/** The request bodies a route takes, by their name in the OpenAPI document. */ +export type WeaviateBodySchema = + | "SearchBm25Request" + | "SearchHybridRequest" + | "SearchNearVectorRequest" + | "SearchNearObjectRequest" + | "AggregateRequest"; + +/** One route of the table: the shared route facts, and the schema its body is read by. */ +export interface WeaviateRoute extends RouteSpec { + /** The body's schema, or null where the route takes no body. */ + readonly schema: WeaviateBodySchema | null; +} + +const COLLECTION = Object.freeze({ collection: "name" } as const); +const TENANT = Object.freeze({ collection: "name", tenant: "name" } as const); +const ALIAS = Object.freeze({ alias: "name" } as const); +const OBJECT = Object.freeze({ collection: "name", id: "name" } as const); +const NONE = Object.freeze({}); + +const TEXT: QueryKeySpec = Object.freeze({ kind: "text" }); +const POSITIVE: QueryKeySpec = Object.freeze({ kind: "positive-int" }); + +/** The query keys a route may declare, and the values each takes. */ +export const WEAVIATE_QUERY_KEYS = Object.freeze({ + class: TEXT, + limit: POSITIVE, + after: TEXT, + // Text here and read in phase 0 (request.ts): Weaviate takes an offset of 0, which the shared positive-int kind refuses. + offset: TEXT, + include: Object.freeze({ kind: "word-list", words: Object.freeze(["vector", "classification", "interpretation"]) }), + sort: TEXT, + order: Object.freeze({ kind: "word-list", words: Object.freeze(["asc", "desc"]) }), + tenant: TEXT, + output: Object.freeze({ kind: "word-list", words: Object.freeze(["minimal", "verbose"]) }), +} as const satisfies Readonly>); + +const K = WEAVIATE_QUERY_KEYS; +const OBJECTS_QUERY = Object.freeze({ + class: K.class, + limit: K.limit, + after: K.after, + offset: K.offset, + include: K.include, + sort: K.sort, + order: K.order, + tenant: K.tenant, +}); +const OBJECT_QUERY = Object.freeze({ include: K.include, tenant: K.tenant }); +const SHARDS_QUERY = Object.freeze({ tenant: K.tenant }); +const NODES_QUERY = Object.freeze({ output: K.output }); + +function route( + method: "GET" | "POST", + template: string, + op: WeaviateConsoleOp, + params: WeaviateRoute["params"], + query: WeaviateRoute["query"], + body: WeaviateRoute["body"], + schema: WeaviateBodySchema | null, +): WeaviateRoute { + return Object.freeze({ method, template, op, class: "read", params, query, body, schema }); +} + +/** + * The 17 routes version 1 runs, every one a read, in the order the REST reference lists them. A template is the path + * after the dialect's prefix `/v1/`. The aggregate body is optional and an absent one is sent as `{}`. + */ +export const WEAVIATE_ROUTES: readonly WeaviateRoute[] = Object.freeze([ + route("GET", "meta", "meta", NONE, NONE, "none", null), + route("GET", "schema", "schema", NONE, NONE, "none", null), + route("GET", "schema/{collection}", "collection", COLLECTION, NONE, "none", null), + route("GET", "schema/{collection}/shards", "shards", COLLECTION, SHARDS_QUERY, "none", null), + route("GET", "schema/{collection}/tenants", "tenants", COLLECTION, NONE, "none", null), + route("GET", "schema/{collection}/tenants/{tenant}", "tenant", TENANT, NONE, "none", null), + route("GET", "aliases", "aliases", NONE, NONE, "none", null), + route("GET", "aliases/{alias}", "alias", ALIAS, NONE, "none", null), + route("GET", "nodes", "nodes", NONE, NODES_QUERY, "none", null), + route("GET", "nodes/{collection}", "collection_nodes", COLLECTION, NODES_QUERY, "none", null), + route("GET", "objects", "objects", NONE, OBJECTS_QUERY, "none", null), + route("GET", "objects/{collection}/{id}", "object", OBJECT, OBJECT_QUERY, "none", null), + route("POST", "search/{collection}/bm25", "search_bm25", COLLECTION, NONE, "required", "SearchBm25Request"), + route("POST", "search/{collection}/hybrid", "search_hybrid", COLLECTION, NONE, "required", "SearchHybridRequest"), + route( + "POST", + "search/{collection}/near-vector", + "search_near_vector", + COLLECTION, + NONE, + "required", + "SearchNearVectorRequest", + ), + route( + "POST", + "search/{collection}/near-object", + "search_near_object", + COLLECTION, + NONE, + "required", + "SearchNearObjectRequest", + ), + route("POST", "aggregate/{collection}", "aggregate", COLLECTION, NONE, "optional", "AggregateRequest"), +]); + +/** + * Every operation's method, path and query keys, as the client is built with them: the console's routes, then the + * two the provider writes itself and no console text can name. + */ +export const WEAVIATE_CLIENT_ROUTES: Readonly< + Record +> = Object.freeze({ + ...(Object.fromEntries( + WEAVIATE_ROUTES.map((entry) => [ + entry.op, + Object.freeze({ + method: entry.method as "GET" | "POST", + path: `${WEAVIATE_CONSOLE.pathPrefix}${entry.template}`, + query: Object.freeze(Object.keys(entry.query)), + }), + ]), + ) as Record), + ready: Object.freeze({ method: "GET", path: "/v1/.well-known/ready", query: Object.freeze([]) }), + graphql: Object.freeze({ method: "POST", path: "/v1/graphql", query: Object.freeze([]) }), +}); + +/** One closed object level: the keys it takes, and the keys it cannot go without. */ +export interface KeySet { + readonly keys: readonly string[]; + readonly required: readonly string[]; +} + +const COMMON = [ + "where", + "limit", + "offset", + "autoLimit", + "returnProperties", + "returnMetadata", + "tenant", + "consistencyLevel", +] as const; + +/** Every object a version 1 body can hold, with the keys the document declares for it and version 1 takes. */ +export const WEAVIATE_KEYS = { + SearchBm25Request: { keys: [...COMMON, "query", "queryProperties"], required: ["query"] }, + SearchHybridRequest: { + keys: [...COMMON, "query", "queryProperties", "alpha", "fusionType", "maxVectorDistance", "targetVector"], + required: ["query", "alpha"], + }, + SearchNearVectorRequest: { + keys: [...COMMON, "vector", "targetVector", "distance", "certainty"], + required: ["vector"], + }, + SearchNearObjectRequest: { + keys: [...COMMON, "id", "targetVector", "distance", "certainty"], + required: ["id"], + }, + AggregateRequest: { keys: ["where", "tenant", "groupBy", "limit", "returnMetrics"], required: [] }, + WhereFilter: { + keys: [ + "operator", + "operands", + "path", + "valueInt", + "valueNumber", + "valueBoolean", + "valueString", + "valueText", + "valueDate", + "valueIntArray", + "valueNumberArray", + "valueBooleanArray", + "valueStringArray", + "valueTextArray", + "valueDateArray", + "valueGeoRange", + ], + required: ["operator"], + }, + WhereFilterGeoRange: { keys: ["geoCoordinates", "distance"], required: ["geoCoordinates", "distance"] }, + GeoCoordinates: { keys: ["latitude", "longitude"], required: ["latitude", "longitude"] }, + GeoDistance: { keys: ["max"], required: ["max"] }, +} as const satisfies Readonly>; + +export type WeaviateObjectName = keyof typeof WEAVIATE_KEYS; + +/** + * The body keys the document declares that version 1 refuses by name, with the reason each is refused. The first + * three make the server call a model provider (spec W3); the others are reserved (the 1.40.2 OpenAPI text answers + * them "Returns 422, not yet supported") or not yet measured on the GraphQL path (spec WM7). + */ +export const WEAVIATE_REFUSED_KEYS: Readonly> = Object.freeze({ + singlePrompt: "generative search sends the results to a model provider", + groupedTask: "generative search sends the results to a model provider", + rerank: "reranking sends the results to a model provider", + groupBy: "grouped search is reserved in Weaviate's REST search", + numberOfGroups: "grouped search is reserved in Weaviate's REST search", + objectsPerGroup: "grouped search is reserved in Weaviate's REST search", + returnReferences: "returning cross-references is outside this version of the console", + over: "aggregate over a search is reserved in Weaviate's REST aggregate", + objectLimit: "aggregate over a search is reserved in Weaviate's REST aggregate", +}); + +/** The enumerations a request names, with the words each takes. */ +export const WEAVIATE_ENUMS = Object.freeze({ + operator: Object.freeze([ + "And", + "Or", + "Not", + "Equal", + "NotEqual", + "Like", + "GreaterThan", + "GreaterThanEqual", + "LessThan", + "LessThanEqual", + "WithinGeoRange", + "IsNull", + "ContainsAny", + "ContainsAll", + "ContainsNone", + ]), + returnMetadata: Object.freeze(["distance", "certainty", "score", "explainScore", "creationTime", "lastUpdateTime"]), + consistencyLevel: Object.freeze(["ONE", "QUORUM", "ALL"]), + fusionType: Object.freeze(["ranked", "relativeScore"]), + returnMetrics: Object.freeze(["count"]), +} as const); + +/** Every bound of the console, the results and the calls, as one table. */ +export const WEAVIATE_BOUNDS = Object.freeze({ + /** Sent explicitly where an object list names no limit: Weaviate's own default for `GET /v1/objects`. */ + defaultObjectsLimit: 25, + /** Sent explicitly where a search names no limit, so REST and GraphQL answer the same rows: QUERY_DEFAULTS_LIMIT. */ + defaultSearchLimit: 10, + /** Groups an aggregate with groupBy answers when it names no limit, written out: the server's own default on both paths. */ + defaultGroupsLimit: 100, + /** Rows one request may ask for: a limit, an offset plus a limit. Below Weaviate's QUERY_MAXIMUM_RESULTS (10,000). */ + maxRows: 1_000, + maxDenseSize: 65_536, + maxFilterBytes: 65_536, + maxFilterConditions: 256, + maxFilterDepth: 8, + maxFilterListEntries: 10_000, + maxNameLength: 255, + maxPropertyList: 256, + /** Past this the transport drops the answer and keeps no row. */ + transportCapBytes: 16_777_216, + /** Counted in the bytes the conversion produces; rows past it are dropped whole. */ + resultBudgetBytes: 8_388_608, + /** UTF-16 code units a text cell keeps; a vector cell is never cut. */ + stringCellUnits: 65_536, + /** A metadata route's deadline and a search's, each at most the query timeout and below the 60 s write timeout. */ + metadataDeadlineMs: 10_000, + searchDeadlineMs: 30_000, + perProvider: 4, + perEngine: 16, + queueDepth: 64, + describeConcurrency: 4, + tablesPanelCollections: 200, + /** The tenants a Source lists by name, as Milvus lists partitions (spec 4.4). */ + sourceTenants: 1_024, +}); + +/** What version 1 runs, said after every refusal of a route it does not run. */ +export const WEAVIATE_RUNS = + "This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node " + + "reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts."; + +/** + * The routes version 1 does not run, by what they are. A pattern is the path after the prefix, `*` standing for one + * segment and a trailing `**` for the rest; the first row that matches names the route, so narrower rows come first. + */ +interface RefusedRouteClass { + readonly what: string; + readonly patterns: readonly string[]; + readonly methods?: readonly string[]; +} + +const WEAVIATE_REFUSED_ROUTES: readonly RefusedRouteClass[] = Object.freeze([ + { + what: "a search that sends its text or media to a model provider", + patterns: ["search/*/near-text", "search/*/near-image", "search/*/near-media"], + }, + { + what: "a GraphQL request, which this console writes for you from a REST search", + patterns: ["graphql", "graphql/**"], + }, + { what: "a batch write", patterns: ["batch", "batch/**"] }, + { what: "a backup route", patterns: ["backups", "backups/**"] }, + { what: "a user, role or permission route", patterns: ["authz", "authz/**", "users", "users/**"] }, + { what: "a replication route", patterns: ["replication", "replication/**"] }, + { what: "a namespace route", patterns: ["namespaces", "namespaces/**"] }, + { what: "the server's MCP endpoint", patterns: ["mcp", "mcp/**"] }, + { what: "a classification route", patterns: ["classifications", "classifications/**"] }, + { what: "a tokenize route", patterns: ["tokenize", "schema/*/properties/*/tokenize"] }, + { what: "an export or import route", patterns: ["export", "export/**", "experimental/**"] }, + { what: "a health or readiness route", patterns: [".well-known/**"] }, + { what: "an object write", patterns: ["objects", "objects/**"], methods: ["POST", "PUT", "PATCH", "DELETE", "HEAD"] }, + { what: "a schema, tenant, index or alias change", patterns: ["schema", "schema/**", "aliases", "aliases/**"] }, +]); + +function matches(pattern: string, segments: readonly string[]): boolean { + const parts = pattern.split("/"); + const open = parts[parts.length - 1] === "**"; + const fixed = open ? parts.slice(0, -1) : parts; + if (open ? segments.length <= fixed.length : segments.length !== fixed.length) return false; + return fixed.every((part, index) => part === "*" || part === segments[index]); +} + +/** + * The sentence for a request line version 1 does not run: what the route is, where a row names it, and what the + * console runs. `path` is the request's path as written, with or without the prefix and any query string. + */ +export function refusedRouteSentence(method: string, path: string): string { + const cut = path.search(/[?#]/); + const bare = cut === -1 ? path : path.slice(0, cut); + const relative = bare.startsWith(WEAVIATE_CONSOLE.pathPrefix) + ? bare.slice(WEAVIATE_CONSOLE.pathPrefix.length) + : bare.replace(/^\/+/, ""); + const segments = relative.split("/"); + const found = WEAVIATE_REFUSED_ROUTES.find( + (row) => + (row.methods === undefined || row.methods.includes(method)) && + row.patterns.some((pattern) => matches(pattern, segments)), + ); + const line = `${method} ${WEAVIATE_CONSOLE.pathPrefix}${relative}`; + if (found !== undefined) return `${line} is ${found.what}, which this console does not run. ${WEAVIATE_RUNS}`; + if (!WEAVIATE_CONSOLE.methods.includes(method)) { + return `${line} is not a request this console runs: it sends ${WEAVIATE_CONSOLE.methods.join(" and ")} only. ${WEAVIATE_RUNS}`; + } + return `${line} is not a route this console runs. ${WEAVIATE_RUNS}`; +} diff --git a/src/lib/db/providers/vector/weaviate/schema.ts b/src/lib/db/providers/vector/weaviate/schema.ts new file mode 100644 index 0000000000..cb39957a91 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/schema.ts @@ -0,0 +1,326 @@ +/** + * A Weaviate class definition read into what the tree, the Source, the console and the monitoring panels need + * (#1566 spec 4.2). Pure: it receives the parsed answer of `GET /v1/schema` or `GET /v1/schema/{collection}` and + * never a client. + * + * A collection has either one unnamed vector (`vectorizer`, `vectorIndexType` and `vectorIndexConfig` at its top + * level) or named vectors (`vectorConfig`, each with its own vectorizer, index type and distance), measured on 1.37.4 + * and 1.40.2. The schema declares no dimension, so a vector's dimension is unknown until an object is read + * (`describeObject` reads one, spec 4.2). A property's type is Weaviate's own `dataType` word; a cross-reference's + * `dataType` names its target classes. + * + * Weaviate stores an `int` property as a float64 (spec A.3), so a column typed `int` is a number and the grid shows + * it as one; on the GraphQL path a value outside int32 answers null, which `results.ts` marks. + */ +import { QueryError } from "@/lib/db/errors"; +import type { VectorFieldInfo, VectorIndexKind, VectorMetric } from "@/lib/db/vector/types"; +import type { ColumnSchema, DatabaseType, IndexSchema } from "@/lib/types"; + +const PROVIDER: DatabaseType = "weaviate"; + +/** The data types Weaviate declares for a primitive property; any other `dataType` names a cross-reference target. */ +export const WEAVIATE_PRIMITIVE_TYPES: ReadonlySet = new Set([ + "text", + "text[]", + "string", + "string[]", + "int", + "int[]", + "number", + "number[]", + "boolean", + "boolean[]", + "date", + "date[]", + "uuid", + "uuid[]", + "geoCoordinates", + "phoneNumber", + "blob", + "object", + "object[]", +]); + +export interface WeaviateProperty { + readonly name: string; + /** Weaviate's `dataType` list as declared: one primitive word, or the target classes of a cross-reference. */ + readonly dataType: readonly string[]; + /** Whether the property is a cross-reference. */ + readonly reference: boolean; + /** An `object` or `object[]` property's own properties, as declared; empty for every other type. */ + readonly nested: readonly WeaviateProperty[]; +} + +/** + * One field of a GraphQL selection: a name, and the fields it needs selected under it. GraphQL refuses an object, + * a geo coordinate or a phone number with no sub-selection (measured on 1.37.4), so the selection is built from + * the schema and the two paths answer the same properties. + */ +export interface SelectionField { + readonly name: string; + readonly fields?: readonly SelectionField[]; +} + +const GEO_FIELDS: readonly SelectionField[] = Object.freeze([{ name: "latitude" }, { name: "longitude" }]); +const PHONE_FIELDS: readonly SelectionField[] = Object.freeze( + ["input", "internationalFormatted", "countryCode", "national", "nationalFormatted", "valid", "defaultCountry"].map( + (name) => ({ name }), + ), +); + +/** A property's GraphQL selection; undefined for a cross-reference, which this version never selects. */ +export function selectionOf(property: WeaviateProperty): SelectionField | undefined { + if (property.reference) return undefined; + const type = property.dataType[0]; + if (type === "geoCoordinates") return { name: property.name, fields: GEO_FIELDS }; + if (type === "phoneNumber") return { name: property.name, fields: PHONE_FIELDS }; + if (type === "object" || type === "object[]") { + const fields = property.nested.flatMap((child) => { + const field = selectionOf(child); + return field === undefined ? [] : [field]; + }); + return fields.length === 0 ? undefined : { name: property.name, fields }; + } + return { name: property.name }; +} + +export interface WeaviateVector { + /** "" for the unnamed vector. */ + readonly name: string; + /** The vectorizer module's name, `none` where vectors are supplied by the writer. */ + readonly vectorizer: string; + /** `hnsw`, `flat`, `dynamic`, `hfresh`, or what the server declares. */ + readonly indexType: string; + /** `cosine`, `dot`, `l2-squared`, `hamming`, `manhattan`; null where the server declares none. */ + readonly distance: string | null; + /** The compression the index declares enabled, or null. */ + readonly quantization: string | null; +} + +export interface WeaviateClass { + readonly name: string; + readonly properties: readonly WeaviateProperty[]; + readonly vectors: readonly WeaviateVector[]; + readonly multiTenant: boolean; + readonly autoTenantActivation: boolean; + /** The definition as the server sent it, for the Source. */ + readonly definition: Readonly>; +} + +type JsonObject = Readonly>; + +function isObject(value: unknown): value is JsonObject { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function text(value: unknown): string | null { + return typeof value === "string" ? value : null; +} + +/** The compression an index config declares enabled: `pq`, `bq`, `sq` or `rq`, the first one found. */ +function quantizationOf(config: unknown): string | null { + if (!isObject(config)) return null; + for (const kind of ["pq", "bq", "sq", "rq"]) { + const entry = config[kind]; + if (isObject(entry) && entry.enabled === true) return kind; + } + return null; +} + +/** A named vector's vectorizer is `{ "": {...} }`; the unnamed vector's is the module name itself. */ +function vectorizerName(value: unknown): string { + if (typeof value === "string" && value !== "") return value; + if (isObject(value)) { + const names = Object.keys(value); + if (names.length > 0) return names[0]; + } + return "none"; +} + +function vectorsOf(definition: JsonObject): readonly WeaviateVector[] { + const vectors: WeaviateVector[] = []; + const unnamedIndex = text(definition.vectorIndexType); + if (unnamedIndex !== null) { + const config = definition.vectorIndexConfig; + vectors.push({ + name: "", + vectorizer: vectorizerName(definition.vectorizer), + indexType: unnamedIndex, + distance: isObject(config) ? text(config.distance) : null, + quantization: quantizationOf(config), + }); + } + if (isObject(definition.vectorConfig)) { + for (const [name, entry] of Object.entries(definition.vectorConfig)) { + if (!isObject(entry)) continue; + const config = entry.vectorIndexConfig; + vectors.push({ + name, + vectorizer: vectorizerName(entry.vectorizer), + indexType: text(entry.vectorIndexType) ?? "hnsw", + distance: isObject(config) ? text(config.distance) : null, + quantization: quantizationOf(config), + }); + } + } + return vectors; +} + +function propertiesOf(list: unknown): readonly WeaviateProperty[] { + if (!Array.isArray(list)) return []; + return list.flatMap((entry: unknown): WeaviateProperty[] => { + if (!isObject(entry) || typeof entry.name !== "string") return []; + const dataType = Array.isArray(entry.dataType) + ? entry.dataType.filter((word): word is string => typeof word === "string") + : []; + const reference = dataType.length > 0 && dataType.every((word) => !WEAVIATE_PRIMITIVE_TYPES.has(word)); + return [{ name: entry.name, dataType, reference, nested: propertiesOf(entry.nestedProperties) }]; + }); +} + +/** One class definition, or a refusal naming what is missing. `fallbackName` names it in that refusal. */ +export function readWeaviateClass(definition: unknown, fallbackName: string): WeaviateClass { + if (!isObject(definition) || typeof definition.class !== "string") { + throw new QueryError(`Weaviate's definition of ${JSON.stringify(fallbackName)} holds no class name.`, PROVIDER); + } + const tenancy = isObject(definition.multiTenancyConfig) ? definition.multiTenancyConfig : {}; + return { + name: definition.class, + properties: propertiesOf(definition.properties), + vectors: vectorsOf(definition), + multiTenant: tenancy.enabled === true, + autoTenantActivation: tenancy.autoTenantActivation === true, + definition, + }; +} + +/** The classes of a `GET /v1/schema` answer, in the order the server lists them. */ +export function readWeaviateSchema(answer: unknown): readonly WeaviateClass[] { + const classes = isObject(answer) ? answer.classes : undefined; + if (classes === null || classes === undefined) return []; + if (!Array.isArray(classes)) throw new QueryError("Weaviate's schema holds no classes list.", PROVIDER); + return classes.map((entry, index) => readWeaviateClass(entry, `class ${index}`)); +} + +const METRICS: Readonly> = { + cosine: "cosine", + dot: "dot", + "l2-squared": "euclidean_squared", + manhattan: "manhattan", + hamming: "hamming", +}; + +const INDEX_KINDS: Readonly> = { hnsw: "hnsw", flat: "flat" }; + +/** A vector's column: `$vector` for the unnamed one, `$vector.` and its name for a named one. */ +export function vectorColumnName(name: string): string { + return name === "" ? "$vector" : `$vector.${name}`; +} + +/** The vector's type text, `Vector(16, cosine, hnsw)`, with `?` for a dimension no object has shown. */ +export function vectorTypeText(vector: WeaviateVector, dimension: number | null): string { + const parts = [ + dimension === null ? "?" : String(dimension), + vector.distance ?? "distance not declared", + vector.indexType, + ]; + if (vector.quantization !== null) parts.push(vector.quantization); + return `Vector(${parts.join(", ")})`; +} + +/** A vector as the vector family's shared field, for the dense checks and the grid. */ +export function vectorField(vector: WeaviateVector, dimension: number | null): VectorFieldInfo { + return { + name: vector.name, + kind: "dense", + dtype: "float32", + dimension, + metric: vector.distance === null ? null : (METRICS[vector.distance] ?? "other"), + nativeMetric: vector.distance, + indexKind: INDEX_KINDS[vector.indexType] ?? "opaque", + nativeType: vectorTypeText(vector, dimension), + }; +} + +/** A property's column type: the primitive word, or `ref → Target` for a cross-reference. */ +export function propertyTypeText(property: WeaviateProperty): string { + if (property.reference) return `ref → ${property.dataType.join(" | ")}`; + return property.dataType.join(", ") || "unknown"; +} + +const ID_COLUMN: ColumnSchema = { name: "$id", type: "uuid", nullable: false, isPrimary: true }; + +/** The columns: `$id`, every property in schema order, then every vector, its dimension where an object showed it. */ +export function weaviateColumns( + definition: WeaviateClass, + dimensions: ReadonlyMap = new Map(), +): readonly ColumnSchema[] { + return [ + ID_COLUMN, + ...definition.properties.map( + (property): ColumnSchema => ({ + name: property.name, + type: propertyTypeText(property), + nullable: true, + isPrimary: false, + }), + ), + ...definition.vectors.map( + (vector): ColumnSchema => ({ + name: vectorColumnName(vector.name), + type: vectorTypeText(vector, dimensions.get(vector.name) ?? null), + nullable: true, + isPrimary: false, + }), + ), + ]; +} + +/** One index per vector, named by its column. Inverted indexes are per-property flags in the Source. */ +export function weaviateIndexes(definition: WeaviateClass): readonly IndexSchema[] { + return definition.vectors.map( + (vector): IndexSchema => ({ + name: vectorColumnName(vector.name), + columns: [vectorColumnName(vector.name)], + unique: false, + }), + ); +} + +/** What a console request reads from the collection it names (spec 5.3, W3, W6, W11). */ +export interface WeaviateCollectionFacts { + readonly name: string; + readonly multiTenant: boolean; + readonly autoTenantActivation: boolean; + readonly vectors: readonly WeaviateVector[]; + /** Every top-level property's GraphQL selection, by name; a cross-reference has none. */ + readonly selections: ReadonlyMap; + /** The non-reference properties, in schema order: what REST answers when a request names no property. */ + readonly plainProperties: readonly string[]; + /** The properties typed `int` or `int[]`, whose GraphQL nulls outside int32 are marked (spec 5.2). */ + readonly intProperties: ReadonlySet; + /** The reference properties, which a request may not select in this version. */ + readonly referenceProperties: ReadonlySet; +} + +export function weaviateCollectionFacts(definition: WeaviateClass): WeaviateCollectionFacts { + const selections = new Map(); + for (const property of definition.properties) { + const field = selectionOf(property); + if (field !== undefined) selections.set(property.name, field); + } + return { + name: definition.name, + multiTenant: definition.multiTenant, + autoTenantActivation: definition.autoTenantActivation, + vectors: definition.vectors, + selections, + plainProperties: definition.properties.filter((property) => !property.reference).map((property) => property.name), + intProperties: new Set( + definition.properties + .filter((property) => property.dataType.some((word) => word === "int" || word === "int[]")) + .map((property) => property.name), + ), + referenceProperties: new Set(definition.properties.filter((property) => property.reference).map((p) => p.name)), + }; +} diff --git a/src/lib/db/providers/vector/weaviate/source.ts b/src/lib/db/providers/vector/weaviate/source.ts new file mode 100644 index 0000000000..afcfc9c5c2 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/source.ts @@ -0,0 +1,121 @@ +/** + * A collection's Source (#1566 spec 4.4): two JSON parts, a human surface only, as Qdrant's and Milvus's. + * + * `Schema` is the class definition in Weaviate's own vocabulary, unedited (spec W9). `State` is what the collection + * holds: the aliases that point at it, then for a single-tenant collection its shards with their statuses and its + * exact object count, and for a multi-tenant one its tenant count and the first 1,024 tenants by name with their + * activity statuses, as Milvus lists partitions. Tenant and alias names are data, serialised with `JSON.stringify`. + * + * Pure: it receives the answers and never a client. + */ +import { applySourceBound } from "@/lib/db/object-kinds"; +import type { ObjectSourcePart } from "@/lib/db/types"; +import { WEAVIATE_BOUNDS } from "./routes"; +import type { WeaviateClass } from "./schema"; + +type JsonObject = Readonly>; + +export interface WeaviateSourceInput { + readonly definition: WeaviateClass; + /** The `GET /v1/aliases` answer. */ + readonly aliases: unknown; + /** The `GET /v1/schema/{collection}/shards` answer, or null for a multi-tenant collection. */ + readonly shards: unknown; + /** The `GET /v1/schema/{collection}/tenants` answer, or null for a single-tenant collection. */ + readonly tenants: unknown; + /** The exact count, or null where none was read. */ + readonly count: number | null; +} + +function isObject(value: unknown): value is JsonObject { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +export const PER_TENANT_COUNT = + 'Per-tenant counts are not read here: run POST /v1/aggregate/ {"tenant": ""} for one HOT tenant.'; +export const COUNT_NOT_READ = "not read: the aggregate count failed or this server answered none"; + +/** The alias names that point at `collection`. */ +function aliasesOf(aliases: unknown, collection: string): readonly string[] { + if (!isObject(aliases) || !Array.isArray(aliases.aliases)) return []; + return aliases.aliases.flatMap((entry: unknown) => + isObject(entry) && entry.class === collection && typeof entry.alias === "string" ? [entry.alias] : [], + ); +} + +function shardsOf(shards: unknown): readonly JsonObject[] { + if (!Array.isArray(shards)) return []; + return shards.flatMap((entry: unknown) => + isObject(entry) + ? [ + { + name: entry.name, + status: entry.status, + ...(entry.vectorQueueSize === undefined ? {} : { vectorQueueSize: entry.vectorQueueSize }), + }, + ] + : [], + ); +} + +function tenantsOf(tenants: unknown): { readonly total: number; readonly listed: readonly JsonObject[] } { + if (!Array.isArray(tenants)) return { total: 0, listed: [] }; + const entries = tenants + .flatMap((entry: unknown) => + isObject(entry) && typeof entry.name === "string" + ? [{ name: entry.name, activityStatus: entry.activityStatus ?? null }] + : [], + ) + .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0)); + return { total: entries.length, listed: entries.slice(0, WEAVIATE_BOUNDS.sourceTenants) }; +} + +/** The `State` part's document. */ +export function weaviateStateDocument(input: WeaviateSourceInput): JsonObject { + const { definition } = input; + const base = { + multiTenant: definition.multiTenant, + ...(definition.multiTenant ? { autoTenantActivation: definition.autoTenantActivation } : {}), + aliases: aliasesOf(input.aliases, definition.name), + }; + if (definition.multiTenant) { + const { total, listed } = tenantsOf(input.tenants); + return { + ...base, + tenantCount: total, + tenants: listed, + ...(total > listed.length ? { tenantsListed: `the first ${listed.length} of ${total} by name` } : {}), + objectCount: PER_TENANT_COUNT, + }; + } + return { + ...base, + shards: shardsOf(input.shards), + objectCount: input.count ?? COUNT_NOT_READ, + ...(input.count === null ? {} : { objectCountKind: "exact, aggregate meta.count" }), + }; +} + +function jsonPart(id: string, label: string, document: JsonObject, limit: number | undefined): ObjectSourcePart { + const bounded = applySourceBound(JSON.stringify(document, null, 2), limit); + return { + id, + label, + text: bounded.text, + language: "json", + form: "complete", + origin: "rendered", + ...(bounded.truncated === undefined ? {} : { truncated: bounded.truncated }), + }; +} + +/** The two parts, Schema then State, each cut at the caller's bound through the shared helper. */ +export function weaviateSourceParts( + input: WeaviateSourceInput, + limit?: number, +): readonly [ObjectSourcePart, ObjectSourcePart] { + return [ + jsonPart("schema", "Schema", input.definition.definition, limit), + jsonPart("state", "State", weaviateStateDocument(input), limit), + ]; +} diff --git a/src/lib/db/providers/vector/weaviate/sql-grammar.ts b/src/lib/db/providers/vector/weaviate/sql-grammar.ts new file mode 100644 index 0000000000..be34cbb731 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/sql-grammar.ts @@ -0,0 +1,18 @@ +import { DEFAULT_SQL_GRAMMAR, NO_EXTRA_WORDS } from "@/lib/db/sql-grammar/shared"; +import type { SqlGrammarSpec } from "@/lib/db/sql-grammar/types"; + +/** How Weaviate statement text is read: grammar, SQL text, redaction, update target and completion. */ +export const WEAVIATE_SQL_GRAMMAR: SqlGrammarSpec = { + grammar: DEFAULT_SQL_GRAMMAR, + // `weaviate` takes one Weaviate console request (#1566 spec 5.1), a `METHOD /v1/path` line and one JSON body, + // which is not SQL text either: its strings escape with a backslash and `//` opens a comment outside a string. + // Its provider extends `BaseDatabaseProvider` and parses the text with the shared console parser. + readsSqlText: false, + redaction: { kind: "none" }, + updateTarget: { + dashCommentNeedsSeparator: false, + extraQueryOpeners: NO_EXTRA_WORDS, + extraSetOperators: NO_EXTRA_WORDS, + }, + completion: { formatSegment: null, readQuotedQualifier: null }, +}; diff --git a/src/lib/db/providers/vector/weaviate/sql-writing.ts b/src/lib/db/providers/vector/weaviate/sql-writing.ts new file mode 100644 index 0000000000..ea754b8465 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/sql-writing.ts @@ -0,0 +1,44 @@ +import { + EXACT_DECIMAL_TYPE_NAMES, + FLOAT64_TYPE_NAMES, + identifierDoubleQuoted, + INSTANT_TYPE_NAMES, + literalStandard, + NO_BARE_SPELLING, + NOTHING_STANDS_ALONE, + NULL_NON_FINITE, + STANDARD_DDL_TYPES, + STANDARD_TYPE_VOCABULARY, + unquoteStandard, +} from "@/lib/db/sql-writing/shared"; +import { binaryStandardHex } from "@/lib/db/sql-writing/export-shared"; +import type { SqlWritingSpec } from "@/lib/db/sql-writing/types"; + +/** How a generated statement spells a literal, a name and a bind for Weaviate. */ +export const WEAVIATE_SQL_WRITING: SqlWritingSpec = { + // This engine declares `queryLanguage: "json"`, so no statement is ever built for it to + // read. What a generator emits for such a connection is portable SQL meant to run elsewhere, + // and the standard form is the only thing it can claim. + escapeLiteral: literalStandard, + unescapeLiteral: unquoteStandard, + // The SQL standard form, which this engine's generators fall back to. + quoteIdentifier: identifierDoubleQuoted, + placeholder: null, + temporalLiteral: null, + inlineEdit: { + instantTypeNames: INSTANT_TYPE_NAMES, + exactDecimalTypeNames: EXACT_DECIMAL_TYPE_NAMES, + float64TypeNames: FLOAT64_TYPE_NAMES, + }, + export: { + ddlTypes: STANDARD_DDL_TYPES, + standsAlone: NOTHING_STANDS_ALONE, + bareSpelling: NO_BARE_SPELLING, + typeVocabulary: STANDARD_TYPE_VOCABULARY, + // This engine declares `queryLanguage: "json"`, so no statement is ever built for it to + // read, and the standard form is the only thing an export can claim (as for its literal). + binaryLiteral: binaryStandardHex, + nonFinite: NULL_NON_FINITE, + insertForm: "values", + }, +}; diff --git a/src/lib/db/providers/vector/weaviate/versions.ts b/src/lib/db/providers/vector/weaviate/versions.ts new file mode 100644 index 0000000000..c804b676f8 --- /dev/null +++ b/src/lib/db/providers/vector/weaviate/versions.ts @@ -0,0 +1,95 @@ +/** + * The version a Weaviate server reports and the path it decides (#1566 spec 3.3). Pure. + * + * `GET /v1/meta` answers `{"version", "hostname", "modules", ...}` and `version` was a plain `major.minor.patch` on + * every server measured (1.37.4 to 1.40.2). By precedent (Qdrant, Milvus and InfluxDB read the version and decide by + * a table; no provider probes features), the version alone picks, per search, the REST route or the GraphQL read. + * + * REST search did not arrive in version order (spec A.2): 1.38.22 carries the routes behind + * `EXPERIMENTAL_REST_SEARCH_ENABLED`, 1.39.0 has none, 1.39.6 has them behind the flag, 1.39.7 serves them by + * default, and near-vector starts at 1.39.8. So REST is chosen from 1.39.7 (near-vector from 1.39.8), and GraphQL + * below that, where a flag-on 1.38 server would also answer REST: both paths return the same rows, and the flag is + * configuration the version cannot show. A version that cannot be read takes GraphQL. + */ + +/** A released version as three numbers. */ +export type WeaviateRelease = readonly [major: number, minor: number, patch: number]; + +export interface WeaviateVersion { + /** `version` as the server wrote it, when it is a short token safe to repeat; null otherwise. */ + readonly reported: string | null; + /** The three numbers of a plain `major.minor.patch`; null for anything else. */ + readonly release: WeaviateRelease | null; +} + +/** + * The versions this provider is tested against, one per server shape of the fixture matrix: the newest line, the + * 1.38 line whose REST search sits behind a flag, and DigitalOcean's (decisions of 2026-10-23). + */ +export const WEAVIATE_TESTED_VERSIONS: readonly string[] = Object.freeze(["1.40.2", "1.38.22", "1.37.4"]); + +/** The oldest line version 1 supports (decision, spec 15): end of life upstream, kept for a managed service. */ +export const WEAVIATE_FLOOR: WeaviateRelease = [1, 37, 0]; + +/** The first release that serves bm25, hybrid, near-object and aggregate over REST without a flag. */ +export const REST_SEARCH_SINCE: WeaviateRelease = [1, 39, 7]; +/** The first release with the near-vector REST route. */ +export const REST_NEAR_VECTOR_SINCE: WeaviateRelease = [1, 39, 8]; + +const PLAIN_RELEASE = /^v?(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})\.(0|[1-9]\d{0,5})$/; +/** A version text short and plain enough to repeat in a sentence: `1.41.0-rc.1`, never a server's free text. */ +const REPEATABLE = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,31}$/; + +/** The version in the text of a `GET /v1/meta` answer. A body that is not a JSON object, or holds no string `version`, reports none. */ +export function readWeaviateVersion(metaAnswerText: string): WeaviateVersion { + let parsed: unknown; + try { + parsed = JSON.parse(metaAnswerText); + } catch { + return { reported: null, release: null }; + } + const version = + typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) + ? (parsed as { readonly version?: unknown }).version + : undefined; + if (typeof version !== "string") return { reported: null, release: null }; + const plain = PLAIN_RELEASE.exec(version); + return { + reported: REPEATABLE.test(version) ? version : null, + release: plain === null ? null : [Number(plain[1]), Number(plain[2]), Number(plain[3])], + }; +} + +/** Whether the server is at `needs` or later. A version that cannot be read is older than every release. */ +export function serverHas(version: WeaviateVersion, needs: WeaviateRelease): boolean { + const { release } = version; + if (release === null) return false; + for (let part = 0; part < 3; part++) { + if (release[part] !== needs[part]) return release[part] > needs[part]; + } + return true; +} + +/** The path a search or aggregate starts on. */ +export type WeaviatePath = "rest" | "graphql"; + +/** Whether the operation is near-vector, which needs a later release than the other searches. */ +export type WeaviatePathKind = "near-vector" | "other"; + +/** The table of spec 3.3: the path the version decides for one search. */ +export function initialPath(version: WeaviateVersion, kind: WeaviatePathKind): WeaviatePath { + return serverHas(version, kind === "near-vector" ? REST_NEAR_VECTOR_SINCE : REST_SEARCH_SINCE) ? "rest" : "graphql"; +} + +/** A sentence naming the server's version, for a refusal or a result header. */ +export function versionText(version: WeaviateVersion): string { + if (version.release !== null) return version.release.join("."); + if (version.reported !== null) return `${version.reported}, which is not a plain release number`; + return "a version it did not report"; +} + +/** The warning a connection to a server older than the floor carries; undefined at or above it (spec 3.1). */ +export function belowFloorWarning(version: WeaviateVersion): string | undefined { + if (version.release === null || serverHas(version, WEAVIATE_FLOOR)) return undefined; + return `This Weaviate server is ${version.release.join(".")}, older than ${WEAVIATE_FLOOR.slice(0, 2).join(".")}, the oldest line Studio supports; nothing below it is tested.`; +} diff --git a/src/lib/db/query-dialects.ts b/src/lib/db/query-dialects.ts index 5762471652..1a6e44c833 100644 --- a/src/lib/db/query-dialects.ts +++ b/src/lib/db/query-dialects.ts @@ -4,7 +4,7 @@ import type { QueryTab } from "@/lib/types"; /** * The dialect registry: what each query dialect a provider may declare means for the editor's readers. * - * A dialect is JSON or a command line that is not MongoDB's JSON (Redis, LibreDB, Kafka, etcd, Milvus, Qdrant, Oxia), so every reader + * A dialect is JSON or a command line that is not MongoDB's JSON (Redis, LibreDB, Kafka, etcd, Milvus, Qdrant, Weaviate, Oxia), so every reader * keyed on the language alone would treat its text as a MongoDB document, which is the #427 class. Before this * module each reader carried an arm per dialect, about twenty of them, and a missed arm made a tree click * auto-run a MongoDB `find`. Each dialect is now one record here, one in `DIALECT_EDITORS` @@ -93,6 +93,15 @@ export const QUERY_DIALECTS: Readonly> = Objec offersCountQuery: false, offersSqlExport: false, }), + // Weaviate (#1566 spec 3.4): as Qdrant, a collection's columns include vectors, so neither a profile, a model nor a + // count statement of a SQL grammar applies (a count is the aggregate request), and neither SQL export format applies. + weaviate: Object.freeze({ + tabType: "weaviate", + offersColumnProfiling: false, + offersCodeGeneration: false, + offersCountQuery: false, + offersSqlExport: false, + }), // Oxia (O10): a command line of the oxia client read verbs. Its rows are records of a fixed shape, so no // profile, model or count statement of its grammar applies, and neither SQL export format applies. oxia: Object.freeze({ diff --git a/src/lib/db/sql-grammar/index.ts b/src/lib/db/sql-grammar/index.ts index 0ff7892817..413875e525 100644 --- a/src/lib/db/sql-grammar/index.ts +++ b/src/lib/db/sql-grammar/index.ts @@ -31,6 +31,7 @@ import { OXIA_SQL_GRAMMAR } from "@/lib/db/providers/keyvalue/oxia/sql-grammar"; import { POSTGRES_SQL_GRAMMAR } from "@/lib/db/providers/sql/postgres-sql-grammar"; import { PROMETHEUS_SQL_GRAMMAR } from "@/lib/db/providers/timeseries/prometheus/sql-grammar"; import { QDRANT_SQL_GRAMMAR } from "@/lib/db/providers/vector/qdrant/sql-grammar"; +import { WEAVIATE_SQL_GRAMMAR } from "@/lib/db/providers/vector/weaviate/sql-grammar"; import { RABBITMQ_SQL_GRAMMAR } from "@/lib/db/providers/stream/rabbitmq/sql-grammar"; import { REDIS_SQL_GRAMMAR } from "@/lib/db/providers/keyvalue/redis-sql-grammar"; import { S3_SQL_GRAMMAR } from "@/lib/db/providers/objectstore/s3/sql-grammar"; @@ -92,6 +93,7 @@ export const SQL_GRAMMAR: Readonly> = Objec sparkplug: SPARKPLUG_SQL_GRAMMAR, sqlite: SQLITE_SQL_GRAMMAR, trino: TRINO_SQL_GRAMMAR, + weaviate: WEAVIATE_SQL_GRAMMAR, }); /** diff --git a/src/lib/db/sql-writing/index.ts b/src/lib/db/sql-writing/index.ts index b9f1fc808a..4ec595adca 100644 --- a/src/lib/db/sql-writing/index.ts +++ b/src/lib/db/sql-writing/index.ts @@ -41,6 +41,7 @@ import { INFLUXDB3_SQL_WRITING } from "@/lib/db/providers/timeseries/influxdb/in import { PROMETHEUS_SQL_WRITING } from "@/lib/db/providers/timeseries/prometheus/sql-writing"; import { MILVUS_SQL_WRITING } from "@/lib/db/providers/vector/milvus/sql-writing"; import { QDRANT_SQL_WRITING } from "@/lib/db/providers/vector/qdrant/sql-writing"; +import { WEAVIATE_SQL_WRITING } from "@/lib/db/providers/vector/weaviate/sql-writing"; import { NO_CONNECTION_SQL_WRITING } from "./no-connection"; import type { SqlWritingSpec } from "./types"; import { UNKNOWN_TYPE_SQL_WRITING } from "./unknown-type"; @@ -96,6 +97,7 @@ export const SQL_WRITING: Readonly> = Objec sparkplug: SPARKPLUG_SQL_WRITING, sqlite: SQLITE_SQL_WRITING, trino: TRINO_SQL_WRITING, + weaviate: WEAVIATE_SQL_WRITING, }); /** diff --git a/src/lib/db/types.ts b/src/lib/db/types.ts index 5767fea741..5bba6cf0b5 100644 --- a/src/lib/db/types.ts +++ b/src/lib/db/types.ts @@ -981,6 +981,10 @@ export interface ProviderCapabilities { * line and one JSON body, the closed console the provider re-serialises from its own parse. It landed through * one record in each registry and no arm anywhere else. * + * `"weaviate"` is the Weaviate provider's (#1566 spec 5.1): its editor text is one `METHOD /v1/path` request line + * and one JSON body in Weaviate's REST shape, the closed console the provider runs over REST or GraphQL as the + * server's version decides. It landed through one record in each registry and no arm anywhere else. + * * `"oxia"` is the Oxia provider's: one `oxia client` read command per run (O10). * * `"s3"` is the S3 provider's: one AWS CLI read command per run, `aws s3 ls`, the `aws s3api` reads its table names, @@ -1007,6 +1011,7 @@ export interface ProviderCapabilities { | "etcd" | "milvus" | "qdrant" + | "weaviate" | "oxia" | "s3" | "mqtt" diff --git a/src/lib/editor/dialect-editors.ts b/src/lib/editor/dialect-editors.ts index 93d5b63b3a..26755232f0 100644 --- a/src/lib/editor/dialect-editors.ts +++ b/src/lib/editor/dialect-editors.ts @@ -4,6 +4,7 @@ import { formatConsole } from "@/lib/db/console/format"; import { MTC_CONSOLE_DIALECT, MTC_CONSOLE_ROUTES } from "@/lib/db/providers/industrial/mtconnect/routes"; import { MILVUS_CONSOLE, MILVUS_ROUTES } from "@/lib/db/providers/vector/milvus/routes"; import { QDRANT_CONSOLE, QDRANT_ROUTES } from "@/lib/db/providers/vector/qdrant/routes"; +import { WEAVIATE_CONSOLE, WEAVIATE_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; import { type ConsoleLanguage, registerConsoleLanguage } from "@/lib/editor/console-language"; import type { EditorLanguage } from "@/lib/editor/tab-language"; import type { SqlGrammar } from "@/lib/sql/grammar"; @@ -61,6 +62,9 @@ const MILVUS_CONSOLE_LANGUAGE: ConsoleLanguage = Object.freeze({ spec: MILVUS_CO /** The Qdrant console: its dialect and its route table, which register the Monaco language `qdrant` (3.5, 6.4). */ const QDRANT_CONSOLE_LANGUAGE: ConsoleLanguage = Object.freeze({ spec: QDRANT_CONSOLE, routes: QDRANT_ROUTES }); +/** The Weaviate console: its dialect and its route table, which register the Monaco language `weaviate` (#1566 3.4). */ +const WEAVIATE_CONSOLE_LANGUAGE: ConsoleLanguage = Object.freeze({ spec: WEAVIATE_CONSOLE, routes: WEAVIATE_ROUTES }); + /** * MTConnect's request line, drawn by the shared console over the route table the guard runs. * @@ -105,6 +109,12 @@ export const DIALECT_EDITORS: Readonly> format: (text: string) => formatConsole(QDRANT_CONSOLE, text), console: QDRANT_CONSOLE_LANGUAGE, }), + // A Weaviate request renders in its own console language and formats through the console formatter, as Qdrant's. + weaviate: Object.freeze({ + monacoId: "weaviate", + format: (text: string) => formatConsole(WEAVIATE_CONSOLE, text), + console: WEAVIATE_CONSOLE_LANGUAGE, + }), // InfluxQL declares a language and no dialect, as PromQL and Cypher do, and has no formatter: no Format for an // InfluxQL tab (InfluxDB spec I12). influxql: Object.freeze({ monacoId: "influxql" }), diff --git a/src/lib/editor/tab-language.ts b/src/lib/editor/tab-language.ts index be88b1a189..7660ed8c55 100644 --- a/src/lib/editor/tab-language.ts +++ b/src/lib/editor/tab-language.ts @@ -14,6 +14,7 @@ export type EditorLanguage = | "graph-cypher" | "milvus" | "qdrant" + | "weaviate" | "influxql" | "oxia" | "s3" diff --git a/src/lib/query-generators.ts b/src/lib/query-generators.ts index 9586328947..bfef5fe19d 100644 --- a/src/lib/query-generators.ts +++ b/src/lib/query-generators.ts @@ -14,6 +14,7 @@ import { influxqlSource, quoteInfluxqlIdentifier } from "@/lib/db/providers/time import { metricSelector } from "@/lib/db/providers/timeseries/prometheus/promql"; import { milvusSelectQuery, milvusTableQuery } from "@/lib/db/providers/vector/milvus/generators"; import { qdrantSelectQuery, qdrantTableQuery } from "@/lib/db/providers/vector/qdrant/generators"; +import { weaviateSelectQuery, weaviateTableQuery } from "@/lib/db/providers/vector/weaviate/generators"; import { type ObjectReadRange, offersCountQuery, @@ -922,6 +923,12 @@ const DIALECT_GENERATORS: Readonly> = Ob table: (path) => qdrantTableQuery(path), select: (path, columns) => qdrantSelectQuery(path, columns), }, + // Weaviate reads a collection through its own console request (#1566 spec 6.4), written by the provider's + // generators: the click lists the first objects, Generate Request writes a near-vector search without running it. + weaviate: { + table: (path) => weaviateTableQuery(path), + select: (path, columns) => weaviateSelectQuery(path, columns), + }, // Oxia reads a key through an oxia client command (SB2-4.5), written by the provider's browser-safe generators.ts: // the click is `get `, and "Generate Command" that get with the `list --prefix` and `range-scan --prefix` forms // as comments. No shipped click reaches them in v1 (a key row opens its Source tab, SB2-12 D2). Neither reads the diff --git a/src/lib/seed/types.ts b/src/lib/seed/types.ts index ee845e3e0c..5403f92f43 100644 --- a/src/lib/seed/types.ts +++ b/src/lib/seed/types.ts @@ -108,6 +108,7 @@ const SeedDatabaseType = z.enum([ "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", diff --git a/src/lib/sql/fence-tags.ts b/src/lib/sql/fence-tags.ts index 0661b51da4..8f8de4a6dd 100644 --- a/src/lib/sql/fence-tags.ts +++ b/src/lib/sql/fence-tags.ts @@ -100,6 +100,9 @@ const ENGINE_FENCE_TAGS: Readonly> = Object.freeze({ // is registered below: `json` is a MongoDB document as often, `http` and `rest` name no engine, and // `fenceTagEngine` is what decides whether a plan's deliverable was written for THIS connection. qdrant: true, + // A ```weaviate block holds one Weaviate console request the editor runs as it is (#1566 spec 3.4). No alias is + // registered: `graphql` would read as a request this console refuses, and `json` names no engine. + weaviate: true, // An ```influxdb block holds one InfluxQL statement the editor runs as it is. The `influxql` alias below // spells the language, and it still names this engine: see its entry. No `flux` tag is registered anywhere: // no type-id runs Flux, and an alias would make a Flux block look runnable on `influxdb`. diff --git a/src/lib/types.ts b/src/lib/types.ts index e9e65a278f..8a0c7cf412 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -127,6 +127,12 @@ export type DatabaseType = // `queryDialect` of its own. The connection is one REST endpoint plus TLS and an API key or JWT in `password`; // there is no user and no database, and `readOnly` is a mode its provider enforces. | "qdrant" + // Weaviate (#1566). A vector database read over its REST API, and over GraphQL for the searches of a server below + // 1.39.7, by a client of this repository's own on the shared node transport, a member of the `vector/` family. Its + // editor text is Weaviate's own `METHOD /v1/path` request with one JSON body, so it declares `queryLanguage: + // "json"` with a `queryDialect` of its own. The connection is one endpoint plus TLS and an API key or OIDC access + // token in `password`; there is no user and no database, and `readOnly` is a mode its provider enforces. + | "weaviate" // InfluxDB (InfluxDB spec I2). A time-series store read over the v1 `/query` endpoint, as a form POST (R14), in // InfluxQL: the TSM generation (1.x, and 2.x through its virtual DBRP mappings) and InfluxDB 3 through its // v1-compatible handler. It declares `queryLanguage: "influxql"`. The connection is a host, a port, an optional @@ -1029,6 +1035,7 @@ export interface QueryTab { | "cypher" | "milvus" | "qdrant" + | "weaviate" | "influxql" | "oxia" | "s3" diff --git a/src/styles/theme.css b/src/styles/theme.css index db71acf093..53fb689d55 100644 --- a/src/styles/theme.css +++ b/src/styles/theme.css @@ -235,6 +235,14 @@ --studio-hue-slate-alt: #0f172b; --studio-hue-taupe: #473c39; --studio-hue-mauve: #463947; + /* Weaviate (#1566). Every base hue, every `-alt` step and the greys mist, slate, taupe, stone, neutral, + mauve and olive were an engine's by the time it registered, so the palette gains `zinc`, the grey the + Modbus note measured as clearing every test. MEASURED against this file: `zinc-900` in light and + `zinc-400` in dark leave both closest identity pairs where they were (0.0205 light, amber-alt vs + orange; 0.0076 dark, stone vs taupe); its nearest identity is `slate-alt` at 0.0362 in light and + `mauve` at 0.0130 in dark. `zinc-800` falls to 0.0110 from `stone` and `zinc-700` to 0.0175 from + `mist`, each tightening the light set. */ + --studio-hue-zinc: #18181b; } .dark { @@ -367,6 +375,7 @@ --studio-hue-slate-alt: #cad5e2; --studio-hue-taupe: #aba09c; --studio-hue-mauve: #a89ea9; + --studio-hue-zinc: #9f9fa9; } /* @@ -482,6 +491,7 @@ --color-hue-slate-alt: var(--studio-hue-slate-alt); --color-hue-taupe: var(--studio-hue-taupe); --color-hue-mauve: var(--studio-hue-mauve); + --color-hue-zinc: var(--studio-hue-zinc); --color-hue-teal-solid: var(--studio-hue-teal-solid); --color-hue-teal-solid-hover: var(--studio-hue-teal-solid-hover); --color-hue-purple-solid: var(--studio-hue-purple-solid); diff --git a/tests/components/QueryEditor.test.tsx b/tests/components/QueryEditor.test.tsx index 8d11ea8352..c2d38b556c 100644 --- a/tests/components/QueryEditor.test.tsx +++ b/tests/components/QueryEditor.test.tsx @@ -2079,10 +2079,10 @@ describe("QueryEditor", () => { expect(capturedLanguageRegistrations).toContain("graph-cypher"); }); - test("registers the three console languages after the custom languages, before the editor mounts (vector-family spec 3.8)", () => { + test("registers the four console languages after the custom languages, before the editor mounts (vector-family spec 3.8)", () => { render(React.createElement(QueryEditor, createDefaultProps({ language: "sql", value: "SELECT 1" }))); - // registerDialectConsoles runs on every mount, and the Milvus, Qdrant and MTConnect records are the ones that carry a console + // registerDialectConsoles runs on every mount, and the Milvus, Qdrant, Weaviate and MTConnect records are the ones that carry a console // language, registered in the record's order. expect(capturedLanguageRegistrations).toEqual([ "libredb", @@ -2097,6 +2097,7 @@ describe("QueryEditor", () => { "influxql", "milvus", "qdrant", + "weaviate", "mtconnect", ]); }); diff --git a/tests/fixtures/dialect-registry/golden-dialect-outputs.json b/tests/fixtures/dialect-registry/golden-dialect-outputs.json index 67ff83b690..dea9d06e70 100644 --- a/tests/fixtures/dialect-registry/golden-dialect-outputs.json +++ b/tests/fixtures/dialect-registry/golden-dialect-outputs.json @@ -311,6 +311,18 @@ "selectQuery": "// Collection \"Order\\\"Items\" declares no vector to search.", "countQuery": null }, + "weaviate": { + "queryLanguage": "json", + "queryDialect": "weaviate", + "tabType": "weaviate", + "monacoLanguage": "weaviate", + "offersColumnProfiling": false, + "offersCodeGeneration": false, + "offersCountQuery": false, + "tableQuery": "GET /v1/objects?class=Order%22Items&limit=50", + "selectQuery": "// Collection \"Order\\\"Items\" declares no vector to search.\nPOST /v1/search/Order%22Items/bm25\n{\"query\": \"your words\", \"limit\": 10}", + "countQuery": null + }, "influxdb": { "queryLanguage": "influxql", "queryDialect": null, diff --git a/tests/fixtures/weaviate/README.md b/tests/fixtures/weaviate/README.md new file mode 100644 index 0000000000..a2d396595f --- /dev/null +++ b/tests/fixtures/weaviate/README.md @@ -0,0 +1,32 @@ +# Weaviate captures + +What the Weaviate provider sent to the fixture servers of [`docker/weaviate/README.md`](../../../docker/weaviate/README.md), what each server answered, and what each provider call returned or threw, one scenario per file. +The integration test `tests/integration/db/weaviate-provider.test.ts` replays these files through a transport that answers from them; no test here reaches a live server. + +## Where they come from + +`tests/live/weaviate-evidence.ts` writes every file, `/.json`, one per scenario of `tests/live/weaviate-scenarios.ts`. +Each file records the image, its digest, the server version, the date, the runtime and the credential the scenario used, the transport each connect built, every exchange (method, path, body, then the answer or the error the transport threw) and every outcome (a value, or an error's class and message). +A credential header is recorded as `Bearer `, never as its value, and the harness refuses to write a file that holds any key it read. + +## The scenarios + +- `surface`: the tree, the columns, the Source and the panels, on `weaviate` (1.40.2), `weaviate-1-38`, `weaviate-1-37` and `weaviate-nographql`. +- `reads`: every read route, the tenant guard and the not-found answers, on 1.40.2 and 1.37.4. +- `searches`: BM25, hybrid at `alpha` 0, near-vector, near-object and aggregates in the REST shape, run over REST on 1.40.2 and over GraphQL on 1.38.22 and 1.37.4. +- `refusals`: what is refused before anything is sent. +- `weaviate-auth`: the `viewer` user, the root user, a wrong key and no key. +- `weaviate-tls`: the `viewer` user over TLS with the fixture's CA, and plain HTTP to the TLS port. + +## Running it + +Bring the six services up as `docker/weaviate/README.md` says, then copy the keys volume out, outside the repository: + +```sh +dir=$(mktemp -d) +docker cp libredb-weaviate-auth:/keys "$dir/keys" +bun tests/live/weaviate-evidence.ts --keys "$dir/keys" +bun tests/live/weaviate-live-check.ts --keys "$dir/keys" +``` + +The live check holds a fresh run to these files and checks that no run changed the schema, the aliases or any tenant's status. diff --git a/tests/fixtures/weaviate/weaviate-1-37/reads.json b/tests/fixtures/weaviate/weaviate-1-37/reads.json new file mode 100644 index 0000000000..fc3043d772 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-1-37/reads.json @@ -0,0 +1,3088 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-1-37", + "scenario": "reads", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.37.4", + "digest": "sha256:fcd0d4dfe70ed38feb2c12df58f991f3437bdf34ac022d978a48844c3ac86ea0", + "version": "1.37.4", + "date": "2026-10-23T23:54:52.821Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18281", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.37.4\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.37.4\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"U20yv34cKfld\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases/Articles", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"alias\":\"Articles\",\"class\":\"Article\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":3},\"gitHash\":\"7c1e318\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":null,\"status\":\"HEALTHY\",\"version\":\"1.37.4\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes?output=verbose", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":3},\"gitHash\":\"7c1e318\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":[{\"asyncReplicationStatus\":[],\"class\":\"TenantNotes\",\"compressed\":false,\"loaded\":true,\"name\":\"globex\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"TenantNotes\",\"compressed\":false,\"loaded\":true,\"name\":\"acme\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"TenantNotesAuto\",\"compressed\":false,\"loaded\":true,\"name\":\"hooli\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"EdgeValues\",\"compressed\":false,\"loaded\":true,\"name\":\"6sQaztKPiaRF\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Empty\",\"compressed\":false,\"loaded\":true,\"name\":\"xoamC7a4yZNs\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Author\",\"compressed\":false,\"loaded\":true,\"name\":\"GnuDbpXNjuzT\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Article\",\"compressed\":false,\"loaded\":true,\"name\":\"U20yv34cKfld\",\"numberOfReplicas\":1,\"objectCount\":500,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Product\",\"compressed\":false,\"loaded\":true,\"name\":\"DPHQSkhVwydj\",\"numberOfReplicas\":1,\"objectCount\":200,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0}],\"stats\":{\"objectCount\":700,\"shardCount\":8},\"status\":\"HEALTHY\",\"version\":\"1.37.4\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes/Article?output=verbose", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":3},\"gitHash\":\"7c1e318\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":[{\"asyncReplicationStatus\":[],\"class\":\"Article\",\"compressed\":false,\"loaded\":true,\"name\":\"U20yv34cKfld\",\"numberOfReplicas\":1,\"objectCount\":500,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0}],\"stats\":{\"objectCount\":500,\"shardCount\":1},\"status\":\"HEALTHY\",\"version\":\"1.37.4\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=3", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754772770,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754772770,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754772983,\"id\":\"0092cefc-15f3-507f-a85c-2453b81d8c8c\",\"lastUpdateTimeUnix\":1792754772983,\"properties\":{\"body\":\"cosine quantize alias object collection tenant collection shard tenant engine alias hybrid\",\"category\":\"delta\",\"location\":{\"latitude\":59.91,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":4.73,\"tags\":[\"collection\",\"keyword\",\"vector\"],\"title\":\"article 473 keyword search\",\"wordCount\":573,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\",\"href\":\"/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\"}]},\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754772919,\"id\":\"00df1951-be86-5fc4-9acb-b15841334bdf\",\"lastUpdateTimeUnix\":1792754772919,\"properties\":{\"body\":\"search quantize hybrid engine collection keyword node collection object shard vector quantize\",\"category\":\"beta\",\"location\":{\"latitude\":59.743,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":3.06,\"tags\":[\"filter\",\"node\",\"tenant\"],\"title\":\"article 306 alias tenant\",\"wordCount\":406,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null}],\"totalResults\":3}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=2&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754772770,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754772770,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754772983,\"id\":\"0092cefc-15f3-507f-a85c-2453b81d8c8c\",\"lastUpdateTimeUnix\":1792754772983,\"properties\":{\"body\":\"cosine quantize alias object collection tenant collection shard tenant engine alias hybrid\",\"category\":\"delta\",\"location\":{\"latitude\":59.91,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":4.73,\"tags\":[\"collection\",\"keyword\",\"vector\"],\"title\":\"article 473 keyword search\",\"wordCount\":573,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\",\"href\":\"/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\"}]},\"vector\":[-0.348508,0.371256,-0.002633,0.438731,0.926627,0.645241,-0.489321,0.334734,-0.536027,0.075017,0.195246,-0.898757,-0.389559,-0.054653,0.906537,-0.046758],\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792754773037,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792754773037,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=25", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=EdgeValues&limit=8", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":9007199254740991,\"bigs\":[9007199254740991,1],\"label\":\"9007199254740991\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"0a225532-c59c-5c0e-a365-e9feabb88bb5\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":-9223372036854776000,\"bigs\":[-9223372036854776000,1],\"label\":\"-9223372036854775808\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"3984d4bc-224d-5e18-914c-d8bc85b5d189\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":9223372036854776000,\"bigs\":[9223372036854776000,1],\"label\":\"9223372036854775807\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"5dd5d8d9-71eb-5aea-94a7-ab89ee407a8f\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":42,\"bigs\":[42,1],\"label\":\"42\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"85cfb82b-1e89-5b48-b745-e5b05e1566c0\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":-42,\"bigs\":[-42,1],\"label\":\"-42\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"b3530c1a-63ca-5bc5-b14f-c55a1771ef5c\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":9007199254740992,\"bigs\":[9007199254740992,1],\"label\":\"9007199254740993\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"b47ca1ec-54e9-5f83-81c2-0e83338906c3\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":0,\"bigs\":[0,1],\"label\":\"0\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754773090,\"id\":\"ed773a9a-e98d-53df-baaf-d4cbd1915be3\",\"lastUpdateTimeUnix\":1792754773090,\"properties\":{\"big\":4611686018427388000,\"bigs\":[4611686018427388000,1],\"label\":\"4611686018427387911\"},\"vectorWeights\":null}],\"totalResults\":8}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"creationTimeUnix\":1792754772770,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"lastUpdateTimeUnix\":1792754772770,\"properties\":{\"body\":\"replica alias collection collection schema engine recall object quantize property schema filter\",\"category\":\"epsilon\",\"location\":{\"latitude\":59.536,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.99,\"tags\":[\"alias\",\"schema\"],\"title\":\"article 099 tenant index\",\"wordCount\":199,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\",\"href\":\"/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\"}]},\"vectorWeights\":null}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d?include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"creationTimeUnix\":1792754772770,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"lastUpdateTimeUnix\":1792754772770,\"properties\":{\"body\":\"replica alias collection collection schema engine recall object quantize property schema filter\",\"category\":\"epsilon\",\"location\":{\"latitude\":59.536,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.99,\"tags\":[\"alias\",\"schema\"],\"title\":\"article 099 tenant index\",\"wordCount\":199,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\",\"href\":\"/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\"}]},\"vector\":[-0.824794,0.547532,0.989252,-0.893327,-0.748434,0.069502,0.659972,0.593562,-0.803924,-0.346175,0.465874,-0.068295,-0.076308,-0.910744,0.029835,-0.034573],\"vectorWeights\":null}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/00000000-0000-0000-0000-000000000000", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=TenantNotes&limit=2&tenant=acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"TenantNotes\",\"creationTimeUnix\":1792754773078,\"id\":\"0d476b6c-11c4-5d8b-9ef1-505058d6cd01\",\"lastUpdateTimeUnix\":1792754773078,\"properties\":{\"note\":\"acme note 11\",\"seq\":11},\"vectorWeights\":null},{\"class\":\"TenantNotes\",\"creationTimeUnix\":1792754773078,\"id\":\"116eeb91-f7bb-5250-91cf-c252e2bc5f38\",\"lastUpdateTimeUnix\":1792754773078,\"properties\":{\"note\":\"acme note 07\",\"seq\":7},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants/umbrella", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&offset=0", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&offset=2", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"756f95fb-f154-5022-a811-ce9d4198c9dc\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"DE\",\"name\":\"author 10\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"91f4c2c0-cd1d-51c1-abaf-b7de23cc0002\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"EE\",\"name\":\"author 08\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&sort=name", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"98fe41ca-2d7c-54e2-b6df-71de7c0a8ae7\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"TR\",\"name\":\"author 01\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&after=00000000-0000-0000-0000-000000000000", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query GET /v1/meta", + "value": { + "fields": [ + "grpcMaxMessageSize", + "hostname", + "modules", + "version" + ], + "rows": [ + { + "grpcMaxMessageSize": 104858000, + "hostname": "http://[::]:8080", + "modules": {}, + "version": "1.37.4" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema", + "value": { + "fields": [ + "class", + "description", + "invertedIndexConfig", + "multiTenancyConfig", + "properties", + "replicationConfig", + "shardingConfig", + "vectorIndexConfig", + "vectorIndexType", + "vectorizer", + "vectorConfig" + ], + "rows": [ + { + "class": "EdgeValues", + "description": "int64 values a float64 cannot hold, one object per value", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "label", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "big" + }, + { + "dataType": [ + "int[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "bigs" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + }, + { + "class": "TenantNotesAuto", + "description": "multi-tenant with autoTenantActivation on", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": true, + "autoTenantCreation": false, + "enabled": true + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "note", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "seq" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 0, + "actualVirtualCount": 0, + "desiredCount": 0, + "desiredVirtualCount": 0, + "function": "", + "key": "", + "strategy": "", + "virtualPerPhysical": 0 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + }, + { + "class": "TenantNotes", + "description": "multi-tenant, a read does not activate a tenant", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": true + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "note", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "seq" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 0, + "actualVirtualCount": 0, + "desiredCount": 0, + "desiredVirtualCount": 0, + "function": "", + "key": "", + "strategy": "", + "virtualPerPhysical": 0 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + }, + { + "class": "Empty", + "description": "no objects", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "label", + "tokenization": "word" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + }, + { + "class": "Product", + "description": "two named vectors with different dimensions and distances", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "name", + "tokenization": "word" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "price" + }, + { + "dataType": [ + "uuid" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "sku" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": null, + "vectorIndexType": null, + "vectorizer": null, + "vectorConfig": { + "image": { + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": { + "none": {} + } + }, + "text": { + "vectorIndexConfig": { + "bq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "distance": "dot", + "pq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "rq": { + "bits": 8, + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "skipDefaultQuantization": false, + "sq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "flat", + "vectorizer": { + "none": {} + } + } + } + }, + { + "class": "Article", + "description": "one unnamed vector, a cross-reference and the common property types", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "indexTimestamps": true, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "title", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "body", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "category", + "tokenization": "field" + }, + { + "dataType": [ + "text[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "tags", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "wordCount" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "rating" + }, + { + "dataType": [ + "boolean" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "published" + }, + { + "dataType": [ + "date" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "publishedAt" + }, + { + "dataType": [ + "geoCoordinates" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "location" + }, + { + "dataType": [ + "object" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "meta", + "nestedProperties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "source", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "revision" + } + ] + }, + { + "dataType": [ + "Author" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "writtenBy" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + }, + { + "class": "Author", + "description": "objects with no vector at all", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "name", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "country", + "tokenization": "field" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "vectorConfig": null + } + ], + "rowCount": 7, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/Article", + "value": { + "fields": [ + "class", + "description", + "invertedIndexConfig", + "multiTenancyConfig", + "properties", + "replicationConfig", + "shardingConfig", + "vectorIndexConfig", + "vectorIndexType", + "vectorizer" + ], + "rows": [ + { + "class": "Article", + "description": "one unnamed vector, a cross-reference and the common property types", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "indexTimestamps": true, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "title", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "body", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "category", + "tokenization": "field" + }, + { + "dataType": [ + "text[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "tags", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "wordCount" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "rating" + }, + { + "dataType": [ + "boolean" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "published" + }, + { + "dataType": [ + "date" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "publishedAt" + }, + { + "dataType": [ + "geoCoordinates" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "location" + }, + { + "dataType": [ + "object" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "meta", + "nestedProperties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "source", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "revision" + } + ] + }, + { + "dataType": [ + "Author" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "writtenBy" + } + ], + "replicationConfig": { + "asyncEnabled": false, + "deletionStrategy": "TimeBasedResolution", + "factor": 1 + }, + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "enabled": false, + "rescoreLimit": 20 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/Article/shards", + "value": { + "fields": [ + "name", + "status", + "vectorQueueSize" + ], + "rows": [ + { + "name": "U20yv34cKfld", + "status": "READY", + "vectorQueueSize": 0 + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "HOT", + "name": "acme" + }, + { + "activityStatus": "HOT", + "name": "globex" + }, + { + "activityStatus": "COLD", + "name": "initech" + } + ], + "rowCount": 3, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants/acme", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "HOT", + "name": "acme" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants/initech", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "COLD", + "name": "initech" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/aliases", + "value": { + "fields": [ + "alias", + "class" + ], + "rows": [ + { + "alias": "Articles", + "class": "Article" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/aliases/Articles", + "value": { + "fields": [ + "alias", + "class" + ], + "rows": [ + { + "alias": "Articles", + "class": "Article" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 3 + }, + "gitHash": "7c1e318", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": null, + "status": "HEALTHY", + "version": "1.37.4" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes?output=verbose", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "stats", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 3 + }, + "gitHash": "7c1e318", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": [ + { + "asyncReplicationStatus": [], + "class": "TenantNotes", + "compressed": false, + "loaded": true, + "name": "globex", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "TenantNotes", + "compressed": false, + "loaded": true, + "name": "acme", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "TenantNotesAuto", + "compressed": false, + "loaded": true, + "name": "hooli", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "EdgeValues", + "compressed": false, + "loaded": true, + "name": "6sQaztKPiaRF", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Empty", + "compressed": false, + "loaded": true, + "name": "xoamC7a4yZNs", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Author", + "compressed": false, + "loaded": true, + "name": "GnuDbpXNjuzT", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Article", + "compressed": false, + "loaded": true, + "name": "U20yv34cKfld", + "numberOfReplicas": 1, + "objectCount": 500, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Product", + "compressed": false, + "loaded": true, + "name": "DPHQSkhVwydj", + "numberOfReplicas": 1, + "objectCount": 200, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + } + ], + "stats": { + "objectCount": 700, + "shardCount": 8 + }, + "status": "HEALTHY", + "version": "1.37.4" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes/Article?output=verbose", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "stats", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 3 + }, + "gitHash": "7c1e318", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": [ + { + "asyncReplicationStatus": [], + "class": "Article", + "compressed": false, + "loaded": true, + "name": "U20yv34cKfld", + "numberOfReplicas": 1, + "objectCount": 500, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + } + ], + "stats": { + "objectCount": 500, + "shardCount": 1 + }, + "status": "HEALTHY", + "version": "1.37.4" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/objects?class=Article&limit=3", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754772770, + "$lastUpdateTime": 1792754772770 + }, + { + "$id": "0092cefc-15f3-507f-a85c-2453b81d8c8c", + "title": "article 473 keyword search", + "body": "cosine quantize alias object collection tenant collection shard tenant engine alias hybrid", + "category": "delta", + "tags": [ + "collection", + "keyword", + "vector" + ], + "wordCount": 573, + "rating": 4.73, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.91, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9", + "href": "/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9" + } + ], + "$creationTime": 1792754772983, + "$lastUpdateTime": 1792754772983 + }, + { + "$id": "00df1951-be86-5fc4-9acb-b15841334bdf", + "title": "article 306 alias tenant", + "body": "search quantize hybrid engine collection keyword node collection object shard vector quantize", + "category": "beta", + "tags": [ + "filter", + "node", + "tenant" + ], + "wordCount": 406, + "rating": 3.06, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.743, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754772919, + "$lastUpdateTime": 1792754772919 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=00df1951-be86-5fc4-9acb-b15841334bdf to read the next 3." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Article&limit=2&include=vector", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$vector", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$vector": [ + 0.090872, + -0.268579, + 0.799546, + 0.963254, + 0.140379, + 0.019355, + -0.921561, + 0.336068, + -0.831569, + 0.932756, + -0.881524, + 0.622357, + -0.189283, + 0.105446, + 0.013549, + 0.315139 + ], + "$creationTime": 1792754772770, + "$lastUpdateTime": 1792754772770 + }, + { + "$id": "0092cefc-15f3-507f-a85c-2453b81d8c8c", + "title": "article 473 keyword search", + "body": "cosine quantize alias object collection tenant collection shard tenant engine alias hybrid", + "category": "delta", + "tags": [ + "collection", + "keyword", + "vector" + ], + "wordCount": 573, + "rating": 4.73, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.91, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9", + "href": "/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9" + } + ], + "$vector": [ + -0.348508, + 0.371256, + -0.002633, + 0.438731, + 0.926627, + 0.645241, + -0.489321, + 0.334734, + -0.536027, + 0.075017, + 0.195246, + -0.898757, + -0.389559, + -0.054653, + 0.906537, + -0.046758 + ], + "$creationTime": 1792754772983, + "$lastUpdateTime": 1792754772983 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + }, + "warnings": [ + { + "message": "More objects may follow: add &after=0092cefc-15f3-507f-a85c-2453b81d8c8c to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Product&limit=1&include=vector", + "value": { + "fields": [ + "$id", + "name", + "price", + "sku", + "$vector.image", + "$vector.text", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "017df454-5e7d-575f-a30b-81ab587ab05f", + "name": "product 087", + "price": 22.75, + "sku": "d73893f9-6387-5361-8190-44281f1fa3c9", + "$vector.image": [ + -0.004234, + 0.925485, + 0.143918, + -0.16418, + 0.567372, + 0.745523, + 0.214667, + -0.240875 + ], + "$vector.text": [ + -0.095434, + -0.084195, + 0.446122, + -0.414162, + -0.218631, + 0.110703, + -0.230998, + -0.356012, + 0.574156, + 0.699133, + -0.0009, + -0.111938, + -0.631577, + -0.391935, + -0.710019, + 0.150866 + ], + "$creationTime": 1792754773037, + "$lastUpdateTime": 1792754773037 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector.image": { + "kind": "dense", + "dtype": "float32", + "dimension": 8 + }, + "$vector.text": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + }, + "warnings": [ + { + "message": "More objects may follow: add &after=017df454-5e7d-575f-a30b-81ab587ab05f to read the next 1." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=188d0dcf-7792-5d1d-83d0-b36a206db92a to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Empty", + "value": { + "fields": [ + "$id" + ], + "rows": [], + "rowCount": 0, + "columnTypes": { + "$id": "uuid" + } + } + }, + { + "step": "query GET /v1/objects?class=EdgeValues&limit=8", + "value": { + "fields": [ + "$id", + "label", + "big", + "bigs", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": 9007199254740991, + "bigs": [ + 9007199254740991, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "0a225532-c59c-5c0e-a365-e9feabb88bb5", + "label": "-9223372036854775808", + "big": -9223372036854776000, + "bigs": [ + -9223372036854776000, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "3984d4bc-224d-5e18-914c-d8bc85b5d189", + "label": "9223372036854775807", + "big": 9223372036854776000, + "bigs": [ + 9223372036854776000, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "5dd5d8d9-71eb-5aea-94a7-ab89ee407a8f", + "label": "42", + "big": 42, + "bigs": [ + 42, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "85cfb82b-1e89-5b48-b745-e5b05e1566c0", + "label": "-42", + "big": -42, + "bigs": [ + -42, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "b3530c1a-63ca-5bc5-b14f-c55a1771ef5c", + "label": "9007199254740993", + "big": 9007199254740992, + "bigs": [ + 9007199254740992, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "b47ca1ec-54e9-5f83-81c2-0e83338906c3", + "label": "0", + "big": 0, + "bigs": [ + 0, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + }, + { + "$id": "ed773a9a-e98d-53df-baaf-d4cbd1915be3", + "label": "4611686018427387911", + "big": 4611686018427388000, + "bigs": [ + 4611686018427388000, + 1 + ], + "$creationTime": 1792754773090, + "$lastUpdateTime": 1792754773090 + } + ], + "rowCount": 8, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=ed773a9a-e98d-53df-baaf-d4cbd1915be3 to read the next 8." + } + ] + } + }, + { + "step": "query GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "body": "replica alias collection collection schema engine recall object quantize property schema filter", + "category": "epsilon", + "tags": [ + "alias", + "schema" + ], + "wordCount": 199, + "rating": 0.99, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.536, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28", + "href": "/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28" + } + ], + "$creationTime": 1792754772770, + "$lastUpdateTime": 1792754772770 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d?include=vector", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$vector", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "body": "replica alias collection collection schema engine recall object quantize property schema filter", + "category": "epsilon", + "tags": [ + "alias", + "schema" + ], + "wordCount": 199, + "rating": 0.99, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.536, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28", + "href": "/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28" + } + ], + "$vector": [ + -0.824794, + 0.547532, + 0.989252, + -0.893327, + -0.748434, + 0.069502, + 0.659972, + 0.593562, + -0.803924, + -0.346175, + 0.465874, + -0.068295, + -0.076308, + -0.910744, + 0.029835, + -0.034573 + ], + "$creationTime": 1792754772770, + "$lastUpdateTime": 1792754772770 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + } + } + }, + { + "step": "query GET /v1/objects/Article/00000000-0000-0000-0000-000000000000", + "error": { + "name": "QueryError", + "message": "No object has this id in this collection." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", + "value": { + "fields": [ + "$id", + "note", + "seq", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "0d476b6c-11c4-5d8b-9ef1-505058d6cd01", + "note": "acme note 11", + "seq": 11, + "$creationTime": 1792754773078, + "$lastUpdateTime": 1792754773078 + }, + { + "$id": "116eeb91-f7bb-5250-91cf-c252e2bc5f38", + "note": "acme note 07", + "seq": 7, + "$creationTime": 1792754773078, + "$lastUpdateTime": 1792754773078 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=116eeb91-f7bb-5250-91cf-c252e2bc5f38 to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2", + "error": { + "name": "RequestRefusal", + "message": "The collection \"TenantNotes\" is multi-tenant, so the request needs a tenant (?tenant=...). Nothing was read: GET /v1/schema/TenantNotes/tenants lists its tenants and which are HOT, without waking any." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2&tenant=initech", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotesAuto&limit=2&tenant=umbrella", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"umbrella\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query GET /v1/objects?class=Missing&limit=2", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&offset=0", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&offset=2", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "756f95fb-f154-5022-a811-ce9d4198c9dc", + "name": "author 10", + "country": "DE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + }, + { + "$id": "91f4c2c0-cd1d-51c1-abaf-b7de23cc0002", + "name": "author 08", + "country": "EE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&sort=name", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + }, + { + "$id": "98fe41ca-2d7c-54e2-b6df-71de7c0a8ae7", + "name": "author 01", + "country": "TR", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&after=00000000-0000-0000-0000-000000000000", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754772718, + "$lastUpdateTime": 1792754772718 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: set after=188d0dcf-7792-5d1d-83d0-b36a206db92a to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/schema/Missing", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-1-37/searches.json b/tests/fixtures/weaviate/weaviate-1-37/searches.json new file mode 100644 index 0000000000..903592a726 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-1-37/searches.json @@ -0,0 +1,1302 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-1-37", + "scenario": "searches", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.37.4", + "digest": "sha256:fcd0d4dfe70ed38feb2c12df58f991f3437bdf34ac022d978a48844c3ac86ea0", + "version": "1.37.4", + "date": "2026-10-23T23:54:52.901Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18281", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.37.4\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(bm25:{query:\\\"vector\\\"},limit:3){title wordCount _additional{id score}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"score\":\"1.7275589\"},\"title\":\"article 271 cosine schema\",\"wordCount\":371},{\"_additional\":{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"score\":\"1.2622087\"},\"title\":\"article 001 schema vector\",\"wordCount\":101},{\"_additional\":{\"id\":\"6a685778-9bb0-5b39-b66e-20e12491d845\",\"score\":\"1.0772038\"},\"title\":\"article 494 index graph\",\"wordCount\":594}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(where:{path:[\\\"category\\\"],operator:Equal,valueText:\\\"alpha\\\"},bm25:{query:\\\"vector\\\"},limit:2){title category _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\"},\"category\":\"alpha\",\"title\":\"article 260 vector recall\"},{\"_additional\":{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\"},\"category\":\"alpha\",\"title\":\"article 065 property collection\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(bm25:{query:\\\"vector\\\"},limit:2){title body category tags wordCount rating published publishedAt location{latitude longitude} meta{source revision} _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\"},\"body\":\"schema replica vector hybrid index index vector vector cosine tenant keyword hybrid\",\"category\":\"beta\",\"location\":{\"latitude\":59.708,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":2.71,\"tags\":[\"graph\",\"vector\"],\"title\":\"article 271 cosine schema\",\"wordCount\":371},{\"_additional\":{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\"},\"body\":\"tenant tenant index object object node schema shard collection object tenant alias\",\"category\":\"beta\",\"location\":{\"latitude\":59.438,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.01,\"tags\":[\"replica\",\"tenant\",\"vector\"],\"title\":\"article 001 schema vector\",\"wordCount\":101}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(nearVector:{vector:[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7]},limit:2){title _additional{id distance}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"distance\":0.23860067,\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\"},\"title\":\"article 044 quantize object\"},{\"_additional\":{\"distance\":0.38131392,\"id\":\"b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de\"},\"title\":\"article 428 alias keyword\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(nearObject:{id:\\\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\\\"},limit:2){title _additional{id distance}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"distance\":2.3841858e-7,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\"},\"title\":\"article 099 tenant index\"},{\"_additional\":{\"distance\":0.30005395,\"id\":\"091a6b21-3727-5500-8f12-17036b912723\"},\"title\":\"article 468 shard quantize\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(hybrid:{query:\\\"vector\\\",alpha:0},limit:2){title _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"6b7a5622-dfa8-5802-9c9a-b39275345406\"},\"title\":\"article 261 vector vector\"},{\"_additional\":{\"id\":\"0590a353-a65e-5f95-bafc-0b46dca27152\"},\"title\":\"article 223 vector search\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Product(nearVector:{vector:[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8],targetVectors:[\\\"image\\\"]},limit:1){name _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Product\":[{\"_additional\":{\"id\":\"9d8ce3ea-cf2e-5f73-a18c-f5016695d856\"},\"name\":\"product 019\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{TenantNotes(tenant:\\\"acme\\\",bm25:{query:\\\"note\\\"},limit:2){note seq _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"TenantNotes\":[{\"_additional\":{\"id\":\"5f733153-385b-599c-baea-79de4736abac\"},\"note\":\"acme note 02\",\"seq\":2},{\"_additional\":{\"id\":\"988ef2a7-fe5e-591e-b020-9a2239223014\"},\"note\":\"acme note 01\",\"seq\":1}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{EdgeValues(bm25:{query:\\\"9007199254740991\\\"},limit:10){label big _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"EdgeValues\":[{\"_additional\":{\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\"},\"big\":null,\"label\":\"9007199254740991\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Product(bm25:{query:\\\"product\\\"},limit:2){name _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Product\":[{\"_additional\":{\"id\":\"51fd5a34-9aa4-54be-afcf-ff814a32afb7\"},\"name\":\"product 001\"},{\"_additional\":{\"id\":\"92693fd4-cfd7-50d9-a1bc-7d9cf95d0326\"},\"name\":\"product 000\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(groupBy:[\\\"category\\\"],limit:100){meta{count} groupedBy{value path}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"epsilon\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"alpha\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"beta\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"delta\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"gamma\"},\"meta\":{\"count\":100}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{TenantNotes(tenant:\\\"acme\\\"){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"TenantNotes\":[{\"meta\":{\"count\":20}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(where:{path:[\\\"location\\\"],operator:WithinGeoRange,valueGeoRange:{geoCoordinates:{latitude:41,longitude:29},distance:{max:3000000}}}){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(where:{operator:And,operands:[{path:[\\\"published\\\"],operator:Equal,valueBoolean:true},{path:[\\\"location\\\"],operator:WithinGeoRange,valueGeoRange:{geoCoordinates:{latitude:41,longitude:29},distance:{max:3000000}}}]}){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(where:{path:[\\\"tags\\\"],operator:ContainsAny,valueText:[\\\"graph\\\",\\\"shard\\\"]},bm25:{query:\\\"vector\\\"},limit:50){title _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\"},\"title\":\"article 271 cosine schema\"},{\"_additional\":{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\"},\"title\":\"article 260 vector recall\"},{\"_additional\":{\"id\":\"78dfc127-4ef9-5643-9476-410f7efe648f\"},\"title\":\"article 405 cosine vector\"},{\"_additional\":{\"id\":\"97059d77-2db1-5521-855a-7fe8043015cc\"},\"title\":\"article 273 vector property\"},{\"_additional\":{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\"},\"title\":\"article 065 property collection\"},{\"_additional\":{\"id\":\"5950025b-9947-5837-bc3d-b08a911897a1\"},\"title\":\"article 262 vector node\"},{\"_additional\":{\"id\":\"5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f\"},\"title\":\"article 282 filter vector\"},{\"_additional\":{\"id\":\"568019d7-fa21-5d7b-98a7-126890f32e51\"},\"title\":\"article 341 node index\"},{\"_additional\":{\"id\":\"97bf6379-894b-5304-a05d-dc88e2efb96d\"},\"title\":\"article 334 quantize filter\"},{\"_additional\":{\"id\":\"adbe9c20-828e-5543-ab79-5fe3cd27be37\"},\"title\":\"article 224 vector shard\"},{\"_additional\":{\"id\":\"b181572c-0cdf-5f13-bde8-87fd7f1ce823\"},\"title\":\"article 328 filter property\"},{\"_additional\":{\"id\":\"e66f149e-51db-5bdb-afb2-d0fb6d47873d\"},\"title\":\"article 164 keyword node\"},{\"_additional\":{\"id\":\"9cd5f0ba-baff-56a1-a2a9-053ebc89309e\"},\"title\":\"article 403 search schema\"},{\"_additional\":{\"id\":\"d84aef74-a1a2-5534-964c-4f2f13f5b040\"},\"title\":\"article 463 keyword cosine\"},{\"_additional\":{\"id\":\"df43df7f-7493-5b64-b8d1-03be6a838dd8\"},\"title\":\"article 037 object node\"},{\"_additional\":{\"id\":\"109ab621-699c-521a-a71d-8761665a0fd2\"},\"title\":\"article 240 filter keyword\"},{\"_additional\":{\"id\":\"11910949-1a12-5d12-9c1c-015c150aa53c\"},\"title\":\"article 257 property graph\"},{\"_additional\":{\"id\":\"154cade8-3800-54f7-86bf-11940efda50c\"},\"title\":\"article 063 replica keyword\"},{\"_additional\":{\"id\":\"15a7167f-5614-5907-9c37-6ec7ac2faec3\"},\"title\":\"article 242 cosine shard\"},{\"_additional\":{\"id\":\"15b9b024-cbbe-506e-8cc6-b547ef29d366\"},\"title\":\"article 427 engine object\"},{\"_additional\":{\"id\":\"3bf3c3da-3b9d-586e-be52-058c017d408b\"},\"title\":\"article 034 cosine replica\"},{\"_additional\":{\"id\":\"675a3068-3c33-5279-937b-a1e55d8858e5\"},\"title\":\"article 043 shard tenant\"},{\"_additional\":{\"id\":\"71ad2be0-c4cb-5d55-ae14-45aaea14f4a9\"},\"title\":\"article 245 property shard\"},{\"_additional\":{\"id\":\"83a602fc-404e-56fb-9faf-f9405e6f50eb\"},\"title\":\"article 426 cosine recall\"},{\"_additional\":{\"id\":\"9eeef104-fb18-58a8-83ef-63db7229b331\"},\"title\":\"article 156 index hybrid\"},{\"_additional\":{\"id\":\"aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d\"},\"title\":\"article 385 hybrid cosine\"},{\"_additional\":{\"id\":\"b32a7a72-6389-5bb4-9947-49abf9b9cd91\"},\"title\":\"article 278 shard engine\"},{\"_additional\":{\"id\":\"c7a72ea7-5103-5ef4-b0b7-94052e81e528\"},\"title\":\"article 129 cosine tenant\"},{\"_additional\":{\"id\":\"efe60c07-cd04-5435-955b-e0f657176bae\"},\"title\":\"article 324 tenant alias\"},{\"_additional\":{\"id\":\"c9985312-f531-5ed2-a0f4-c4f070fcaffa\"},\"title\":\"article 492 search node\"},{\"_additional\":{\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\"},\"title\":\"article 042 index search\"},{\"_additional\":{\"id\":\"16f723f0-5c76-5f11-9cae-c8d970510c4a\"},\"title\":\"article 023 shard search\"},{\"_additional\":{\"id\":\"2716ffdb-f678-5f5e-a25b-7597d419a8f6\"},\"title\":\"article 040 shard graph\"},{\"_additional\":{\"id\":\"28a5ee00-944b-5fbe-bb71-775ef97aae95\"},\"title\":\"article 024 filter vector\"},{\"_additional\":{\"id\":\"30c49f98-46cc-51c8-9364-f0f544bd99f3\"},\"title\":\"article 161 object quantize\"},{\"_additional\":{\"id\":\"3968998f-7416-5e44-a02b-3d4f6a76d28d\"},\"title\":\"article 047 hybrid property\"},{\"_additional\":{\"id\":\"3b5e188a-dba4-551c-a4c2-2743202df1bb\"},\"title\":\"article 189 schema property\"},{\"_additional\":{\"id\":\"4d89b5b1-1efa-561a-add6-06731ea73da5\"},\"title\":\"article 197 keyword node\"},{\"_additional\":{\"id\":\"4e9f48c4-d174-52ff-becc-c2d72ea4fcde\"},\"title\":\"article 128 replica object\"},{\"_additional\":{\"id\":\"536bc3a8-9bff-5042-bfb2-f9d9cbecc250\"},\"title\":\"article 066 shard object\"},{\"_additional\":{\"id\":\"69b31860-8732-512f-aef1-79d35b48ed84\"},\"title\":\"article 244 cosine engine\"},{\"_additional\":{\"id\":\"754bf866-c2db-5a9b-929e-f69ba6555b80\"},\"title\":\"article 185 search filter\"},{\"_additional\":{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\"},\"title\":\"article 044 quantize object\"},{\"_additional\":{\"id\":\"a8212a0a-ba71-5ab9-9408-9158262a5711\"},\"title\":\"article 202 index tenant\"},{\"_additional\":{\"id\":\"a8eadb65-e8e1-5db4-b088-9bae6988ee67\"},\"title\":\"article 144 collection graph\"},{\"_additional\":{\"id\":\"a9d0efad-a959-552b-b65a-fda42cdbe2cd\"},\"title\":\"article 117 collection graph\"},{\"_additional\":{\"id\":\"b3c2ed60-4a50-5b93-97f3-d379133c266c\"},\"title\":\"article 237 replica object\"},{\"_additional\":{\"id\":\"b5391a2a-6084-55bd-ad80-c17ce6392439\"},\"title\":\"article 174 quantize tenant\"},{\"_additional\":{\"id\":\"d976ca88-a069-5460-a816-70339070c4ce\"},\"title\":\"article 029 filter property\"},{\"_additional\":{\"id\":\"fb3cde60-51fc-5a23-b3cd-5914001d0b7b\"},\"title\":\"article 264 recall quantize\"}]}}}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 3, \"returnProperties\": [\"title\", \"wordCount\"], \"returnMetadata\": [\"score\"]}", + "value": { + "fields": [ + "$id", + "title", + "wordCount", + "$score" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "wordCount": 371, + "$score": 1.7275589 + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "wordCount": 101, + "$score": 1.2622087 + }, + { + "$id": "6a685778-9bb0-5b39-b66e-20e12491d845", + "title": "article 494 index graph", + "wordCount": 594, + "$score": 1.0772038 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$score": "score, higher is better" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"category\"], \"operator\": \"Equal\", \"valueText\": \"alpha\"}, \"limit\": 2, \"returnProperties\": [\"title\", \"category\"]}", + "value": { + "fields": [ + "$id", + "title", + "category" + ], + "rows": [ + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall", + "category": "alpha" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection", + "category": "alpha" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "body": "schema replica vector hybrid index index vector vector cosine tenant keyword hybrid", + "category": "beta", + "tags": [ + "graph", + "vector" + ], + "wordCount": 371, + "rating": 2.71, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.708, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + } + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "body": "tenant tenant index object object node schema shard collection object tenant alias", + "category": "beta", + "tags": [ + "replica", + "tenant", + "vector" + ], + "wordCount": 101, + "rating": 0.01, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.438, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + } + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object", + "$distance": 0.23860067 + }, + { + "$id": "b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de", + "title": "article 428 alias keyword", + "$distance": 0.38131392 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 1, \"includeVector\": true}", + "error": { + "name": "RequestRefusal", + "message": "The body takes no key \"includeVector\": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, vector, targetVector, distance, certainty there and nothing else." + } + }, + { + "step": "query POST /v1/search/Article/near-object {\"id\": \"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\", \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "$distance": 2.3841858e-7 + }, + { + "$id": "091a6b21-3727-5500-8f12-17036b912723", + "title": "article 468 shard quantize", + "$distance": 0.30005395 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\", \"alpha\": 0, \"limit\": 2, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "6b7a5622-dfa8-5802-9c9a-b39275345406", + "title": "article 261 vector vector" + }, + { + "$id": "0590a353-a65e-5f95-bafc-0b46dca27152", + "title": "article 223 vector search" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/near-vector {\"vector\": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], \"targetVector\": \"image\", \"limit\": 1, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "9d8ce3ea-cf2e-5f73-a18c-f5016695d856", + "name": "product 019" + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/TenantNotes/bm25 {\"query\": \"note\", \"tenant\": \"acme\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "note", + "seq" + ], + "rows": [ + { + "$id": "5f733153-385b-599c-baea-79de4736abac", + "note": "acme note 02", + "seq": 2 + }, + { + "$id": "988ef2a7-fe5e-591e-b020-9a2239223014", + "note": "acme note 01", + "seq": 1 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/EdgeValues/bm25 {\"query\": \"9007199254740991\", \"returnProperties\": [\"label\", \"big\"]}", + "value": { + "fields": [ + "$id", + "label", + "big" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": null + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + }, + { + "message": "GraphQL answers null for an int outside the 32-bit range, so a null in big may be such a value; Weaviate 1.39.7 and later answer it over REST." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/bm25 {\"query\": \"product\", \"limit\": 2, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "51fd5a34-9aa4-54be-afcf-ff814a32afb7", + "name": "product 001" + }, + { + "$id": "92693fd4-cfd7-50d9-a1bc-7d9cf95d0326", + "name": "product 000" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Missing/bm25 {\"query\": \"x\"}", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query POST /v1/aggregate/Article {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"groupBy\": \"category\"}", + "value": { + "fields": [ + "category", + "count" + ], + "rows": [ + { + "category": "epsilon", + "count": 100 + }, + { + "category": "alpha", + "count": 100 + }, + { + "category": "beta", + "count": 100 + }, + { + "category": "delta", + "count": 100 + }, + { + "category": "gamma", + "count": 100 + } + ], + "rowCount": 5, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"acme\"}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 20 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"initech\"}", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query POST /v1/aggregate/Empty {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + }, + { + "message": "Weaviate 1.37.4 counts an aggregate filtered by WithinGeoRange as 0 even where objects match (measured on 1.37.4); read the objects with a search, or count on 1.38 or later." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"operator\": \"And\", \"operands\": [{\"path\": [\"published\"], \"operator\": \"Equal\", \"valueBoolean\": true}, {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}]}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + }, + { + "message": "Weaviate 1.37.4 counts an aggregate filtered by WithinGeoRange as 0 even where objects match (measured on 1.37.4); read the objects with a search, or count on 1.38 or later." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"tags\"], \"operator\": \"ContainsAny\", \"valueTextArray\": [\"graph\", \"shard\"]}, \"limit\": 50, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema" + }, + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall" + }, + { + "$id": "78dfc127-4ef9-5643-9476-410f7efe648f", + "title": "article 405 cosine vector" + }, + { + "$id": "97059d77-2db1-5521-855a-7fe8043015cc", + "title": "article 273 vector property" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection" + }, + { + "$id": "5950025b-9947-5837-bc3d-b08a911897a1", + "title": "article 262 vector node" + }, + { + "$id": "5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f", + "title": "article 282 filter vector" + }, + { + "$id": "568019d7-fa21-5d7b-98a7-126890f32e51", + "title": "article 341 node index" + }, + { + "$id": "97bf6379-894b-5304-a05d-dc88e2efb96d", + "title": "article 334 quantize filter" + }, + { + "$id": "adbe9c20-828e-5543-ab79-5fe3cd27be37", + "title": "article 224 vector shard" + }, + { + "$id": "b181572c-0cdf-5f13-bde8-87fd7f1ce823", + "title": "article 328 filter property" + }, + { + "$id": "e66f149e-51db-5bdb-afb2-d0fb6d47873d", + "title": "article 164 keyword node" + }, + { + "$id": "9cd5f0ba-baff-56a1-a2a9-053ebc89309e", + "title": "article 403 search schema" + }, + { + "$id": "d84aef74-a1a2-5534-964c-4f2f13f5b040", + "title": "article 463 keyword cosine" + }, + { + "$id": "df43df7f-7493-5b64-b8d1-03be6a838dd8", + "title": "article 037 object node" + }, + { + "$id": "109ab621-699c-521a-a71d-8761665a0fd2", + "title": "article 240 filter keyword" + }, + { + "$id": "11910949-1a12-5d12-9c1c-015c150aa53c", + "title": "article 257 property graph" + }, + { + "$id": "154cade8-3800-54f7-86bf-11940efda50c", + "title": "article 063 replica keyword" + }, + { + "$id": "15a7167f-5614-5907-9c37-6ec7ac2faec3", + "title": "article 242 cosine shard" + }, + { + "$id": "15b9b024-cbbe-506e-8cc6-b547ef29d366", + "title": "article 427 engine object" + }, + { + "$id": "3bf3c3da-3b9d-586e-be52-058c017d408b", + "title": "article 034 cosine replica" + }, + { + "$id": "675a3068-3c33-5279-937b-a1e55d8858e5", + "title": "article 043 shard tenant" + }, + { + "$id": "71ad2be0-c4cb-5d55-ae14-45aaea14f4a9", + "title": "article 245 property shard" + }, + { + "$id": "83a602fc-404e-56fb-9faf-f9405e6f50eb", + "title": "article 426 cosine recall" + }, + { + "$id": "9eeef104-fb18-58a8-83ef-63db7229b331", + "title": "article 156 index hybrid" + }, + { + "$id": "aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d", + "title": "article 385 hybrid cosine" + }, + { + "$id": "b32a7a72-6389-5bb4-9947-49abf9b9cd91", + "title": "article 278 shard engine" + }, + { + "$id": "c7a72ea7-5103-5ef4-b0b7-94052e81e528", + "title": "article 129 cosine tenant" + }, + { + "$id": "efe60c07-cd04-5435-955b-e0f657176bae", + "title": "article 324 tenant alias" + }, + { + "$id": "c9985312-f531-5ed2-a0f4-c4f070fcaffa", + "title": "article 492 search node" + }, + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search" + }, + { + "$id": "16f723f0-5c76-5f11-9cae-c8d970510c4a", + "title": "article 023 shard search" + }, + { + "$id": "2716ffdb-f678-5f5e-a25b-7597d419a8f6", + "title": "article 040 shard graph" + }, + { + "$id": "28a5ee00-944b-5fbe-bb71-775ef97aae95", + "title": "article 024 filter vector" + }, + { + "$id": "30c49f98-46cc-51c8-9364-f0f544bd99f3", + "title": "article 161 object quantize" + }, + { + "$id": "3968998f-7416-5e44-a02b-3d4f6a76d28d", + "title": "article 047 hybrid property" + }, + { + "$id": "3b5e188a-dba4-551c-a4c2-2743202df1bb", + "title": "article 189 schema property" + }, + { + "$id": "4d89b5b1-1efa-561a-add6-06731ea73da5", + "title": "article 197 keyword node" + }, + { + "$id": "4e9f48c4-d174-52ff-becc-c2d72ea4fcde", + "title": "article 128 replica object" + }, + { + "$id": "536bc3a8-9bff-5042-bfb2-f9d9cbecc250", + "title": "article 066 shard object" + }, + { + "$id": "69b31860-8732-512f-aef1-79d35b48ed84", + "title": "article 244 cosine engine" + }, + { + "$id": "754bf866-c2db-5a9b-929e-f69ba6555b80", + "title": "article 185 search filter" + }, + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object" + }, + { + "$id": "a8212a0a-ba71-5ab9-9408-9158262a5711", + "title": "article 202 index tenant" + }, + { + "$id": "a8eadb65-e8e1-5db4-b088-9bae6988ee67", + "title": "article 144 collection graph" + }, + { + "$id": "a9d0efad-a959-552b-b65a-fda42cdbe2cd", + "title": "article 117 collection graph" + }, + { + "$id": "b3c2ed60-4a50-5b93-97f3-d379133c266c", + "title": "article 237 replica object" + }, + { + "$id": "b5391a2a-6084-55bd-ad80-c17ce6392439", + "title": "article 174 quantize tenant" + }, + { + "$id": "d976ca88-a069-5460-a816-70339070c4ce", + "title": "article 029 filter property" + }, + { + "$id": "fb3cde60-51fc-5a23-b3cd-5914001d0b7b", + "title": "article 264 recall quantize" + } + ], + "rowCount": 50, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-1-37/surface.json b/tests/fixtures/weaviate/weaviate-1-37/surface.json new file mode 100644 index 0000000000..25d2edcca7 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-1-37/surface.json @@ -0,0 +1,1708 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-1-37", + "scenario": "surface", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.37.4", + "digest": "sha256:fcd0d4dfe70ed38feb2c12df58f991f3437bdf34ac022d978a48844c3ac86ea0", + "version": "1.37.4", + "date": "2026-10-23T23:54:52.750Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18281", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.37.4\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754772770,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754772770,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792754773037,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792754773037,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754772718,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754772718,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"U20yv34cKfld\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"DPHQSkhVwydj\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Product{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Product\":[{\"meta\":{\"count\":200}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"hooli\"},{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"xoamC7a4yZNs\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/.well-known/ready", + "body": null, + "answer": { + "status": 200, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.37.4\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Author{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Author\":[{\"meta\":{\"count\":12}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{EdgeValues{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"EdgeValues\":[{\"meta\":{\"count\":8}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Product{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Product\":[{\"meta\":{\"count\":200}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"replicationConfig\":{\"asyncEnabled\":false,\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1},\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\"}]}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "connectWarnings", + "value": [] + }, + { + "step": "listContainers", + "value": [] + }, + { + "step": "countObjects", + "value": { + "collection": { + "count": 7 + } + } + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "describeObjects", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "EdgeValues" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "big", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "bigs", + "type": "int[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(?, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotesAuto" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ] + } + }, + { + "step": "describeObjects limit 2", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ], + "truncated": { + "limit": 2, + "reason": "the bulk column read was bounded at 2 objects by its caller" + } + } + }, + { + "step": "describeObject Article", + "value": { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(16, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Product", + "value": { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(8, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(16, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Author", + "value": { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Empty", + "value": { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "readObjectSource Article", + "value": { + "path": [ + "Article" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Article\",\n \"description\": \"one unnamed vector, a cross-reference and the common property types\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"indexTimestamps\": true,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"title\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"body\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"category\",\n \"tokenization\": \"field\"\n },\n {\n \"dataType\": [\n \"text[]\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"tags\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"wordCount\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"rating\"\n },\n {\n \"dataType\": [\n \"boolean\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"published\"\n },\n {\n \"dataType\": [\n \"date\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"publishedAt\"\n },\n {\n \"dataType\": [\n \"geoCoordinates\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"location\"\n },\n {\n \"dataType\": [\n \"object\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"meta\",\n \"nestedProperties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"source\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"revision\"\n }\n ]\n },\n {\n \"dataType\": [\n \"Author\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"writtenBy\"\n }\n ],\n \"replicationConfig\": {\n \"asyncEnabled\": false,\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1\n },\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [\n \"Articles\"\n ],\n \"shards\": [\n {\n \"name\": \"U20yv34cKfld\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 500,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Product", + "value": { + "path": [ + "Product" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Product\",\n \"description\": \"two named vectors with different dimensions and distances\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"name\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"price\"\n },\n {\n \"dataType\": [\n \"uuid\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"sku\"\n }\n ],\n \"replicationConfig\": {\n \"asyncEnabled\": false,\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1\n },\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorConfig\": {\n \"image\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": {\n \"none\": {}\n }\n },\n \"text\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"distance\": \"dot\",\n \"pq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"rq\": {\n \"bits\": 8,\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"flat\",\n \"vectorizer\": {\n \"none\": {}\n }\n }\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"DPHQSkhVwydj\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 200,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotes\",\n \"description\": \"multi-tenant, a read does not activate a tenant\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"replicationConfig\": {\n \"asyncEnabled\": false,\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1\n },\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": false,\n \"aliases\": [],\n \"tenantCount\": 3,\n \"tenants\": [\n {\n \"name\": \"acme\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"globex\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"initech\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotesAuto", + "value": { + "path": [ + "TenantNotesAuto" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotesAuto\",\n \"description\": \"multi-tenant with autoTenantActivation on\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": true,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"replicationConfig\": {\n \"asyncEnabled\": false,\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1\n },\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": true,\n \"aliases\": [],\n \"tenantCount\": 2,\n \"tenants\": [\n {\n \"name\": \"hooli\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"umbrella\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Empty", + "value": { + "path": [ + "Empty" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Empty\",\n \"description\": \"no objects\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"label\",\n \"tokenization\": \"word\"\n }\n ],\n \"replicationConfig\": {\n \"asyncEnabled\": false,\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1\n },\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"xoamC7a4yZNs\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 0,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "getHealth", + "value": { + "databaseSize": "N/A", + "cacheHitRatio": "N/A", + "slowQueries": [], + "activeSessions": [] + } + }, + { + "step": "getOverview", + "value": { + "version": "1.37.4", + "uptime": "N/A", + "maxConnections": 0, + "databaseSize": "N/A", + "tableCount": 7, + "indexCount": 8 + } + }, + { + "step": "getTableStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "rowCount": 500, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "rowCount": 12, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "rowCount": 8, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "rowCount": 0, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "rowCount": 200, + "totalSize": "N/A", + "totalSizeBytes": 0 + } + ] + }, + { + "step": "getIndexStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.image", + "indexType": "hnsw, cosine", + "columns": [ + "$vector.image" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.text", + "indexType": "flat, dot", + "columns": [ + "$vector.text" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotes", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotesAuto", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + } + ] + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-1-38/searches.json b/tests/fixtures/weaviate/weaviate-1-38/searches.json new file mode 100644 index 0000000000..dff4fafa80 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-1-38/searches.json @@ -0,0 +1,1296 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-1-38", + "scenario": "searches", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.38.22", + "digest": "sha256:3b114db3992b8b4a62b623112b21a3d18c589e084dd9954b87b8d2ef08c6645c", + "version": "1.38.22", + "date": "2026-10-23T23:54:52.686Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18285", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.38.22\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(bm25:{query:\\\"vector\\\"},limit:3){title wordCount _additional{id score}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"score\":\"1.7275589\"},\"title\":\"article 271 cosine schema\",\"wordCount\":371},{\"_additional\":{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"score\":\"1.2622087\"},\"title\":\"article 001 schema vector\",\"wordCount\":101},{\"_additional\":{\"id\":\"6a685778-9bb0-5b39-b66e-20e12491d845\",\"score\":\"1.0772038\"},\"title\":\"article 494 index graph\",\"wordCount\":594}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(where:{path:[\\\"category\\\"],operator:Equal,valueText:\\\"alpha\\\"},bm25:{query:\\\"vector\\\"},limit:2){title category _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\"},\"category\":\"alpha\",\"title\":\"article 260 vector recall\"},{\"_additional\":{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\"},\"category\":\"alpha\",\"title\":\"article 065 property collection\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(bm25:{query:\\\"vector\\\"},limit:2){title body category tags wordCount rating published publishedAt location{latitude longitude} meta{source revision} _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\"},\"body\":\"schema replica vector hybrid index index vector vector cosine tenant keyword hybrid\",\"category\":\"beta\",\"location\":{\"latitude\":59.708,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":2.71,\"tags\":[\"graph\",\"vector\"],\"title\":\"article 271 cosine schema\",\"wordCount\":371},{\"_additional\":{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\"},\"body\":\"tenant tenant index object object node schema shard collection object tenant alias\",\"category\":\"beta\",\"location\":{\"latitude\":59.438,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.01,\"tags\":[\"replica\",\"tenant\",\"vector\"],\"title\":\"article 001 schema vector\",\"wordCount\":101}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(nearVector:{vector:[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7]},limit:2){title _additional{id distance}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"distance\":0.23860067,\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\"},\"title\":\"article 044 quantize object\"},{\"_additional\":{\"distance\":0.38131392,\"id\":\"b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de\"},\"title\":\"article 428 alias keyword\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(nearObject:{id:\\\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\\\"},limit:2){title _additional{id distance}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"distance\":2.3841858e-7,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\"},\"title\":\"article 099 tenant index\"},{\"_additional\":{\"distance\":0.30005395,\"id\":\"091a6b21-3727-5500-8f12-17036b912723\"},\"title\":\"article 468 shard quantize\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(hybrid:{query:\\\"vector\\\",alpha:0},limit:2){title _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"6b7a5622-dfa8-5802-9c9a-b39275345406\"},\"title\":\"article 261 vector vector\"},{\"_additional\":{\"id\":\"0590a353-a65e-5f95-bafc-0b46dca27152\"},\"title\":\"article 223 vector search\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Product(nearVector:{vector:[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8],targetVectors:[\\\"image\\\"]},limit:1){name _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Product\":[{\"_additional\":{\"id\":\"9d8ce3ea-cf2e-5f73-a18c-f5016695d856\"},\"name\":\"product 019\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{TenantNotes(tenant:\\\"acme\\\",bm25:{query:\\\"note\\\"},limit:2){note seq _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"TenantNotes\":[{\"_additional\":{\"id\":\"5f733153-385b-599c-baea-79de4736abac\"},\"note\":\"acme note 02\",\"seq\":2},{\"_additional\":{\"id\":\"988ef2a7-fe5e-591e-b020-9a2239223014\"},\"note\":\"acme note 01\",\"seq\":1}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{EdgeValues(bm25:{query:\\\"9007199254740991\\\"},limit:10){label big _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"EdgeValues\":[{\"_additional\":{\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\"},\"big\":null,\"label\":\"9007199254740991\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Product(bm25:{query:\\\"product\\\"},limit:2){name _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Product\":[{\"_additional\":{\"id\":\"51fd5a34-9aa4-54be-afcf-ff814a32afb7\"},\"name\":\"product 001\"},{\"_additional\":{\"id\":\"92693fd4-cfd7-50d9-a1bc-7d9cf95d0326\"},\"name\":\"product 000\"}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(groupBy:[\\\"category\\\"],limit:100){meta{count} groupedBy{value path}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"epsilon\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"alpha\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"beta\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"delta\"},\"meta\":{\"count\":100}},{\"groupedBy\":{\"path\":[\"category\"],\"value\":\"gamma\"},\"meta\":{\"count\":100}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{TenantNotes(tenant:\\\"acme\\\"){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"TenantNotes\":[{\"meta\":{\"count\":20}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(where:{path:[\\\"location\\\"],operator:WithinGeoRange,valueGeoRange:{geoCoordinates:{latitude:41,longitude:29},distance:{max:3000000}}}){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article(where:{operator:And,operands:[{path:[\\\"published\\\"],operator:Equal,valueBoolean:true},{path:[\\\"location\\\"],operator:WithinGeoRange,valueGeoRange:{geoCoordinates:{latitude:41,longitude:29},distance:{max:3000000}}}]}){meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":333}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Get{Article(where:{path:[\\\"tags\\\"],operator:ContainsAny,valueText:[\\\"graph\\\",\\\"shard\\\"]},bm25:{query:\\\"vector\\\"},limit:50){title _additional{id}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Get\":{\"Article\":[{\"_additional\":{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\"},\"title\":\"article 271 cosine schema\"},{\"_additional\":{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\"},\"title\":\"article 260 vector recall\"},{\"_additional\":{\"id\":\"78dfc127-4ef9-5643-9476-410f7efe648f\"},\"title\":\"article 405 cosine vector\"},{\"_additional\":{\"id\":\"97059d77-2db1-5521-855a-7fe8043015cc\"},\"title\":\"article 273 vector property\"},{\"_additional\":{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\"},\"title\":\"article 065 property collection\"},{\"_additional\":{\"id\":\"5950025b-9947-5837-bc3d-b08a911897a1\"},\"title\":\"article 262 vector node\"},{\"_additional\":{\"id\":\"5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f\"},\"title\":\"article 282 filter vector\"},{\"_additional\":{\"id\":\"568019d7-fa21-5d7b-98a7-126890f32e51\"},\"title\":\"article 341 node index\"},{\"_additional\":{\"id\":\"97bf6379-894b-5304-a05d-dc88e2efb96d\"},\"title\":\"article 334 quantize filter\"},{\"_additional\":{\"id\":\"adbe9c20-828e-5543-ab79-5fe3cd27be37\"},\"title\":\"article 224 vector shard\"},{\"_additional\":{\"id\":\"b181572c-0cdf-5f13-bde8-87fd7f1ce823\"},\"title\":\"article 328 filter property\"},{\"_additional\":{\"id\":\"e66f149e-51db-5bdb-afb2-d0fb6d47873d\"},\"title\":\"article 164 keyword node\"},{\"_additional\":{\"id\":\"9cd5f0ba-baff-56a1-a2a9-053ebc89309e\"},\"title\":\"article 403 search schema\"},{\"_additional\":{\"id\":\"d84aef74-a1a2-5534-964c-4f2f13f5b040\"},\"title\":\"article 463 keyword cosine\"},{\"_additional\":{\"id\":\"df43df7f-7493-5b64-b8d1-03be6a838dd8\"},\"title\":\"article 037 object node\"},{\"_additional\":{\"id\":\"109ab621-699c-521a-a71d-8761665a0fd2\"},\"title\":\"article 240 filter keyword\"},{\"_additional\":{\"id\":\"11910949-1a12-5d12-9c1c-015c150aa53c\"},\"title\":\"article 257 property graph\"},{\"_additional\":{\"id\":\"154cade8-3800-54f7-86bf-11940efda50c\"},\"title\":\"article 063 replica keyword\"},{\"_additional\":{\"id\":\"15a7167f-5614-5907-9c37-6ec7ac2faec3\"},\"title\":\"article 242 cosine shard\"},{\"_additional\":{\"id\":\"15b9b024-cbbe-506e-8cc6-b547ef29d366\"},\"title\":\"article 427 engine object\"},{\"_additional\":{\"id\":\"3bf3c3da-3b9d-586e-be52-058c017d408b\"},\"title\":\"article 034 cosine replica\"},{\"_additional\":{\"id\":\"675a3068-3c33-5279-937b-a1e55d8858e5\"},\"title\":\"article 043 shard tenant\"},{\"_additional\":{\"id\":\"71ad2be0-c4cb-5d55-ae14-45aaea14f4a9\"},\"title\":\"article 245 property shard\"},{\"_additional\":{\"id\":\"83a602fc-404e-56fb-9faf-f9405e6f50eb\"},\"title\":\"article 426 cosine recall\"},{\"_additional\":{\"id\":\"9eeef104-fb18-58a8-83ef-63db7229b331\"},\"title\":\"article 156 index hybrid\"},{\"_additional\":{\"id\":\"aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d\"},\"title\":\"article 385 hybrid cosine\"},{\"_additional\":{\"id\":\"b32a7a72-6389-5bb4-9947-49abf9b9cd91\"},\"title\":\"article 278 shard engine\"},{\"_additional\":{\"id\":\"c7a72ea7-5103-5ef4-b0b7-94052e81e528\"},\"title\":\"article 129 cosine tenant\"},{\"_additional\":{\"id\":\"efe60c07-cd04-5435-955b-e0f657176bae\"},\"title\":\"article 324 tenant alias\"},{\"_additional\":{\"id\":\"c9985312-f531-5ed2-a0f4-c4f070fcaffa\"},\"title\":\"article 492 search node\"},{\"_additional\":{\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\"},\"title\":\"article 042 index search\"},{\"_additional\":{\"id\":\"16f723f0-5c76-5f11-9cae-c8d970510c4a\"},\"title\":\"article 023 shard search\"},{\"_additional\":{\"id\":\"2716ffdb-f678-5f5e-a25b-7597d419a8f6\"},\"title\":\"article 040 shard graph\"},{\"_additional\":{\"id\":\"28a5ee00-944b-5fbe-bb71-775ef97aae95\"},\"title\":\"article 024 filter vector\"},{\"_additional\":{\"id\":\"30c49f98-46cc-51c8-9364-f0f544bd99f3\"},\"title\":\"article 161 object quantize\"},{\"_additional\":{\"id\":\"3968998f-7416-5e44-a02b-3d4f6a76d28d\"},\"title\":\"article 047 hybrid property\"},{\"_additional\":{\"id\":\"3b5e188a-dba4-551c-a4c2-2743202df1bb\"},\"title\":\"article 189 schema property\"},{\"_additional\":{\"id\":\"4d89b5b1-1efa-561a-add6-06731ea73da5\"},\"title\":\"article 197 keyword node\"},{\"_additional\":{\"id\":\"4e9f48c4-d174-52ff-becc-c2d72ea4fcde\"},\"title\":\"article 128 replica object\"},{\"_additional\":{\"id\":\"536bc3a8-9bff-5042-bfb2-f9d9cbecc250\"},\"title\":\"article 066 shard object\"},{\"_additional\":{\"id\":\"69b31860-8732-512f-aef1-79d35b48ed84\"},\"title\":\"article 244 cosine engine\"},{\"_additional\":{\"id\":\"754bf866-c2db-5a9b-929e-f69ba6555b80\"},\"title\":\"article 185 search filter\"},{\"_additional\":{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\"},\"title\":\"article 044 quantize object\"},{\"_additional\":{\"id\":\"a8212a0a-ba71-5ab9-9408-9158262a5711\"},\"title\":\"article 202 index tenant\"},{\"_additional\":{\"id\":\"a8eadb65-e8e1-5db4-b088-9bae6988ee67\"},\"title\":\"article 144 collection graph\"},{\"_additional\":{\"id\":\"a9d0efad-a959-552b-b65a-fda42cdbe2cd\"},\"title\":\"article 117 collection graph\"},{\"_additional\":{\"id\":\"b3c2ed60-4a50-5b93-97f3-d379133c266c\"},\"title\":\"article 237 replica object\"},{\"_additional\":{\"id\":\"b5391a2a-6084-55bd-ad80-c17ce6392439\"},\"title\":\"article 174 quantize tenant\"},{\"_additional\":{\"id\":\"d976ca88-a069-5460-a816-70339070c4ce\"},\"title\":\"article 029 filter property\"},{\"_additional\":{\"id\":\"fb3cde60-51fc-5a23-b3cd-5914001d0b7b\"},\"title\":\"article 264 recall quantize\"}]}}}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 3, \"returnProperties\": [\"title\", \"wordCount\"], \"returnMetadata\": [\"score\"]}", + "value": { + "fields": [ + "$id", + "title", + "wordCount", + "$score" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "wordCount": 371, + "$score": 1.7275589 + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "wordCount": 101, + "$score": 1.2622087 + }, + { + "$id": "6a685778-9bb0-5b39-b66e-20e12491d845", + "title": "article 494 index graph", + "wordCount": 594, + "$score": 1.0772038 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$score": "score, higher is better" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"category\"], \"operator\": \"Equal\", \"valueText\": \"alpha\"}, \"limit\": 2, \"returnProperties\": [\"title\", \"category\"]}", + "value": { + "fields": [ + "$id", + "title", + "category" + ], + "rows": [ + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall", + "category": "alpha" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection", + "category": "alpha" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "body": "schema replica vector hybrid index index vector vector cosine tenant keyword hybrid", + "category": "beta", + "tags": [ + "graph", + "vector" + ], + "wordCount": 371, + "rating": 2.71, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.708, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + } + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "body": "tenant tenant index object object node schema shard collection object tenant alias", + "category": "beta", + "tags": [ + "replica", + "tenant", + "vector" + ], + "wordCount": 101, + "rating": 0.01, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.438, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + } + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object", + "$distance": 0.23860067 + }, + { + "$id": "b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de", + "title": "article 428 alias keyword", + "$distance": 0.38131392 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 1, \"includeVector\": true}", + "error": { + "name": "RequestRefusal", + "message": "The body takes no key \"includeVector\": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, vector, targetVector, distance, certainty there and nothing else." + } + }, + { + "step": "query POST /v1/search/Article/near-object {\"id\": \"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\", \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "$distance": 2.3841858e-7 + }, + { + "$id": "091a6b21-3727-5500-8f12-17036b912723", + "title": "article 468 shard quantize", + "$distance": 0.30005395 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\", \"alpha\": 0, \"limit\": 2, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "6b7a5622-dfa8-5802-9c9a-b39275345406", + "title": "article 261 vector vector" + }, + { + "$id": "0590a353-a65e-5f95-bafc-0b46dca27152", + "title": "article 223 vector search" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/near-vector {\"vector\": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], \"targetVector\": \"image\", \"limit\": 1, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "9d8ce3ea-cf2e-5f73-a18c-f5016695d856", + "name": "product 019" + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/TenantNotes/bm25 {\"query\": \"note\", \"tenant\": \"acme\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "note", + "seq" + ], + "rows": [ + { + "$id": "5f733153-385b-599c-baea-79de4736abac", + "note": "acme note 02", + "seq": 2 + }, + { + "$id": "988ef2a7-fe5e-591e-b020-9a2239223014", + "note": "acme note 01", + "seq": 1 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/EdgeValues/bm25 {\"query\": \"9007199254740991\", \"returnProperties\": [\"label\", \"big\"]}", + "value": { + "fields": [ + "$id", + "label", + "big" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": null + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + }, + { + "message": "GraphQL answers null for an int outside the 32-bit range, so a null in big may be such a value; Weaviate 1.39.7 and later answer it over REST." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/bm25 {\"query\": \"product\", \"limit\": 2, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "51fd5a34-9aa4-54be-afcf-ff814a32afb7", + "name": "product 001" + }, + { + "$id": "92693fd4-cfd7-50d9-a1bc-7d9cf95d0326", + "name": "product 000" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Missing/bm25 {\"query\": \"x\"}", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query POST /v1/aggregate/Article {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"groupBy\": \"category\"}", + "value": { + "fields": [ + "category", + "count" + ], + "rows": [ + { + "category": "epsilon", + "count": 100 + }, + { + "category": "alpha", + "count": 100 + }, + { + "category": "beta", + "count": 100 + }, + { + "category": "delta", + "count": 100 + }, + { + "category": "gamma", + "count": 100 + } + ], + "rowCount": 5, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"acme\"}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 20 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"initech\"}", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query POST /v1/aggregate/Empty {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"operator\": \"And\", \"operands\": [{\"path\": [\"published\"], \"operator\": \"Equal\", \"valueBoolean\": true}, {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}]}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 333 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"tags\"], \"operator\": \"ContainsAny\", \"valueTextArray\": [\"graph\", \"shard\"]}, \"limit\": 50, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema" + }, + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall" + }, + { + "$id": "78dfc127-4ef9-5643-9476-410f7efe648f", + "title": "article 405 cosine vector" + }, + { + "$id": "97059d77-2db1-5521-855a-7fe8043015cc", + "title": "article 273 vector property" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection" + }, + { + "$id": "5950025b-9947-5837-bc3d-b08a911897a1", + "title": "article 262 vector node" + }, + { + "$id": "5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f", + "title": "article 282 filter vector" + }, + { + "$id": "568019d7-fa21-5d7b-98a7-126890f32e51", + "title": "article 341 node index" + }, + { + "$id": "97bf6379-894b-5304-a05d-dc88e2efb96d", + "title": "article 334 quantize filter" + }, + { + "$id": "adbe9c20-828e-5543-ab79-5fe3cd27be37", + "title": "article 224 vector shard" + }, + { + "$id": "b181572c-0cdf-5f13-bde8-87fd7f1ce823", + "title": "article 328 filter property" + }, + { + "$id": "e66f149e-51db-5bdb-afb2-d0fb6d47873d", + "title": "article 164 keyword node" + }, + { + "$id": "9cd5f0ba-baff-56a1-a2a9-053ebc89309e", + "title": "article 403 search schema" + }, + { + "$id": "d84aef74-a1a2-5534-964c-4f2f13f5b040", + "title": "article 463 keyword cosine" + }, + { + "$id": "df43df7f-7493-5b64-b8d1-03be6a838dd8", + "title": "article 037 object node" + }, + { + "$id": "109ab621-699c-521a-a71d-8761665a0fd2", + "title": "article 240 filter keyword" + }, + { + "$id": "11910949-1a12-5d12-9c1c-015c150aa53c", + "title": "article 257 property graph" + }, + { + "$id": "154cade8-3800-54f7-86bf-11940efda50c", + "title": "article 063 replica keyword" + }, + { + "$id": "15a7167f-5614-5907-9c37-6ec7ac2faec3", + "title": "article 242 cosine shard" + }, + { + "$id": "15b9b024-cbbe-506e-8cc6-b547ef29d366", + "title": "article 427 engine object" + }, + { + "$id": "3bf3c3da-3b9d-586e-be52-058c017d408b", + "title": "article 034 cosine replica" + }, + { + "$id": "675a3068-3c33-5279-937b-a1e55d8858e5", + "title": "article 043 shard tenant" + }, + { + "$id": "71ad2be0-c4cb-5d55-ae14-45aaea14f4a9", + "title": "article 245 property shard" + }, + { + "$id": "83a602fc-404e-56fb-9faf-f9405e6f50eb", + "title": "article 426 cosine recall" + }, + { + "$id": "9eeef104-fb18-58a8-83ef-63db7229b331", + "title": "article 156 index hybrid" + }, + { + "$id": "aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d", + "title": "article 385 hybrid cosine" + }, + { + "$id": "b32a7a72-6389-5bb4-9947-49abf9b9cd91", + "title": "article 278 shard engine" + }, + { + "$id": "c7a72ea7-5103-5ef4-b0b7-94052e81e528", + "title": "article 129 cosine tenant" + }, + { + "$id": "efe60c07-cd04-5435-955b-e0f657176bae", + "title": "article 324 tenant alias" + }, + { + "$id": "c9985312-f531-5ed2-a0f4-c4f070fcaffa", + "title": "article 492 search node" + }, + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search" + }, + { + "$id": "16f723f0-5c76-5f11-9cae-c8d970510c4a", + "title": "article 023 shard search" + }, + { + "$id": "2716ffdb-f678-5f5e-a25b-7597d419a8f6", + "title": "article 040 shard graph" + }, + { + "$id": "28a5ee00-944b-5fbe-bb71-775ef97aae95", + "title": "article 024 filter vector" + }, + { + "$id": "30c49f98-46cc-51c8-9364-f0f544bd99f3", + "title": "article 161 object quantize" + }, + { + "$id": "3968998f-7416-5e44-a02b-3d4f6a76d28d", + "title": "article 047 hybrid property" + }, + { + "$id": "3b5e188a-dba4-551c-a4c2-2743202df1bb", + "title": "article 189 schema property" + }, + { + "$id": "4d89b5b1-1efa-561a-add6-06731ea73da5", + "title": "article 197 keyword node" + }, + { + "$id": "4e9f48c4-d174-52ff-becc-c2d72ea4fcde", + "title": "article 128 replica object" + }, + { + "$id": "536bc3a8-9bff-5042-bfb2-f9d9cbecc250", + "title": "article 066 shard object" + }, + { + "$id": "69b31860-8732-512f-aef1-79d35b48ed84", + "title": "article 244 cosine engine" + }, + { + "$id": "754bf866-c2db-5a9b-929e-f69ba6555b80", + "title": "article 185 search filter" + }, + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object" + }, + { + "$id": "a8212a0a-ba71-5ab9-9408-9158262a5711", + "title": "article 202 index tenant" + }, + { + "$id": "a8eadb65-e8e1-5db4-b088-9bae6988ee67", + "title": "article 144 collection graph" + }, + { + "$id": "a9d0efad-a959-552b-b65a-fda42cdbe2cd", + "title": "article 117 collection graph" + }, + { + "$id": "b3c2ed60-4a50-5b93-97f3-d379133c266c", + "title": "article 237 replica object" + }, + { + "$id": "b5391a2a-6084-55bd-ad80-c17ce6392439", + "title": "article 174 quantize tenant" + }, + { + "$id": "d976ca88-a069-5460-a816-70339070c4ce", + "title": "article 029 filter property" + }, + { + "$id": "fb3cde60-51fc-5a23-b3cd-5914001d0b7b", + "title": "article 264 recall quantize" + } + ], + "rowCount": 50, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via GraphQL." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-1-38/surface.json b/tests/fixtures/weaviate/weaviate-1-38/surface.json new file mode 100644 index 0000000000..c8b6450bee --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-1-38/surface.json @@ -0,0 +1,1708 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-1-38", + "scenario": "surface", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.38.22", + "digest": "sha256:3b114db3992b8b4a62b623112b21a3d18c589e084dd9954b87b8d2ef08c6645c", + "version": "1.38.22", + "date": "2026-10-23T23:54:52.589Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18285", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.38.22\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792766837163,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792766837163,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792766837433,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792766837433,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792766837129,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792766837129,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"NPaR1iZmmhIF\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"qR7mhpPkGXaJ\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Product{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Product\":[{\"meta\":{\"count\":200}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"},{\"activityStatus\":\"HOT\",\"name\":\"hooli\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"f1N5F7yqulwi\",\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/.well-known/ready", + "body": null, + "answer": { + "status": 200, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"modules\":{},\"version\":\"1.38.22\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Article{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Article\":[{\"meta\":{\"count\":500}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Author{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Author\":[{\"meta\":{\"count\":12}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{EdgeValues{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"EdgeValues\":[{\"meta\":{\"count\":8}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Empty{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Empty\":[{\"meta\":{\"count\":0}}]}}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/graphql", + "body": "{\"query\":\"{Aggregate{Product{meta{count}}}}\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"data\":{\"Aggregate\":{\"Product\":[{\"meta\":{\"count\":200}}]}}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"enabled\":false,\"rescoreLimit\":20},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "connectWarnings", + "value": [] + }, + { + "step": "listContainers", + "value": [] + }, + { + "step": "countObjects", + "value": { + "collection": { + "count": 7 + } + } + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "describeObjects", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "EdgeValues" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "big", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "bigs", + "type": "int[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(?, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotesAuto" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ] + } + }, + { + "step": "describeObjects limit 2", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ], + "truncated": { + "limit": 2, + "reason": "the bulk column read was bounded at 2 objects by its caller" + } + } + }, + { + "step": "describeObject Article", + "value": { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(16, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Product", + "value": { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(8, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(16, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Author", + "value": { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Empty", + "value": { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "readObjectSource Article", + "value": { + "path": [ + "Article" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Article\",\n \"description\": \"one unnamed vector, a cross-reference and the common property types\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"indexTimestamps\": true,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"title\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"body\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"category\",\n \"tokenization\": \"field\"\n },\n {\n \"dataType\": [\n \"text[]\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"tags\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"wordCount\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"rating\"\n },\n {\n \"dataType\": [\n \"boolean\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"published\"\n },\n {\n \"dataType\": [\n \"date\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"publishedAt\"\n },\n {\n \"dataType\": [\n \"geoCoordinates\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"location\"\n },\n {\n \"dataType\": [\n \"object\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"meta\",\n \"nestedProperties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"source\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"revision\"\n }\n ]\n },\n {\n \"dataType\": [\n \"Author\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"writtenBy\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [\n \"Articles\"\n ],\n \"shards\": [\n {\n \"name\": \"NPaR1iZmmhIF\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 500,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Product", + "value": { + "path": [ + "Product" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Product\",\n \"description\": \"two named vectors with different dimensions and distances\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"name\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"price\"\n },\n {\n \"dataType\": [\n \"uuid\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"sku\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorConfig\": {\n \"image\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": {\n \"none\": {}\n }\n },\n \"text\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"distance\": \"dot\",\n \"pq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"rq\": {\n \"bits\": 8,\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"flat\",\n \"vectorizer\": {\n \"none\": {}\n }\n }\n },\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"qR7mhpPkGXaJ\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 200,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotes\",\n \"description\": \"multi-tenant, a read does not activate a tenant\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": false,\n \"aliases\": [],\n \"tenantCount\": 3,\n \"tenants\": [\n {\n \"name\": \"acme\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"globex\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"initech\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotesAuto", + "value": { + "path": [ + "TenantNotesAuto" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotesAuto\",\n \"description\": \"multi-tenant with autoTenantActivation on\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": true,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": true,\n \"aliases\": [],\n \"tenantCount\": 2,\n \"tenants\": [\n {\n \"name\": \"hooli\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"umbrella\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Empty", + "value": { + "path": [ + "Empty" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Empty\",\n \"description\": \"no objects\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"label\",\n \"tokenization\": \"word\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"enabled\": false,\n \"rescoreLimit\": 20\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"f1N5F7yqulwi\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 0,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "getHealth", + "value": { + "databaseSize": "N/A", + "cacheHitRatio": "N/A", + "slowQueries": [], + "activeSessions": [] + } + }, + { + "step": "getOverview", + "value": { + "version": "1.38.22", + "uptime": "N/A", + "maxConnections": 0, + "databaseSize": "N/A", + "tableCount": 7, + "indexCount": 8 + } + }, + { + "step": "getTableStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "rowCount": 500, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "rowCount": 12, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "rowCount": 8, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "rowCount": 0, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "rowCount": 200, + "totalSize": "N/A", + "totalSizeBytes": 0 + } + ] + }, + { + "step": "getIndexStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.image", + "indexType": "hnsw, cosine", + "columns": [ + "$vector.image" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.text", + "indexType": "flat, dot", + "columns": [ + "$vector.text" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotes", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotesAuto", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + } + ] + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-auth/no-key.json b/tests/fixtures/weaviate/weaviate-auth/no-key.json new file mode 100644 index 0000000000..7d5150cc3f --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-auth/no-key.json @@ -0,0 +1,44 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-auth", + "scenario": "no-key", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.073Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18283", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 401, + "contentType": "text/plain; charset=utf-8", + "retryAfter": null, + "text": "{\"code\":401,\"message\": \"anonymous access not enabled. Please authenticate through one of the available methods: [API-keys]\" }" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "error": { + "name": "AuthenticationError", + "message": "Weaviate refused the API key or token. (Weaviate: anonymous access not enabled. Please authenticate through one of the available methods: [API-keys])" + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-auth/reader.json b/tests/fixtures/weaviate/weaviate-auth/reader.json new file mode 100644 index 0000000000..3bfc8b0a74 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-auth/reader.json @@ -0,0 +1,600 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-auth", + "scenario": "reader", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.062Z", + "runtime": "bun 1.4.2", + "credential": "reader" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18283", + "tls": null, + "maxSockets": 4, + "headers": { + "authorization": "Bearer " + } + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"pYR6GlZ0Ilj7\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Author", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":12,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/EdgeValues", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":8,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Product", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":200,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=2", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754765097,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754765097,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754765330,\"id\":\"0092cefc-15f3-507f-a85c-2453b81d8c8c\",\"lastUpdateTimeUnix\":1792754765330,\"properties\":{\"body\":\"cosine quantize alias object collection tenant collection shard tenant engine alias hybrid\",\"category\":\"delta\",\"location\":{\"latitude\":59.91,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":4.73,\"tags\":[\"collection\",\"keyword\",\"vector\"],\"title\":\"article 473 keyword search\",\"wordCount\":573,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\",\"href\":\"/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\"}]},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"limit\":2}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"properties\":{\"body\":\"schema replica vector hybrid index index vector vector cosine tenant keyword hybrid\",\"category\":\"beta\",\"location\":{\"latitude\":59.708,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":2.71,\"tags\":[\"graph\",\"vector\"],\"title\":\"article 271 cosine schema\",\"wordCount\":371}},{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"properties\":{\"body\":\"tenant tenant index object object node schema shard collection object tenant alias\",\"category\":\"beta\",\"location\":{\"latitude\":59.438,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.01,\"tags\":[\"replica\",\"tenant\",\"vector\"],\"title\":\"article 001 schema vector\",\"wordCount\":101}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "connectWarnings", + "value": [] + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "readObjectSource Article", + "value": { + "path": [ + "Article" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Article\",\n \"description\": \"one unnamed vector, a cross-reference and the common property types\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"indexTimestamps\": true,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"title\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"body\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"category\",\n \"tokenization\": \"field\"\n },\n {\n \"dataType\": [\n \"text[]\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"tags\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"wordCount\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"rating\"\n },\n {\n \"dataType\": [\n \"boolean\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"published\"\n },\n {\n \"dataType\": [\n \"date\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"publishedAt\"\n },\n {\n \"dataType\": [\n \"geoCoordinates\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"location\"\n },\n {\n \"dataType\": [\n \"object\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"meta\",\n \"nestedProperties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"source\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"revision\"\n }\n ]\n },\n {\n \"dataType\": [\n \"Author\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"writtenBy\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [\n \"Articles\"\n ],\n \"shards\": [\n {\n \"name\": \"pYR6GlZ0Ilj7\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 500,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "getOverview", + "value": { + "version": "1.40.2", + "uptime": "N/A", + "maxConnections": 0, + "databaseSize": "N/A", + "tableCount": 7, + "tableCountSampledFrom": "the collections visible to this credential", + "indexCount": 8 + } + }, + { + "step": "getTableStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "rowCount": 500, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "rowCount": 12, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "rowCount": 8, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "rowCount": 0, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "rowCount": 200, + "totalSize": "N/A", + "totalSizeBytes": 0 + } + ] + }, + { + "step": "query GET /v1/objects?class=Article&limit=2", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754765097, + "$lastUpdateTime": 1792754765097 + }, + { + "$id": "0092cefc-15f3-507f-a85c-2453b81d8c8c", + "title": "article 473 keyword search", + "body": "cosine quantize alias object collection tenant collection shard tenant engine alias hybrid", + "category": "delta", + "tags": [ + "collection", + "keyword", + "vector" + ], + "wordCount": 573, + "rating": 4.73, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.91, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9", + "href": "/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9" + } + ], + "$creationTime": 1792754765330, + "$lastUpdateTime": 1792754765330 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=0092cefc-15f3-507f-a85c-2453b81d8c8c to read the next 2." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "body": "schema replica vector hybrid index index vector vector cosine tenant keyword hybrid", + "category": "beta", + "tags": [ + "graph", + "vector" + ], + "wordCount": 371, + "rating": 2.71, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.708, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + } + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "body": "tenant tenant index object object node schema shard collection object tenant alias", + "category": "beta", + "tags": [ + "replica", + "tenant", + "vector" + ], + "wordCount": 101, + "rating": 0.01, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.438, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + } + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-auth/root.json b/tests/fixtures/weaviate/weaviate-auth/root.json new file mode 100644 index 0000000000..1eb800fa85 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-auth/root.json @@ -0,0 +1,109 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-auth", + "scenario": "root", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.068Z", + "runtime": "bun 1.4.2", + "credential": "root" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18283", + "tls": null, + "maxSockets": 4, + "headers": { + "authorization": "Bearer " + } + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-auth/wrong-key.json b/tests/fixtures/weaviate/weaviate-auth/wrong-key.json new file mode 100644 index 0000000000..e5301c0e06 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-auth/wrong-key.json @@ -0,0 +1,46 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-auth", + "scenario": "wrong-key", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.071Z", + "runtime": "bun 1.4.2", + "credential": "wrong" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18283", + "tls": null, + "maxSockets": 4, + "headers": { + "authorization": "Bearer " + } + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 401, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"code\":401,\"message\":\"unauthorized: invalid api key\"}" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "error": { + "name": "AuthenticationError", + "message": "Weaviate refused the API key or token. (Weaviate: unauthorized: invalid api key)" + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-nographql/searches.json b/tests/fixtures/weaviate/weaviate-nographql/searches.json new file mode 100644 index 0000000000..5f3c2ecaf5 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-nographql/searches.json @@ -0,0 +1,1293 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-nographql", + "scenario": "searches", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.026Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18282", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"limit\":3,\"returnProperties\":[\"title\",\"wordCount\"],\"returnMetadata\":[\"score\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"metadata\":{\"score\":1.7275589},\"properties\":{\"title\":\"article 271 cosine schema\",\"wordCount\":371}},{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"metadata\":{\"score\":1.2622087},\"properties\":{\"title\":\"article 001 schema vector\",\"wordCount\":101}},{\"id\":\"6a685778-9bb0-5b39-b66e-20e12491d845\",\"metadata\":{\"score\":1.0772038},\"properties\":{\"title\":\"article 494 index graph\",\"wordCount\":594}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"where\":{\"path\":[\"category\"],\"operator\":\"Equal\",\"valueText\":\"alpha\"},\"limit\":2,\"returnProperties\":[\"title\",\"category\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\",\"properties\":{\"category\":\"alpha\",\"title\":\"article 260 vector recall\"}},{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\",\"properties\":{\"category\":\"alpha\",\"title\":\"article 065 property collection\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"limit\":2}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"properties\":{\"body\":\"schema replica vector hybrid index index vector vector cosine tenant keyword hybrid\",\"category\":\"beta\",\"location\":{\"latitude\":59.708,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":2.71,\"tags\":[\"graph\",\"vector\"],\"title\":\"article 271 cosine schema\",\"wordCount\":371}},{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"properties\":{\"body\":\"tenant tenant index object object node schema shard collection object tenant alias\",\"category\":\"beta\",\"location\":{\"latitude\":59.438,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.01,\"tags\":[\"replica\",\"tenant\",\"vector\"],\"title\":\"article 001 schema vector\",\"wordCount\":101}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/near-vector", + "body": "{\"vector\":[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7],\"limit\":2,\"returnProperties\":[\"title\"],\"returnMetadata\":[\"distance\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\",\"metadata\":{\"distance\":0.23860073},\"properties\":{\"title\":\"article 044 quantize object\"}},{\"id\":\"b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de\",\"metadata\":{\"distance\":0.38131392},\"properties\":{\"title\":\"article 428 alias keyword\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/near-object", + "body": "{\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"limit\":2,\"returnProperties\":[\"title\"],\"returnMetadata\":[\"distance\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"metadata\":{\"distance\":1.1920929e-7},\"properties\":{\"title\":\"article 099 tenant index\"}},{\"id\":\"091a6b21-3727-5500-8f12-17036b912723\",\"metadata\":{\"distance\":0.3000539},\"properties\":{\"title\":\"article 468 shard quantize\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/hybrid", + "body": "{\"query\":\"vector\",\"alpha\":0,\"limit\":2,\"returnProperties\":[\"title\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"6b7a5622-dfa8-5802-9c9a-b39275345406\",\"properties\":{\"title\":\"article 261 vector vector\"}},{\"id\":\"0590a353-a65e-5f95-bafc-0b46dca27152\",\"properties\":{\"title\":\"article 223 vector search\"}}],\"tookMs\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Product/near-vector", + "body": "{\"vector\":[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8],\"targetVector\":\"image\",\"limit\":1,\"returnProperties\":[\"name\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"9d8ce3ea-cf2e-5f73-a18c-f5016695d856\",\"properties\":{\"name\":\"product 019\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/TenantNotes/bm25", + "body": "{\"query\":\"note\",\"tenant\":\"acme\",\"limit\":2}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5f733153-385b-599c-baea-79de4736abac\",\"properties\":{\"note\":\"acme note 02\",\"seq\":2}},{\"id\":\"988ef2a7-fe5e-591e-b020-9a2239223014\",\"properties\":{\"note\":\"acme note 01\",\"seq\":1}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/EdgeValues/bm25", + "body": "{\"query\":\"9007199254740991\",\"returnProperties\":[\"label\",\"big\"],\"limit\":10}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\",\"properties\":{\"big\":9007199254740991,\"label\":\"9007199254740991\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Product/bm25", + "body": "{\"query\":\"product\",\"limit\":2,\"returnProperties\":[\"name\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"51fd5a34-9aa4-54be-afcf-ff814a32afb7\",\"properties\":{\"name\":\"product 001\"}},{\"id\":\"92693fd4-cfd7-50d9-a1bc-7d9cf95d0326\",\"properties\":{\"name\":\"product 000\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"groupBy\":\"category\",\"limit\":100}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"groups\":[{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"epsilon\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"alpha\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"beta\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"delta\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"gamma\"}}],\"tookMs\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/TenantNotes", + "body": "{\"tenant\":\"acme\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":20,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"where\":{\"path\":[\"location\"],\"operator\":\"WithinGeoRange\",\"valueGeoRange\":{\"geoCoordinates\":{\"latitude\":41,\"longitude\":29},\"distance\":{\"max\":3000000}}}}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"where\":{\"operator\":\"And\",\"operands\":[{\"path\":[\"published\"],\"operator\":\"Equal\",\"valueBoolean\":true},{\"path\":[\"location\"],\"operator\":\"WithinGeoRange\",\"valueGeoRange\":{\"geoCoordinates\":{\"latitude\":41,\"longitude\":29},\"distance\":{\"max\":3000000}}}]}}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":333,\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"where\":{\"path\":[\"tags\"],\"operator\":\"ContainsAny\",\"valueTextArray\":[\"graph\",\"shard\"]},\"limit\":50,\"returnProperties\":[\"title\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"properties\":{\"title\":\"article 271 cosine schema\"}},{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\",\"properties\":{\"title\":\"article 260 vector recall\"}},{\"id\":\"78dfc127-4ef9-5643-9476-410f7efe648f\",\"properties\":{\"title\":\"article 405 cosine vector\"}},{\"id\":\"97059d77-2db1-5521-855a-7fe8043015cc\",\"properties\":{\"title\":\"article 273 vector property\"}},{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\",\"properties\":{\"title\":\"article 065 property collection\"}},{\"id\":\"5950025b-9947-5837-bc3d-b08a911897a1\",\"properties\":{\"title\":\"article 262 vector node\"}},{\"id\":\"5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f\",\"properties\":{\"title\":\"article 282 filter vector\"}},{\"id\":\"568019d7-fa21-5d7b-98a7-126890f32e51\",\"properties\":{\"title\":\"article 341 node index\"}},{\"id\":\"97bf6379-894b-5304-a05d-dc88e2efb96d\",\"properties\":{\"title\":\"article 334 quantize filter\"}},{\"id\":\"adbe9c20-828e-5543-ab79-5fe3cd27be37\",\"properties\":{\"title\":\"article 224 vector shard\"}},{\"id\":\"b181572c-0cdf-5f13-bde8-87fd7f1ce823\",\"properties\":{\"title\":\"article 328 filter property\"}},{\"id\":\"e66f149e-51db-5bdb-afb2-d0fb6d47873d\",\"properties\":{\"title\":\"article 164 keyword node\"}},{\"id\":\"9cd5f0ba-baff-56a1-a2a9-053ebc89309e\",\"properties\":{\"title\":\"article 403 search schema\"}},{\"id\":\"d84aef74-a1a2-5534-964c-4f2f13f5b040\",\"properties\":{\"title\":\"article 463 keyword cosine\"}},{\"id\":\"df43df7f-7493-5b64-b8d1-03be6a838dd8\",\"properties\":{\"title\":\"article 037 object node\"}},{\"id\":\"109ab621-699c-521a-a71d-8761665a0fd2\",\"properties\":{\"title\":\"article 240 filter keyword\"}},{\"id\":\"11910949-1a12-5d12-9c1c-015c150aa53c\",\"properties\":{\"title\":\"article 257 property graph\"}},{\"id\":\"154cade8-3800-54f7-86bf-11940efda50c\",\"properties\":{\"title\":\"article 063 replica keyword\"}},{\"id\":\"15a7167f-5614-5907-9c37-6ec7ac2faec3\",\"properties\":{\"title\":\"article 242 cosine shard\"}},{\"id\":\"15b9b024-cbbe-506e-8cc6-b547ef29d366\",\"properties\":{\"title\":\"article 427 engine object\"}},{\"id\":\"3bf3c3da-3b9d-586e-be52-058c017d408b\",\"properties\":{\"title\":\"article 034 cosine replica\"}},{\"id\":\"675a3068-3c33-5279-937b-a1e55d8858e5\",\"properties\":{\"title\":\"article 043 shard tenant\"}},{\"id\":\"71ad2be0-c4cb-5d55-ae14-45aaea14f4a9\",\"properties\":{\"title\":\"article 245 property shard\"}},{\"id\":\"83a602fc-404e-56fb-9faf-f9405e6f50eb\",\"properties\":{\"title\":\"article 426 cosine recall\"}},{\"id\":\"9eeef104-fb18-58a8-83ef-63db7229b331\",\"properties\":{\"title\":\"article 156 index hybrid\"}},{\"id\":\"aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d\",\"properties\":{\"title\":\"article 385 hybrid cosine\"}},{\"id\":\"b32a7a72-6389-5bb4-9947-49abf9b9cd91\",\"properties\":{\"title\":\"article 278 shard engine\"}},{\"id\":\"c7a72ea7-5103-5ef4-b0b7-94052e81e528\",\"properties\":{\"title\":\"article 129 cosine tenant\"}},{\"id\":\"efe60c07-cd04-5435-955b-e0f657176bae\",\"properties\":{\"title\":\"article 324 tenant alias\"}},{\"id\":\"c9985312-f531-5ed2-a0f4-c4f070fcaffa\",\"properties\":{\"title\":\"article 492 search node\"}},{\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"properties\":{\"title\":\"article 042 index search\"}},{\"id\":\"16f723f0-5c76-5f11-9cae-c8d970510c4a\",\"properties\":{\"title\":\"article 023 shard search\"}},{\"id\":\"2716ffdb-f678-5f5e-a25b-7597d419a8f6\",\"properties\":{\"title\":\"article 040 shard graph\"}},{\"id\":\"28a5ee00-944b-5fbe-bb71-775ef97aae95\",\"properties\":{\"title\":\"article 024 filter vector\"}},{\"id\":\"30c49f98-46cc-51c8-9364-f0f544bd99f3\",\"properties\":{\"title\":\"article 161 object quantize\"}},{\"id\":\"3968998f-7416-5e44-a02b-3d4f6a76d28d\",\"properties\":{\"title\":\"article 047 hybrid property\"}},{\"id\":\"3b5e188a-dba4-551c-a4c2-2743202df1bb\",\"properties\":{\"title\":\"article 189 schema property\"}},{\"id\":\"4d89b5b1-1efa-561a-add6-06731ea73da5\",\"properties\":{\"title\":\"article 197 keyword node\"}},{\"id\":\"4e9f48c4-d174-52ff-becc-c2d72ea4fcde\",\"properties\":{\"title\":\"article 128 replica object\"}},{\"id\":\"536bc3a8-9bff-5042-bfb2-f9d9cbecc250\",\"properties\":{\"title\":\"article 066 shard object\"}},{\"id\":\"69b31860-8732-512f-aef1-79d35b48ed84\",\"properties\":{\"title\":\"article 244 cosine engine\"}},{\"id\":\"754bf866-c2db-5a9b-929e-f69ba6555b80\",\"properties\":{\"title\":\"article 185 search filter\"}},{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\",\"properties\":{\"title\":\"article 044 quantize object\"}},{\"id\":\"a8212a0a-ba71-5ab9-9408-9158262a5711\",\"properties\":{\"title\":\"article 202 index tenant\"}},{\"id\":\"a8eadb65-e8e1-5db4-b088-9bae6988ee67\",\"properties\":{\"title\":\"article 144 collection graph\"}},{\"id\":\"a9d0efad-a959-552b-b65a-fda42cdbe2cd\",\"properties\":{\"title\":\"article 117 collection graph\"}},{\"id\":\"b3c2ed60-4a50-5b93-97f3-d379133c266c\",\"properties\":{\"title\":\"article 237 replica object\"}},{\"id\":\"b5391a2a-6084-55bd-ad80-c17ce6392439\",\"properties\":{\"title\":\"article 174 quantize tenant\"}},{\"id\":\"d976ca88-a069-5460-a816-70339070c4ce\",\"properties\":{\"title\":\"article 029 filter property\"}},{\"id\":\"fb3cde60-51fc-5a23-b3cd-5914001d0b7b\",\"properties\":{\"title\":\"article 264 recall quantize\"}}],\"tookMs\":1}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 3, \"returnProperties\": [\"title\", \"wordCount\"], \"returnMetadata\": [\"score\"]}", + "value": { + "fields": [ + "$id", + "title", + "wordCount", + "$score" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "wordCount": 371, + "$score": 1.7275589 + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "wordCount": 101, + "$score": 1.2622087 + }, + { + "$id": "6a685778-9bb0-5b39-b66e-20e12491d845", + "title": "article 494 index graph", + "wordCount": 594, + "$score": 1.0772038 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$score": "score, higher is better" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"category\"], \"operator\": \"Equal\", \"valueText\": \"alpha\"}, \"limit\": 2, \"returnProperties\": [\"title\", \"category\"]}", + "value": { + "fields": [ + "$id", + "title", + "category" + ], + "rows": [ + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall", + "category": "alpha" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection", + "category": "alpha" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "body": "schema replica vector hybrid index index vector vector cosine tenant keyword hybrid", + "category": "beta", + "tags": [ + "graph", + "vector" + ], + "wordCount": 371, + "rating": 2.71, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.708, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + } + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "body": "tenant tenant index object object node schema shard collection object tenant alias", + "category": "beta", + "tags": [ + "replica", + "tenant", + "vector" + ], + "wordCount": 101, + "rating": 0.01, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.438, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + } + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object", + "$distance": 0.23860073 + }, + { + "$id": "b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de", + "title": "article 428 alias keyword", + "$distance": 0.38131392 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 1, \"includeVector\": true}", + "error": { + "name": "RequestRefusal", + "message": "The body takes no key \"includeVector\": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, vector, targetVector, distance, certainty there and nothing else." + } + }, + { + "step": "query POST /v1/search/Article/near-object {\"id\": \"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\", \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "$distance": 1.1920929e-7 + }, + { + "$id": "091a6b21-3727-5500-8f12-17036b912723", + "title": "article 468 shard quantize", + "$distance": 0.3000539 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\", \"alpha\": 0, \"limit\": 2, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "6b7a5622-dfa8-5802-9c9a-b39275345406", + "title": "article 261 vector vector" + }, + { + "$id": "0590a353-a65e-5f95-bafc-0b46dca27152", + "title": "article 223 vector search" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/near-vector {\"vector\": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], \"targetVector\": \"image\", \"limit\": 1, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "9d8ce3ea-cf2e-5f73-a18c-f5016695d856", + "name": "product 019" + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/TenantNotes/bm25 {\"query\": \"note\", \"tenant\": \"acme\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "note", + "seq" + ], + "rows": [ + { + "$id": "5f733153-385b-599c-baea-79de4736abac", + "note": "acme note 02", + "seq": 2 + }, + { + "$id": "988ef2a7-fe5e-591e-b020-9a2239223014", + "note": "acme note 01", + "seq": 1 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/EdgeValues/bm25 {\"query\": \"9007199254740991\", \"returnProperties\": [\"label\", \"big\"]}", + "value": { + "fields": [ + "$id", + "label", + "big" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": 9007199254740991 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/bm25 {\"query\": \"product\", \"limit\": 2, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "51fd5a34-9aa4-54be-afcf-ff814a32afb7", + "name": "product 001" + }, + { + "$id": "92693fd4-cfd7-50d9-a1bc-7d9cf95d0326", + "name": "product 000" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Missing/bm25 {\"query\": \"x\"}", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query POST /v1/aggregate/Article {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"groupBy\": \"category\"}", + "value": { + "fields": [ + "category", + "count" + ], + "rows": [ + { + "category": "epsilon", + "count": 100 + }, + { + "category": "alpha", + "count": 100 + }, + { + "category": "beta", + "count": 100 + }, + { + "category": "delta", + "count": 100 + }, + { + "category": "gamma", + "count": 100 + } + ], + "rowCount": 5, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"acme\"}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 20 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"initech\"}", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query POST /v1/aggregate/Empty {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"operator\": \"And\", \"operands\": [{\"path\": [\"published\"], \"operator\": \"Equal\", \"valueBoolean\": true}, {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}]}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 333 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"tags\"], \"operator\": \"ContainsAny\", \"valueTextArray\": [\"graph\", \"shard\"]}, \"limit\": 50, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema" + }, + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall" + }, + { + "$id": "78dfc127-4ef9-5643-9476-410f7efe648f", + "title": "article 405 cosine vector" + }, + { + "$id": "97059d77-2db1-5521-855a-7fe8043015cc", + "title": "article 273 vector property" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection" + }, + { + "$id": "5950025b-9947-5837-bc3d-b08a911897a1", + "title": "article 262 vector node" + }, + { + "$id": "5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f", + "title": "article 282 filter vector" + }, + { + "$id": "568019d7-fa21-5d7b-98a7-126890f32e51", + "title": "article 341 node index" + }, + { + "$id": "97bf6379-894b-5304-a05d-dc88e2efb96d", + "title": "article 334 quantize filter" + }, + { + "$id": "adbe9c20-828e-5543-ab79-5fe3cd27be37", + "title": "article 224 vector shard" + }, + { + "$id": "b181572c-0cdf-5f13-bde8-87fd7f1ce823", + "title": "article 328 filter property" + }, + { + "$id": "e66f149e-51db-5bdb-afb2-d0fb6d47873d", + "title": "article 164 keyword node" + }, + { + "$id": "9cd5f0ba-baff-56a1-a2a9-053ebc89309e", + "title": "article 403 search schema" + }, + { + "$id": "d84aef74-a1a2-5534-964c-4f2f13f5b040", + "title": "article 463 keyword cosine" + }, + { + "$id": "df43df7f-7493-5b64-b8d1-03be6a838dd8", + "title": "article 037 object node" + }, + { + "$id": "109ab621-699c-521a-a71d-8761665a0fd2", + "title": "article 240 filter keyword" + }, + { + "$id": "11910949-1a12-5d12-9c1c-015c150aa53c", + "title": "article 257 property graph" + }, + { + "$id": "154cade8-3800-54f7-86bf-11940efda50c", + "title": "article 063 replica keyword" + }, + { + "$id": "15a7167f-5614-5907-9c37-6ec7ac2faec3", + "title": "article 242 cosine shard" + }, + { + "$id": "15b9b024-cbbe-506e-8cc6-b547ef29d366", + "title": "article 427 engine object" + }, + { + "$id": "3bf3c3da-3b9d-586e-be52-058c017d408b", + "title": "article 034 cosine replica" + }, + { + "$id": "675a3068-3c33-5279-937b-a1e55d8858e5", + "title": "article 043 shard tenant" + }, + { + "$id": "71ad2be0-c4cb-5d55-ae14-45aaea14f4a9", + "title": "article 245 property shard" + }, + { + "$id": "83a602fc-404e-56fb-9faf-f9405e6f50eb", + "title": "article 426 cosine recall" + }, + { + "$id": "9eeef104-fb18-58a8-83ef-63db7229b331", + "title": "article 156 index hybrid" + }, + { + "$id": "aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d", + "title": "article 385 hybrid cosine" + }, + { + "$id": "b32a7a72-6389-5bb4-9947-49abf9b9cd91", + "title": "article 278 shard engine" + }, + { + "$id": "c7a72ea7-5103-5ef4-b0b7-94052e81e528", + "title": "article 129 cosine tenant" + }, + { + "$id": "efe60c07-cd04-5435-955b-e0f657176bae", + "title": "article 324 tenant alias" + }, + { + "$id": "c9985312-f531-5ed2-a0f4-c4f070fcaffa", + "title": "article 492 search node" + }, + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search" + }, + { + "$id": "16f723f0-5c76-5f11-9cae-c8d970510c4a", + "title": "article 023 shard search" + }, + { + "$id": "2716ffdb-f678-5f5e-a25b-7597d419a8f6", + "title": "article 040 shard graph" + }, + { + "$id": "28a5ee00-944b-5fbe-bb71-775ef97aae95", + "title": "article 024 filter vector" + }, + { + "$id": "30c49f98-46cc-51c8-9364-f0f544bd99f3", + "title": "article 161 object quantize" + }, + { + "$id": "3968998f-7416-5e44-a02b-3d4f6a76d28d", + "title": "article 047 hybrid property" + }, + { + "$id": "3b5e188a-dba4-551c-a4c2-2743202df1bb", + "title": "article 189 schema property" + }, + { + "$id": "4d89b5b1-1efa-561a-add6-06731ea73da5", + "title": "article 197 keyword node" + }, + { + "$id": "4e9f48c4-d174-52ff-becc-c2d72ea4fcde", + "title": "article 128 replica object" + }, + { + "$id": "536bc3a8-9bff-5042-bfb2-f9d9cbecc250", + "title": "article 066 shard object" + }, + { + "$id": "69b31860-8732-512f-aef1-79d35b48ed84", + "title": "article 244 cosine engine" + }, + { + "$id": "754bf866-c2db-5a9b-929e-f69ba6555b80", + "title": "article 185 search filter" + }, + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object" + }, + { + "$id": "a8212a0a-ba71-5ab9-9408-9158262a5711", + "title": "article 202 index tenant" + }, + { + "$id": "a8eadb65-e8e1-5db4-b088-9bae6988ee67", + "title": "article 144 collection graph" + }, + { + "$id": "a9d0efad-a959-552b-b65a-fda42cdbe2cd", + "title": "article 117 collection graph" + }, + { + "$id": "b3c2ed60-4a50-5b93-97f3-d379133c266c", + "title": "article 237 replica object" + }, + { + "$id": "b5391a2a-6084-55bd-ad80-c17ce6392439", + "title": "article 174 quantize tenant" + }, + { + "$id": "d976ca88-a069-5460-a816-70339070c4ce", + "title": "article 029 filter property" + }, + { + "$id": "fb3cde60-51fc-5a23-b3cd-5914001d0b7b", + "title": "article 264 recall quantize" + } + ], + "rowCount": 50, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-nographql/surface.json b/tests/fixtures/weaviate/weaviate-nographql/surface.json new file mode 100644 index 0000000000..bdce18c23f --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-nographql/surface.json @@ -0,0 +1,1708 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-nographql", + "scenario": "surface", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:52.955Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18282", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754774936,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754774936,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792754775188,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792754775188,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754774902,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754774902,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"2e8MmoLp1qWS\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"SsT6dWZV3n2c\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Product", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":200,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"},{\"activityStatus\":\"HOT\",\"name\":\"hooli\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"Jkru19hmdTKo\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/.well-known/ready", + "body": null, + "answer": { + "status": 200, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Author", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":12,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/EdgeValues", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":8,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Product", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":200,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "connectWarnings", + "value": [] + }, + { + "step": "listContainers", + "value": [] + }, + { + "step": "countObjects", + "value": { + "collection": { + "count": 7 + } + } + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "describeObjects", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "EdgeValues" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "big", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "bigs", + "type": "int[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(?, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotesAuto" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ] + } + }, + { + "step": "describeObjects limit 2", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ], + "truncated": { + "limit": 2, + "reason": "the bulk column read was bounded at 2 objects by its caller" + } + } + }, + { + "step": "describeObject Article", + "value": { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(16, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Product", + "value": { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(8, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(16, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Author", + "value": { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Empty", + "value": { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "readObjectSource Article", + "value": { + "path": [ + "Article" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Article\",\n \"description\": \"one unnamed vector, a cross-reference and the common property types\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"indexTimestamps\": true,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"title\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"body\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"category\",\n \"tokenization\": \"field\"\n },\n {\n \"dataType\": [\n \"text[]\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"tags\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"wordCount\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"rating\"\n },\n {\n \"dataType\": [\n \"boolean\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"published\"\n },\n {\n \"dataType\": [\n \"date\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"publishedAt\"\n },\n {\n \"dataType\": [\n \"geoCoordinates\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"location\"\n },\n {\n \"dataType\": [\n \"object\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"meta\",\n \"nestedProperties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"source\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"revision\"\n }\n ]\n },\n {\n \"dataType\": [\n \"Author\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"writtenBy\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [\n \"Articles\"\n ],\n \"shards\": [\n {\n \"name\": \"2e8MmoLp1qWS\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 500,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Product", + "value": { + "path": [ + "Product" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Product\",\n \"description\": \"two named vectors with different dimensions and distances\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"name\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"price\"\n },\n {\n \"dataType\": [\n \"uuid\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"sku\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorConfig\": {\n \"image\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": {\n \"none\": {}\n }\n },\n \"text\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"distance\": \"dot\",\n \"pq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"rq\": {\n \"bits\": 8,\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"flat\",\n \"vectorizer\": {\n \"none\": {}\n }\n }\n },\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"SsT6dWZV3n2c\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 200,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotes\",\n \"description\": \"multi-tenant, a read does not activate a tenant\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": false,\n \"aliases\": [],\n \"tenantCount\": 3,\n \"tenants\": [\n {\n \"name\": \"acme\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"globex\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"initech\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotesAuto", + "value": { + "path": [ + "TenantNotesAuto" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotesAuto\",\n \"description\": \"multi-tenant with autoTenantActivation on\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": true,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": true,\n \"aliases\": [],\n \"tenantCount\": 2,\n \"tenants\": [\n {\n \"name\": \"hooli\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"umbrella\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Empty", + "value": { + "path": [ + "Empty" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Empty\",\n \"description\": \"no objects\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"label\",\n \"tokenization\": \"word\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"Jkru19hmdTKo\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 0,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "getHealth", + "value": { + "databaseSize": "N/A", + "cacheHitRatio": "N/A", + "slowQueries": [], + "activeSessions": [] + } + }, + { + "step": "getOverview", + "value": { + "version": "1.40.2", + "uptime": "N/A", + "maxConnections": 0, + "databaseSize": "N/A", + "tableCount": 7, + "indexCount": 8 + } + }, + { + "step": "getTableStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "rowCount": 500, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "rowCount": 12, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "rowCount": 8, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "rowCount": 0, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "rowCount": 200, + "totalSize": "N/A", + "totalSizeBytes": 0 + } + ] + }, + { + "step": "getIndexStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.image", + "indexType": "hnsw, cosine", + "columns": [ + "$vector.image" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.text", + "indexType": "flat, dot", + "columns": [ + "$vector.text" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotes", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotesAuto", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + } + ] + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-tls/plain-to-tls.json b/tests/fixtures/weaviate/weaviate-tls/plain-to-tls.json new file mode 100644 index 0000000000..cb36307946 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-tls/plain-to-tls.json @@ -0,0 +1,44 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-tls", + "scenario": "plain-to-tls", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.096Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18284", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 400, + "contentType": null, + "retryAfter": null, + "text": "Client sent an HTTP request to an HTTPS server.\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "error": { + "name": "ConnectionError", + "message": "Weaviate at 127.0.0.1:18284 speaks TLS on this port, and the connection sent plain HTTP: choose an SSL mode under SSL / TLS." + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate-tls/reader.json b/tests/fixtures/weaviate/weaviate-tls/reader.json new file mode 100644 index 0000000000..572d5a7157 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate-tls/reader.json @@ -0,0 +1,201 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate-tls", + "scenario": "reader", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:53.092Z", + "runtime": "bun 1.4.2", + "credential": "reader" + }, + "transport": [ + { + "origin": "https://127.0.0.1:18284", + "tls": { + "rejectUnauthorized": true, + "ca": true + }, + "maxSockets": 4, + "headers": { + "authorization": "Bearer " + } + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"https://[::]:8443\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=1", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754767745,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754767745,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "query GET /v1/objects?class=Article&limit=1", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754767745, + "$lastUpdateTime": 1792754767745 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=00139992-3118-5ccc-bfac-42062afb1418 to read the next 1." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate/reads.json b/tests/fixtures/weaviate/weaviate/reads.json new file mode 100644 index 0000000000..f8fd2c9503 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate/reads.json @@ -0,0 +1,3113 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate", + "scenario": "reads", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:52.433Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18280", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"PqZ7DmG5G0U9\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases/Articles", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"alias\":\"Articles\",\"class\":\"Article\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":0},\"gitHash\":\"8b9cac3\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":null,\"status\":\"HEALTHY\",\"version\":\"1.40.2\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes?output=verbose", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":0},\"gitHash\":\"8b9cac3\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":[{\"asyncReplicationStatus\":[],\"class\":\"Article\",\"compressed\":false,\"loaded\":true,\"name\":\"PqZ7DmG5G0U9\",\"numberOfReplicas\":1,\"objectCount\":500,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Author\",\"compressed\":false,\"loaded\":true,\"name\":\"FEg1d1biwC0n\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"EdgeValues\",\"compressed\":false,\"loaded\":true,\"name\":\"370dyulQSf5d\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Empty\",\"compressed\":false,\"loaded\":true,\"name\":\"2nk4zUrnyCFk\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"Product\",\"compressed\":false,\"loaded\":true,\"name\":\"VC0BMTbIis9m\",\"numberOfReplicas\":1,\"objectCount\":200,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"TenantNotes\",\"compressed\":false,\"loaded\":true,\"name\":\"acme\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"TenantNotes\",\"compressed\":false,\"loaded\":true,\"name\":\"globex\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0},{\"asyncReplicationStatus\":[],\"class\":\"TenantNotesAuto\",\"compressed\":false,\"loaded\":true,\"name\":\"hooli\",\"numberOfReplicas\":1,\"objectCount\":0,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0}],\"stats\":{\"objectCount\":700,\"shardCount\":8},\"status\":\"HEALTHY\",\"version\":\"1.40.2\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/nodes/Article?output=verbose", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"nodes\":[{\"batchStats\":{\"queueLength\":0,\"ratePerSecond\":0},\"gitHash\":\"8b9cac3\",\"name\":\"node1\",\"operationalMode\":\"ReadWrite\",\"shards\":[{\"asyncReplicationStatus\":[],\"class\":\"Article\",\"compressed\":false,\"loaded\":true,\"name\":\"PqZ7DmG5G0U9\",\"numberOfReplicas\":1,\"objectCount\":500,\"replicationFactor\":1,\"vectorIndexingStatus\":\"READY\",\"vectorQueueLength\":0}],\"stats\":{\"objectCount\":500,\"shardCount\":1},\"status\":\"HEALTHY\",\"version\":\"1.40.2\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=3", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754764912,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754764912,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754765140,\"id\":\"0092cefc-15f3-507f-a85c-2453b81d8c8c\",\"lastUpdateTimeUnix\":1792754765140,\"properties\":{\"body\":\"cosine quantize alias object collection tenant collection shard tenant engine alias hybrid\",\"category\":\"delta\",\"location\":{\"latitude\":59.91,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":4.73,\"tags\":[\"collection\",\"keyword\",\"vector\"],\"title\":\"article 473 keyword search\",\"wordCount\":573,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\",\"href\":\"/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\"}]},\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754765069,\"id\":\"00df1951-be86-5fc4-9acb-b15841334bdf\",\"lastUpdateTimeUnix\":1792754765069,\"properties\":{\"body\":\"search quantize hybrid engine collection keyword node collection object shard vector quantize\",\"category\":\"beta\",\"location\":{\"latitude\":59.743,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":3.06,\"tags\":[\"filter\",\"node\",\"tenant\"],\"title\":\"article 306 alias tenant\",\"wordCount\":406,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vectorWeights\":null}],\"totalResults\":3}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=2&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754764912,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754764912,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null},{\"class\":\"Article\",\"creationTimeUnix\":1792754765140,\"id\":\"0092cefc-15f3-507f-a85c-2453b81d8c8c\",\"lastUpdateTimeUnix\":1792754765140,\"properties\":{\"body\":\"cosine quantize alias object collection tenant collection shard tenant engine alias hybrid\",\"category\":\"delta\",\"location\":{\"latitude\":59.91,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":4.73,\"tags\":[\"collection\",\"keyword\",\"vector\"],\"title\":\"article 473 keyword search\",\"wordCount\":573,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\",\"href\":\"/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9\"}]},\"vector\":[-0.348508,0.371256,-0.002633,0.438731,0.926627,0.645241,-0.489321,0.334734,-0.536027,0.075017,0.195246,-0.898757,-0.389559,-0.054653,0.906537,-0.046758],\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792754765214,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792754765214,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=25", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=EdgeValues&limit=8", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":9007199254740991,\"bigs\":[9007199254740991,1],\"label\":\"9007199254740991\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"0a225532-c59c-5c0e-a365-e9feabb88bb5\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":-9223372036854776000,\"bigs\":[-9223372036854776000,1],\"label\":\"-9223372036854775808\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"3984d4bc-224d-5e18-914c-d8bc85b5d189\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":9223372036854776000,\"bigs\":[9223372036854776000,1],\"label\":\"9223372036854775807\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"5dd5d8d9-71eb-5aea-94a7-ab89ee407a8f\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":42,\"bigs\":[42,1],\"label\":\"42\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"85cfb82b-1e89-5b48-b745-e5b05e1566c0\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":-42,\"bigs\":[-42,1],\"label\":\"-42\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"b3530c1a-63ca-5bc5-b14f-c55a1771ef5c\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":9007199254740992,\"bigs\":[9007199254740992,1],\"label\":\"9007199254740993\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"b47ca1ec-54e9-5f83-81c2-0e83338906c3\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":0,\"bigs\":[0,1],\"label\":\"0\"},\"vectorWeights\":null},{\"class\":\"EdgeValues\",\"creationTimeUnix\":1792754765278,\"id\":\"ed773a9a-e98d-53df-baaf-d4cbd1915be3\",\"lastUpdateTimeUnix\":1792754765278,\"properties\":{\"big\":4611686018427388000,\"bigs\":[4611686018427388000,1],\"label\":\"4611686018427387911\"},\"vectorWeights\":null}],\"totalResults\":8}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"creationTimeUnix\":1792754764912,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"lastUpdateTimeUnix\":1792754764912,\"properties\":{\"body\":\"replica alias collection collection schema engine recall object quantize property schema filter\",\"category\":\"epsilon\",\"location\":{\"latitude\":59.536,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.99,\"tags\":[\"alias\",\"schema\"],\"title\":\"article 099 tenant index\",\"wordCount\":199,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\",\"href\":\"/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\"}]},\"vectorWeights\":null}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d?include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"creationTimeUnix\":1792754764912,\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"lastUpdateTimeUnix\":1792754764912,\"properties\":{\"body\":\"replica alias collection collection schema engine recall object quantize property schema filter\",\"category\":\"epsilon\",\"location\":{\"latitude\":59.536,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.99,\"tags\":[\"alias\",\"schema\"],\"title\":\"article 099 tenant index\",\"wordCount\":199,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\",\"href\":\"/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28\"}]},\"vector\":[-0.824794,0.547532,0.989252,-0.893327,-0.748434,0.069502,0.659972,0.593562,-0.803924,-0.346175,0.465874,-0.068295,-0.076308,-0.910744,0.029835,-0.034573],\"vectorWeights\":null}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects/Article/00000000-0000-0000-0000-000000000000", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=TenantNotes&limit=2&tenant=acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"TenantNotes\",\"creationTimeUnix\":1792754765263,\"id\":\"0d476b6c-11c4-5d8b-9ef1-505058d6cd01\",\"lastUpdateTimeUnix\":1792754765263,\"properties\":{\"note\":\"acme note 11\",\"seq\":11},\"vectorWeights\":null},{\"class\":\"TenantNotes\",\"creationTimeUnix\":1792754765263,\"id\":\"116eeb91-f7bb-5250-91cf-c252e2bc5f38\",\"lastUpdateTimeUnix\":1792754765263,\"properties\":{\"note\":\"acme note 07\",\"seq\":7},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants/umbrella", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&offset=0", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&offset=2", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"756f95fb-f154-5022-a811-ce9d4198c9dc\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"DE\",\"name\":\"author 10\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"91f4c2c0-cd1d-51c1-abaf-b7de23cc0002\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"EE\",\"name\":\"author 08\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&sort=name", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"98fe41ca-2d7c-54e2-b6df-71de7c0a8ae7\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"TR\",\"name\":\"author 01\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=2&after=00000000-0000-0000-0000-000000000000", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null},{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"188d0dcf-7792-5d1d-83d0-b36a206db92a\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"EE\",\"name\":\"author 00\"},\"vectorWeights\":null}],\"totalResults\":2}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query GET /v1/meta", + "value": { + "fields": [ + "grpcMaxMessageSize", + "hostname", + "license", + "modules", + "version" + ], + "rows": [ + { + "grpcMaxMessageSize": 104858000, + "hostname": "http://[::]:8080", + "license": { + "documentationHref": "https://docs.weaviate.io/deploy/enterprise", + "edition": "community" + }, + "modules": {}, + "version": "1.40.2" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema", + "value": { + "fields": [ + "class", + "description", + "invertedIndexConfig", + "multiTenancyConfig", + "properties", + "shardingConfig", + "vectorIndexConfig", + "vectorIndexType", + "vectorizer", + "replicationConfig", + "vectorConfig" + ], + "rows": [ + { + "class": "Author", + "description": "objects with no vector at all", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "name", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "country", + "tokenization": "field" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "TenantNotesAuto", + "description": "multi-tenant with autoTenantActivation on", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": true, + "autoTenantCreation": false, + "enabled": true + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "note", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "seq" + } + ], + "shardingConfig": { + "actualCount": 0, + "actualVirtualCount": 0, + "desiredCount": 0, + "desiredVirtualCount": 0, + "function": "", + "key": "", + "strategy": "", + "virtualPerPhysical": 0 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "TenantNotes", + "description": "multi-tenant, a read does not activate a tenant", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": true + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "note", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "seq" + } + ], + "shardingConfig": { + "actualCount": 0, + "actualVirtualCount": 0, + "desiredCount": 0, + "desiredVirtualCount": 0, + "function": "", + "key": "", + "strategy": "", + "virtualPerPhysical": 0 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "EdgeValues", + "description": "int64 values a float64 cannot hold, one object per value", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "label", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "big" + }, + { + "dataType": [ + "int[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "bigs" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "Article", + "description": "one unnamed vector, a cross-reference and the common property types", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "indexTimestamps": true, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "title", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "body", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "category", + "tokenization": "field" + }, + { + "dataType": [ + "text[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "tags", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "wordCount" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "rating" + }, + { + "dataType": [ + "boolean" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "published" + }, + { + "dataType": [ + "date" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "publishedAt" + }, + { + "dataType": [ + "geoCoordinates" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "location" + }, + { + "dataType": [ + "object" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "meta", + "nestedProperties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "source", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "revision" + } + ] + }, + { + "dataType": [ + "Author" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "writtenBy" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "Empty", + "description": "no objects", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "label", + "tokenization": "word" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": null + }, + { + "class": "Product", + "description": "two named vectors with different dimensions and distances", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "name", + "tokenization": "word" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "price" + }, + { + "dataType": [ + "uuid" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "sku" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": null, + "vectorIndexType": null, + "vectorizer": null, + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + }, + "vectorConfig": { + "image": { + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": { + "none": {} + } + }, + "text": { + "vectorIndexConfig": { + "bq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "distance": "dot", + "pq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "rq": { + "bits": 8, + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "skipDefaultQuantization": false, + "sq": { + "cache": false, + "enabled": false, + "rescoreLimit": -1 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "flat", + "vectorizer": { + "none": {} + } + } + } + } + ], + "rowCount": 7, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/Article", + "value": { + "fields": [ + "class", + "description", + "invertedIndexConfig", + "multiTenancyConfig", + "properties", + "shardingConfig", + "vectorIndexConfig", + "vectorIndexType", + "vectorizer", + "replicationConfig" + ], + "rows": [ + { + "class": "Article", + "description": "one unnamed vector, a cross-reference and the common property types", + "invertedIndexConfig": { + "bm25": { + "b": 0.75, + "k1": 1.2 + }, + "cleanupIntervalSeconds": 60, + "indexTimestamps": true, + "stopwords": { + "additions": null, + "preset": "en", + "removals": null + }, + "usingBlockMaxWAND": true + }, + "multiTenancyConfig": { + "autoTenantActivation": false, + "autoTenantCreation": false, + "enabled": false + }, + "properties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "title", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "body", + "tokenization": "word" + }, + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "category", + "tokenization": "field" + }, + { + "dataType": [ + "text[]" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "tags", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "wordCount" + }, + { + "dataType": [ + "number" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "rating" + }, + { + "dataType": [ + "boolean" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "published" + }, + { + "dataType": [ + "date" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "publishedAt" + }, + { + "dataType": [ + "geoCoordinates" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "location" + }, + { + "dataType": [ + "object" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "meta", + "nestedProperties": [ + { + "dataType": [ + "text" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": true, + "name": "source", + "tokenization": "word" + }, + { + "dataType": [ + "int" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "revision" + } + ] + }, + { + "dataType": [ + "Author" + ], + "indexFilterable": true, + "indexRangeFilters": false, + "indexSearchable": false, + "name": "writtenBy" + } + ], + "shardingConfig": { + "actualCount": 1, + "actualVirtualCount": 128, + "desiredCount": 1, + "desiredVirtualCount": 128, + "function": "murmur3", + "key": "_id", + "strategy": "hash", + "virtualPerPhysical": 128 + }, + "vectorIndexConfig": { + "bq": { + "enabled": false + }, + "cleanupIntervalSeconds": 300, + "distance": "cosine", + "dynamicEfFactor": 8, + "dynamicEfMax": 500, + "dynamicEfMin": 100, + "ef": -1, + "efConstruction": 128, + "filterStrategy": "acorn", + "flatSearchCutoff": 40000, + "maxConnections": 32, + "multivector": { + "aggregation": "maxSim", + "enabled": false, + "muvera": { + "dprojections": 16, + "enabled": false, + "ksim": 4, + "repetitions": 10 + } + }, + "pq": { + "bitCompression": false, + "centroids": 256, + "enabled": false, + "encoder": { + "distribution": "log-normal", + "type": "kmeans" + }, + "segments": 0, + "trainingLimit": 100000 + }, + "rq": { + "bits": 8, + "centering": false, + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 10000 + }, + "skip": false, + "skipDefaultQuantization": false, + "sq": { + "enabled": false, + "rescoreLimit": 20, + "trainingLimit": 100000 + }, + "trackDefaultQuantization": false, + "vectorCacheMaxObjects": 1000000000000 + }, + "vectorIndexType": "hnsw", + "vectorizer": "none", + "replicationConfig": { + "deletionStrategy": "TimeBasedResolution", + "factor": 1, + "asyncEnabled": false + } + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/Article/shards", + "value": { + "fields": [ + "name", + "per_node_status", + "status", + "vectorQueueSize" + ], + "rows": [ + { + "name": "PqZ7DmG5G0U9", + "per_node_status": { + "node1": "READY" + }, + "status": "READY", + "vectorQueueSize": 0 + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "HOT", + "name": "acme" + }, + { + "activityStatus": "HOT", + "name": "globex" + }, + { + "activityStatus": "COLD", + "name": "initech" + } + ], + "rowCount": 3, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants/acme", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "HOT", + "name": "acme" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/schema/TenantNotes/tenants/initech", + "value": { + "fields": [ + "activityStatus", + "name" + ], + "rows": [ + { + "activityStatus": "COLD", + "name": "initech" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/aliases", + "value": { + "fields": [ + "alias", + "class" + ], + "rows": [ + { + "alias": "Articles", + "class": "Article" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/aliases/Articles", + "value": { + "fields": [ + "alias", + "class" + ], + "rows": [ + { + "alias": "Articles", + "class": "Article" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 0 + }, + "gitHash": "8b9cac3", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": null, + "status": "HEALTHY", + "version": "1.40.2" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes?output=verbose", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "stats", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 0 + }, + "gitHash": "8b9cac3", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": [ + { + "asyncReplicationStatus": [], + "class": "Article", + "compressed": false, + "loaded": true, + "name": "PqZ7DmG5G0U9", + "numberOfReplicas": 1, + "objectCount": 500, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Author", + "compressed": false, + "loaded": true, + "name": "FEg1d1biwC0n", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "EdgeValues", + "compressed": false, + "loaded": true, + "name": "370dyulQSf5d", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Empty", + "compressed": false, + "loaded": true, + "name": "2nk4zUrnyCFk", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "Product", + "compressed": false, + "loaded": true, + "name": "VC0BMTbIis9m", + "numberOfReplicas": 1, + "objectCount": 200, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "TenantNotes", + "compressed": false, + "loaded": true, + "name": "acme", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "TenantNotes", + "compressed": false, + "loaded": true, + "name": "globex", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + }, + { + "asyncReplicationStatus": [], + "class": "TenantNotesAuto", + "compressed": false, + "loaded": true, + "name": "hooli", + "numberOfReplicas": 1, + "objectCount": 0, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + } + ], + "stats": { + "objectCount": 700, + "shardCount": 8 + }, + "status": "HEALTHY", + "version": "1.40.2" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/nodes/Article?output=verbose", + "value": { + "fields": [ + "batchStats", + "gitHash", + "name", + "operationalMode", + "shards", + "stats", + "status", + "version" + ], + "rows": [ + { + "batchStats": { + "queueLength": 0, + "ratePerSecond": 0 + }, + "gitHash": "8b9cac3", + "name": "node1", + "operationalMode": "ReadWrite", + "shards": [ + { + "asyncReplicationStatus": [], + "class": "Article", + "compressed": false, + "loaded": true, + "name": "PqZ7DmG5G0U9", + "numberOfReplicas": 1, + "objectCount": 500, + "replicationFactor": 1, + "vectorIndexingStatus": "READY", + "vectorQueueLength": 0 + } + ], + "stats": { + "objectCount": 500, + "shardCount": 1 + }, + "status": "HEALTHY", + "version": "1.40.2" + } + ], + "rowCount": 1, + "columnTypes": {} + } + }, + { + "step": "query GET /v1/objects?class=Article&limit=3", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754764912, + "$lastUpdateTime": 1792754764912 + }, + { + "$id": "0092cefc-15f3-507f-a85c-2453b81d8c8c", + "title": "article 473 keyword search", + "body": "cosine quantize alias object collection tenant collection shard tenant engine alias hybrid", + "category": "delta", + "tags": [ + "collection", + "keyword", + "vector" + ], + "wordCount": 573, + "rating": 4.73, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.91, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9", + "href": "/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9" + } + ], + "$creationTime": 1792754765140, + "$lastUpdateTime": 1792754765140 + }, + { + "$id": "00df1951-be86-5fc4-9acb-b15841334bdf", + "title": "article 306 alias tenant", + "body": "search quantize hybrid engine collection keyword node collection object shard vector quantize", + "category": "beta", + "tags": [ + "filter", + "node", + "tenant" + ], + "wordCount": 406, + "rating": 3.06, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.743, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$creationTime": 1792754765069, + "$lastUpdateTime": 1792754765069 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=00df1951-be86-5fc4-9acb-b15841334bdf to read the next 3." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Article&limit=2&include=vector", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$vector", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search", + "body": "engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine", + "category": "gamma", + "tags": [ + "replica", + "schema", + "shard" + ], + "wordCount": 142, + "rating": 0.42, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.479, + "longitude": 24.7536 + }, + "meta": { + "revision": 2, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683", + "href": "/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683" + } + ], + "$vector": [ + 0.090872, + -0.268579, + 0.799546, + 0.963254, + 0.140379, + 0.019355, + -0.921561, + 0.336068, + -0.831569, + 0.932756, + -0.881524, + 0.622357, + -0.189283, + 0.105446, + 0.013549, + 0.315139 + ], + "$creationTime": 1792754764912, + "$lastUpdateTime": 1792754764912 + }, + { + "$id": "0092cefc-15f3-507f-a85c-2453b81d8c8c", + "title": "article 473 keyword search", + "body": "cosine quantize alias object collection tenant collection shard tenant engine alias hybrid", + "category": "delta", + "tags": [ + "collection", + "keyword", + "vector" + ], + "wordCount": 573, + "rating": 4.73, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.91, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9", + "href": "/v1/objects/Author/a83cc937-c45d-554c-b77a-9fa4397ffed9" + } + ], + "$vector": [ + -0.348508, + 0.371256, + -0.002633, + 0.438731, + 0.926627, + 0.645241, + -0.489321, + 0.334734, + -0.536027, + 0.075017, + 0.195246, + -0.898757, + -0.389559, + -0.054653, + 0.906537, + -0.046758 + ], + "$creationTime": 1792754765140, + "$lastUpdateTime": 1792754765140 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + }, + "warnings": [ + { + "message": "More objects may follow: add &after=0092cefc-15f3-507f-a85c-2453b81d8c8c to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Product&limit=1&include=vector", + "value": { + "fields": [ + "$id", + "name", + "price", + "sku", + "$vector.image", + "$vector.text", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "017df454-5e7d-575f-a30b-81ab587ab05f", + "name": "product 087", + "price": 22.75, + "sku": "d73893f9-6387-5361-8190-44281f1fa3c9", + "$vector.image": [ + -0.004234, + 0.925485, + 0.143918, + -0.16418, + 0.567372, + 0.745523, + 0.214667, + -0.240875 + ], + "$vector.text": [ + -0.095434, + -0.084195, + 0.446122, + -0.414162, + -0.218631, + 0.110703, + -0.230998, + -0.356012, + 0.574156, + 0.699133, + -0.0009, + -0.111938, + -0.631577, + -0.391935, + -0.710019, + 0.150866 + ], + "$creationTime": 1792754765214, + "$lastUpdateTime": 1792754765214 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector.image": { + "kind": "dense", + "dtype": "float32", + "dimension": 8 + }, + "$vector.text": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + }, + "warnings": [ + { + "message": "More objects may follow: add &after=017df454-5e7d-575f-a30b-81ab587ab05f to read the next 1." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=188d0dcf-7792-5d1d-83d0-b36a206db92a to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=Empty", + "value": { + "fields": [ + "$id" + ], + "rows": [], + "rowCount": 0, + "columnTypes": { + "$id": "uuid" + } + } + }, + { + "step": "query GET /v1/objects?class=EdgeValues&limit=8", + "value": { + "fields": [ + "$id", + "label", + "big", + "bigs", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": 9007199254740991, + "bigs": [ + 9007199254740991, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "0a225532-c59c-5c0e-a365-e9feabb88bb5", + "label": "-9223372036854775808", + "big": -9223372036854776000, + "bigs": [ + -9223372036854776000, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "3984d4bc-224d-5e18-914c-d8bc85b5d189", + "label": "9223372036854775807", + "big": 9223372036854776000, + "bigs": [ + 9223372036854776000, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "5dd5d8d9-71eb-5aea-94a7-ab89ee407a8f", + "label": "42", + "big": 42, + "bigs": [ + 42, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "85cfb82b-1e89-5b48-b745-e5b05e1566c0", + "label": "-42", + "big": -42, + "bigs": [ + -42, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "b3530c1a-63ca-5bc5-b14f-c55a1771ef5c", + "label": "9007199254740993", + "big": 9007199254740992, + "bigs": [ + 9007199254740992, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "b47ca1ec-54e9-5f83-81c2-0e83338906c3", + "label": "0", + "big": 0, + "bigs": [ + 0, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + }, + { + "$id": "ed773a9a-e98d-53df-baaf-d4cbd1915be3", + "label": "4611686018427387911", + "big": 4611686018427388000, + "bigs": [ + 4611686018427388000, + 1 + ], + "$creationTime": 1792754765278, + "$lastUpdateTime": 1792754765278 + } + ], + "rowCount": 8, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=ed773a9a-e98d-53df-baaf-d4cbd1915be3 to read the next 8." + } + ] + } + }, + { + "step": "query GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "body": "replica alias collection collection schema engine recall object quantize property schema filter", + "category": "epsilon", + "tags": [ + "alias", + "schema" + ], + "wordCount": 199, + "rating": 0.99, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.536, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28", + "href": "/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28" + } + ], + "$creationTime": 1792754764912, + "$lastUpdateTime": 1792754764912 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d?include=vector", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta", + "writtenBy", + "$vector", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "body": "replica alias collection collection schema engine recall object quantize property schema filter", + "category": "epsilon", + "tags": [ + "alias", + "schema" + ], + "wordCount": 199, + "rating": 0.99, + "published": false, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.536, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + }, + "writtenBy": [ + { + "beacon": "weaviate://localhost/Author/a1d198cc-96c2-59b0-a557-a783965c2b28", + "href": "/v1/objects/Author/a1d198cc-96c2-59b0-a557-a783965c2b28" + } + ], + "$vector": [ + -0.824794, + 0.547532, + 0.989252, + -0.893327, + -0.748434, + 0.069502, + 0.659972, + 0.593562, + -0.803924, + -0.346175, + 0.465874, + -0.068295, + -0.076308, + -0.910744, + 0.029835, + -0.034573 + ], + "$creationTime": 1792754764912, + "$lastUpdateTime": 1792754764912 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "vectorColumns": { + "$vector": { + "kind": "dense", + "dtype": "float32", + "dimension": 16 + } + } + } + }, + { + "step": "query GET /v1/objects/Article/00000000-0000-0000-0000-000000000000", + "error": { + "name": "QueryError", + "message": "No object has this id in this collection." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", + "value": { + "fields": [ + "$id", + "note", + "seq", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "0d476b6c-11c4-5d8b-9ef1-505058d6cd01", + "note": "acme note 11", + "seq": 11, + "$creationTime": 1792754765263, + "$lastUpdateTime": 1792754765263 + }, + { + "$id": "116eeb91-f7bb-5250-91cf-c252e2bc5f38", + "note": "acme note 07", + "seq": 7, + "$creationTime": 1792754765263, + "$lastUpdateTime": 1792754765263 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: add &after=116eeb91-f7bb-5250-91cf-c252e2bc5f38 to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2", + "error": { + "name": "RequestRefusal", + "message": "The collection \"TenantNotes\" is multi-tenant, so the request needs a tenant (?tenant=...). Nothing was read: GET /v1/schema/TenantNotes/tenants lists its tenants and which are HOT, without waking any." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2&tenant=initech", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query GET /v1/objects?class=TenantNotesAuto&limit=2&tenant=umbrella", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"umbrella\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query GET /v1/objects?class=Missing&limit=2", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&offset=0", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&offset=2", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "756f95fb-f154-5022-a811-ce9d4198c9dc", + "name": "author 10", + "country": "DE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + }, + { + "$id": "91f4c2c0-cd1d-51c1-abaf-b7de23cc0002", + "name": "author 08", + "country": "EE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&sort=name", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + }, + { + "$id": "98fe41ca-2d7c-54e2-b6df-71de7c0a8ae7", + "name": "author 01", + "country": "TR", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + } + } + }, + { + "step": "query GET /v1/objects?class=Author&limit=2&after=00000000-0000-0000-0000-000000000000", + "value": { + "fields": [ + "$id", + "name", + "country", + "$creationTime", + "$lastUpdateTime" + ], + "rows": [ + { + "$id": "03a2e87a-c828-5d72-ba13-fee221989fe9", + "name": "author 02", + "country": "DE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + }, + { + "$id": "188d0dcf-7792-5d1d-83d0-b36a206db92a", + "name": "author 00", + "country": "EE", + "$creationTime": 1792754764874, + "$lastUpdateTime": 1792754764874 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$creationTime": "epoch ms", + "$lastUpdateTime": "epoch ms" + }, + "warnings": [ + { + "message": "More objects may follow: set after=188d0dcf-7792-5d1d-83d0-b36a206db92a to read the next 2." + } + ] + } + }, + { + "step": "query GET /v1/schema/Missing", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate/refusals.json b/tests/fixtures/weaviate/weaviate/refusals.json new file mode 100644 index 0000000000..8db7f00fdf --- /dev/null +++ b/tests/fixtures/weaviate/weaviate/refusals.json @@ -0,0 +1,121 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate", + "scenario": "refusals", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:52.524Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18280", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/nobody", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\", \"alpha\": 0.5}", + "error": { + "name": "RequestRefusal", + "message": "alpha must be 0 in this console: any other value makes Weaviate embed the query text with the collection's vectorizer, which sends it to a model provider. Write \"alpha\": 0 for a keyword-only hybrid search." + } + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\"}", + "error": { + "name": "RequestRefusal", + "message": "The body needs the key alpha." + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"x\", \"wher\": {}}", + "error": { + "name": "RequestRefusal", + "message": "The body takes no key \"wher\": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, query, queryProperties there and nothing else." + } + }, + { + "step": "query POST /v1/search/Article/near-text {\"concepts\": [\"x\"]}", + "error": { + "name": "ConsoleRefusal", + "message": "POST /v1/search/Article/near-text is a search that sends its text or media to a model provider, which this console does not run. This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts. (line 1, column 6)" + } + }, + { + "step": "query DELETE /v1/schema/Article", + "error": { + "name": "ConsoleRefusal", + "message": "DELETE /v1/schema/Article is a schema, tenant, index or alias change, which this console does not run. This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts. (line 1, column 1)" + } + }, + { + "step": "query POST /v1/objects {}", + "error": { + "name": "ConsoleRefusal", + "message": "POST /v1/objects is an object write, which this console does not run. This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts. (line 1, column 6)" + } + }, + { + "step": "query GET /v1/backups/filesystem", + "error": { + "name": "ConsoleRefusal", + "message": "GET /v1/backups/filesystem is a backup route, which this console does not run. This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts. (line 1, column 5)" + } + }, + { + "step": "query GET /v1/objects?class=TenantNotes&limit=2&tenant=nobody", + "error": { + "name": "QueryError", + "message": "The tenant does not exist in this collection." + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate/searches.json b/tests/fixtures/weaviate/weaviate/searches.json new file mode 100644 index 0000000000..7d1be9afd8 --- /dev/null +++ b/tests/fixtures/weaviate/weaviate/searches.json @@ -0,0 +1,1293 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate", + "scenario": "searches", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:52.515Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18280", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"limit\":3,\"returnProperties\":[\"title\",\"wordCount\"],\"returnMetadata\":[\"score\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"metadata\":{\"score\":1.7275589},\"properties\":{\"title\":\"article 271 cosine schema\",\"wordCount\":371}},{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"metadata\":{\"score\":1.2622087},\"properties\":{\"title\":\"article 001 schema vector\",\"wordCount\":101}},{\"id\":\"6a685778-9bb0-5b39-b66e-20e12491d845\",\"metadata\":{\"score\":1.0772038},\"properties\":{\"title\":\"article 494 index graph\",\"wordCount\":594}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"where\":{\"path\":[\"category\"],\"operator\":\"Equal\",\"valueText\":\"alpha\"},\"limit\":2,\"returnProperties\":[\"title\",\"category\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\",\"properties\":{\"category\":\"alpha\",\"title\":\"article 260 vector recall\"}},{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\",\"properties\":{\"category\":\"alpha\",\"title\":\"article 065 property collection\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"limit\":2}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"properties\":{\"body\":\"schema replica vector hybrid index index vector vector cosine tenant keyword hybrid\",\"category\":\"beta\",\"location\":{\"latitude\":59.708,\"longitude\":24.7536},\"meta\":{\"revision\":3,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":2.71,\"tags\":[\"graph\",\"vector\"],\"title\":\"article 271 cosine schema\",\"wordCount\":371}},{\"id\":\"c5ea6507-374d-559f-8ee9-270bd411c288\",\"properties\":{\"body\":\"tenant tenant index object object node schema shard collection object tenant alias\",\"category\":\"beta\",\"location\":{\"latitude\":59.438,\"longitude\":24.7536},\"meta\":{\"revision\":1,\"source\":\"seed\"},\"published\":true,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.01,\"tags\":[\"replica\",\"tenant\",\"vector\"],\"title\":\"article 001 schema vector\",\"wordCount\":101}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/near-vector", + "body": "{\"vector\":[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7],\"limit\":2,\"returnProperties\":[\"title\"],\"returnMetadata\":[\"distance\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\",\"metadata\":{\"distance\":0.23860073},\"properties\":{\"title\":\"article 044 quantize object\"}},{\"id\":\"b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de\",\"metadata\":{\"distance\":0.38131392},\"properties\":{\"title\":\"article 428 alias keyword\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/near-object", + "body": "{\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"limit\":2,\"returnProperties\":[\"title\"],\"returnMetadata\":[\"distance\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\",\"metadata\":{\"distance\":1.1920929e-7},\"properties\":{\"title\":\"article 099 tenant index\"}},{\"id\":\"091a6b21-3727-5500-8f12-17036b912723\",\"metadata\":{\"distance\":0.3000539},\"properties\":{\"title\":\"article 468 shard quantize\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/hybrid", + "body": "{\"query\":\"vector\",\"alpha\":0,\"limit\":2,\"returnProperties\":[\"title\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"6b7a5622-dfa8-5802-9c9a-b39275345406\",\"properties\":{\"title\":\"article 261 vector vector\"}},{\"id\":\"0590a353-a65e-5f95-bafc-0b46dca27152\",\"properties\":{\"title\":\"article 223 vector search\"}}],\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Product/near-vector", + "body": "{\"vector\":[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8],\"targetVector\":\"image\",\"limit\":1,\"returnProperties\":[\"name\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"9d8ce3ea-cf2e-5f73-a18c-f5016695d856\",\"properties\":{\"name\":\"product 019\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/TenantNotes/bm25", + "body": "{\"query\":\"note\",\"tenant\":\"acme\",\"limit\":2}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5f733153-385b-599c-baea-79de4736abac\",\"properties\":{\"note\":\"acme note 02\",\"seq\":2}},{\"id\":\"988ef2a7-fe5e-591e-b020-9a2239223014\",\"properties\":{\"note\":\"acme note 01\",\"seq\":1}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/EdgeValues", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/EdgeValues/bm25", + "body": "{\"query\":\"9007199254740991\",\"returnProperties\":[\"label\",\"big\"],\"limit\":10}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"08f3aa7e-ac67-524b-830c-0f0b4522079b\",\"properties\":{\"big\":9007199254740991,\"label\":\"9007199254740991\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Product/bm25", + "body": "{\"query\":\"product\",\"limit\":2,\"returnProperties\":[\"name\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"51fd5a34-9aa4-54be-afcf-ff814a32afb7\",\"properties\":{\"name\":\"product 001\"}},{\"id\":\"92693fd4-cfd7-50d9-a1bc-7d9cf95d0326\",\"properties\":{\"name\":\"product 000\"}}],\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Missing", + "body": null, + "answer": { + "status": 404, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"groupBy\":\"category\",\"limit\":100}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"groups\":[{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"beta\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"delta\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"gamma\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"epsilon\"}},{\"count\":100,\"groupedBy\":{\"path\":[\"category\"],\"value\":\"alpha\"}}],\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/acme", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"HOT\",\"name\":\"acme\"}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/TenantNotes", + "body": "{\"tenant\":\"acme\"}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":20,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants/initech", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"activityStatus\":\"COLD\",\"name\":\"initech\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"where\":{\"path\":[\"location\"],\"operator\":\"WithinGeoRange\",\"valueGeoRange\":{\"geoCoordinates\":{\"latitude\":41,\"longitude\":29},\"distance\":{\"max\":3000000}}}}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{\"where\":{\"operator\":\"And\",\"operands\":[{\"path\":[\"published\"],\"operator\":\"Equal\",\"valueBoolean\":true},{\"path\":[\"location\"],\"operator\":\"WithinGeoRange\",\"valueGeoRange\":{\"geoCoordinates\":{\"latitude\":41,\"longitude\":29},\"distance\":{\"max\":3000000}}}]}}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":333,\"tookMs\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/search/Article/bm25", + "body": "{\"query\":\"vector\",\"where\":{\"path\":[\"tags\"],\"operator\":\"ContainsAny\",\"valueTextArray\":[\"graph\",\"shard\"]},\"limit\":50,\"returnProperties\":[\"title\"]}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"results\":[{\"id\":\"5878774a-b088-5365-803b-f38de3ae1785\",\"properties\":{\"title\":\"article 271 cosine schema\"}},{\"id\":\"0245f640-b59b-53d9-9c84-456331b99614\",\"properties\":{\"title\":\"article 260 vector recall\"}},{\"id\":\"78dfc127-4ef9-5643-9476-410f7efe648f\",\"properties\":{\"title\":\"article 405 cosine vector\"}},{\"id\":\"97059d77-2db1-5521-855a-7fe8043015cc\",\"properties\":{\"title\":\"article 273 vector property\"}},{\"id\":\"8fc2a823-3c0d-5585-87a8-ada81a6e779d\",\"properties\":{\"title\":\"article 065 property collection\"}},{\"id\":\"5950025b-9947-5837-bc3d-b08a911897a1\",\"properties\":{\"title\":\"article 262 vector node\"}},{\"id\":\"5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f\",\"properties\":{\"title\":\"article 282 filter vector\"}},{\"id\":\"568019d7-fa21-5d7b-98a7-126890f32e51\",\"properties\":{\"title\":\"article 341 node index\"}},{\"id\":\"97bf6379-894b-5304-a05d-dc88e2efb96d\",\"properties\":{\"title\":\"article 334 quantize filter\"}},{\"id\":\"adbe9c20-828e-5543-ab79-5fe3cd27be37\",\"properties\":{\"title\":\"article 224 vector shard\"}},{\"id\":\"b181572c-0cdf-5f13-bde8-87fd7f1ce823\",\"properties\":{\"title\":\"article 328 filter property\"}},{\"id\":\"e66f149e-51db-5bdb-afb2-d0fb6d47873d\",\"properties\":{\"title\":\"article 164 keyword node\"}},{\"id\":\"9cd5f0ba-baff-56a1-a2a9-053ebc89309e\",\"properties\":{\"title\":\"article 403 search schema\"}},{\"id\":\"d84aef74-a1a2-5534-964c-4f2f13f5b040\",\"properties\":{\"title\":\"article 463 keyword cosine\"}},{\"id\":\"df43df7f-7493-5b64-b8d1-03be6a838dd8\",\"properties\":{\"title\":\"article 037 object node\"}},{\"id\":\"109ab621-699c-521a-a71d-8761665a0fd2\",\"properties\":{\"title\":\"article 240 filter keyword\"}},{\"id\":\"11910949-1a12-5d12-9c1c-015c150aa53c\",\"properties\":{\"title\":\"article 257 property graph\"}},{\"id\":\"154cade8-3800-54f7-86bf-11940efda50c\",\"properties\":{\"title\":\"article 063 replica keyword\"}},{\"id\":\"15a7167f-5614-5907-9c37-6ec7ac2faec3\",\"properties\":{\"title\":\"article 242 cosine shard\"}},{\"id\":\"15b9b024-cbbe-506e-8cc6-b547ef29d366\",\"properties\":{\"title\":\"article 427 engine object\"}},{\"id\":\"3bf3c3da-3b9d-586e-be52-058c017d408b\",\"properties\":{\"title\":\"article 034 cosine replica\"}},{\"id\":\"675a3068-3c33-5279-937b-a1e55d8858e5\",\"properties\":{\"title\":\"article 043 shard tenant\"}},{\"id\":\"71ad2be0-c4cb-5d55-ae14-45aaea14f4a9\",\"properties\":{\"title\":\"article 245 property shard\"}},{\"id\":\"83a602fc-404e-56fb-9faf-f9405e6f50eb\",\"properties\":{\"title\":\"article 426 cosine recall\"}},{\"id\":\"9eeef104-fb18-58a8-83ef-63db7229b331\",\"properties\":{\"title\":\"article 156 index hybrid\"}},{\"id\":\"aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d\",\"properties\":{\"title\":\"article 385 hybrid cosine\"}},{\"id\":\"b32a7a72-6389-5bb4-9947-49abf9b9cd91\",\"properties\":{\"title\":\"article 278 shard engine\"}},{\"id\":\"c7a72ea7-5103-5ef4-b0b7-94052e81e528\",\"properties\":{\"title\":\"article 129 cosine tenant\"}},{\"id\":\"efe60c07-cd04-5435-955b-e0f657176bae\",\"properties\":{\"title\":\"article 324 tenant alias\"}},{\"id\":\"c9985312-f531-5ed2-a0f4-c4f070fcaffa\",\"properties\":{\"title\":\"article 492 search node\"}},{\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"properties\":{\"title\":\"article 042 index search\"}},{\"id\":\"16f723f0-5c76-5f11-9cae-c8d970510c4a\",\"properties\":{\"title\":\"article 023 shard search\"}},{\"id\":\"2716ffdb-f678-5f5e-a25b-7597d419a8f6\",\"properties\":{\"title\":\"article 040 shard graph\"}},{\"id\":\"28a5ee00-944b-5fbe-bb71-775ef97aae95\",\"properties\":{\"title\":\"article 024 filter vector\"}},{\"id\":\"30c49f98-46cc-51c8-9364-f0f544bd99f3\",\"properties\":{\"title\":\"article 161 object quantize\"}},{\"id\":\"3968998f-7416-5e44-a02b-3d4f6a76d28d\",\"properties\":{\"title\":\"article 047 hybrid property\"}},{\"id\":\"3b5e188a-dba4-551c-a4c2-2743202df1bb\",\"properties\":{\"title\":\"article 189 schema property\"}},{\"id\":\"4d89b5b1-1efa-561a-add6-06731ea73da5\",\"properties\":{\"title\":\"article 197 keyword node\"}},{\"id\":\"4e9f48c4-d174-52ff-becc-c2d72ea4fcde\",\"properties\":{\"title\":\"article 128 replica object\"}},{\"id\":\"536bc3a8-9bff-5042-bfb2-f9d9cbecc250\",\"properties\":{\"title\":\"article 066 shard object\"}},{\"id\":\"69b31860-8732-512f-aef1-79d35b48ed84\",\"properties\":{\"title\":\"article 244 cosine engine\"}},{\"id\":\"754bf866-c2db-5a9b-929e-f69ba6555b80\",\"properties\":{\"title\":\"article 185 search filter\"}},{\"id\":\"8d4e0b7b-e646-5fce-8c75-448bded66eb1\",\"properties\":{\"title\":\"article 044 quantize object\"}},{\"id\":\"a8212a0a-ba71-5ab9-9408-9158262a5711\",\"properties\":{\"title\":\"article 202 index tenant\"}},{\"id\":\"a8eadb65-e8e1-5db4-b088-9bae6988ee67\",\"properties\":{\"title\":\"article 144 collection graph\"}},{\"id\":\"a9d0efad-a959-552b-b65a-fda42cdbe2cd\",\"properties\":{\"title\":\"article 117 collection graph\"}},{\"id\":\"b3c2ed60-4a50-5b93-97f3-d379133c266c\",\"properties\":{\"title\":\"article 237 replica object\"}},{\"id\":\"b5391a2a-6084-55bd-ad80-c17ce6392439\",\"properties\":{\"title\":\"article 174 quantize tenant\"}},{\"id\":\"d976ca88-a069-5460-a816-70339070c4ce\",\"properties\":{\"title\":\"article 029 filter property\"}},{\"id\":\"fb3cde60-51fc-5a23-b3cd-5914001d0b7b\",\"properties\":{\"title\":\"article 264 recall quantize\"}}],\"tookMs\":1}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 3, \"returnProperties\": [\"title\", \"wordCount\"], \"returnMetadata\": [\"score\"]}", + "value": { + "fields": [ + "$id", + "title", + "wordCount", + "$score" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "wordCount": 371, + "$score": 1.7275589 + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "wordCount": 101, + "$score": 1.2622087 + }, + { + "$id": "6a685778-9bb0-5b39-b66e-20e12491d845", + "title": "article 494 index graph", + "wordCount": 594, + "$score": 1.0772038 + } + ], + "rowCount": 3, + "columnTypes": { + "$id": "uuid", + "$score": "score, higher is better" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"category\"], \"operator\": \"Equal\", \"valueText\": \"alpha\"}, \"limit\": 2, \"returnProperties\": [\"title\", \"category\"]}", + "value": { + "fields": [ + "$id", + "title", + "category" + ], + "rows": [ + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall", + "category": "alpha" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection", + "category": "alpha" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + "meta" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema", + "body": "schema replica vector hybrid index index vector vector cosine tenant keyword hybrid", + "category": "beta", + "tags": [ + "graph", + "vector" + ], + "wordCount": 371, + "rating": 2.71, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.708, + "longitude": 24.7536 + }, + "meta": { + "revision": 3, + "source": "seed" + } + }, + { + "$id": "c5ea6507-374d-559f-8ee9-270bd411c288", + "title": "article 001 schema vector", + "body": "tenant tenant index object object node schema shard collection object tenant alias", + "category": "beta", + "tags": [ + "replica", + "tenant", + "vector" + ], + "wordCount": 101, + "rating": 0.01, + "published": true, + "publishedAt": "2026-10-01T12:00:00Z", + "location": { + "latitude": 59.438, + "longitude": 24.7536 + }, + "meta": { + "revision": 1, + "source": "seed" + } + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object", + "$distance": 0.23860073 + }, + { + "$id": "b3dbaa8b-f6d5-53d4-bc9c-66ee6393b3de", + "title": "article 428 alias keyword", + "$distance": 0.38131392 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/near-vector {\"vector\": [0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7], \"limit\": 1, \"includeVector\": true}", + "error": { + "name": "RequestRefusal", + "message": "The body takes no key \"includeVector\": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, vector, targetVector, distance, certainty there and nothing else." + } + }, + { + "step": "query POST /v1/search/Article/near-object {\"id\": \"9e6866af-ef70-5a5a-9b61-1ae7a41bad0d\", \"limit\": 2, \"returnProperties\": [\"title\"], \"returnMetadata\": [\"distance\"]}", + "value": { + "fields": [ + "$id", + "title", + "$distance" + ], + "rows": [ + { + "$id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", + "title": "article 099 tenant index", + "$distance": 1.1920929e-7 + }, + { + "$id": "091a6b21-3727-5500-8f12-17036b912723", + "title": "article 468 shard quantize", + "$distance": 0.3000539 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid", + "$distance": "distance, lower is closer" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/hybrid {\"query\": \"vector\", \"alpha\": 0, \"limit\": 2, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "6b7a5622-dfa8-5802-9c9a-b39275345406", + "title": "article 261 vector vector" + }, + { + "$id": "0590a353-a65e-5f95-bafc-0b46dca27152", + "title": "article 223 vector search" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/near-vector {\"vector\": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], \"targetVector\": \"image\", \"limit\": 1, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "9d8ce3ea-cf2e-5f73-a18c-f5016695d856", + "name": "product 019" + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/TenantNotes/bm25 {\"query\": \"note\", \"tenant\": \"acme\", \"limit\": 2}", + "value": { + "fields": [ + "$id", + "note", + "seq" + ], + "rows": [ + { + "$id": "5f733153-385b-599c-baea-79de4736abac", + "note": "acme note 02", + "seq": 2 + }, + { + "$id": "988ef2a7-fe5e-591e-b020-9a2239223014", + "note": "acme note 01", + "seq": 1 + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/EdgeValues/bm25 {\"query\": \"9007199254740991\", \"returnProperties\": [\"label\", \"big\"]}", + "value": { + "fields": [ + "$id", + "label", + "big" + ], + "rows": [ + { + "$id": "08f3aa7e-ac67-524b-830c-0f0b4522079b", + "label": "9007199254740991", + "big": 9007199254740991 + } + ], + "rowCount": 1, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Product/bm25 {\"query\": \"product\", \"limit\": 2, \"returnProperties\": [\"name\"]}", + "value": { + "fields": [ + "$id", + "name" + ], + "rows": [ + { + "$id": "51fd5a34-9aa4-54be-afcf-ff814a32afb7", + "name": "product 001" + }, + { + "$id": "92693fd4-cfd7-50d9-a1bc-7d9cf95d0326", + "name": "product 000" + } + ], + "rowCount": 2, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Missing/bm25 {\"query\": \"x\"}", + "error": { + "name": "QueryError", + "message": "The collection does not exist or is not visible to this credential." + } + }, + { + "step": "query POST /v1/aggregate/Article {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"groupBy\": \"category\"}", + "value": { + "fields": [ + "category", + "count" + ], + "rows": [ + { + "category": "beta", + "count": 100 + }, + { + "category": "delta", + "count": 100 + }, + { + "category": "gamma", + "count": 100 + }, + { + "category": "epsilon", + "count": 100 + }, + { + "category": "alpha", + "count": 100 + } + ], + "rowCount": 5, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"acme\"}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 20 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/TenantNotes {\"tenant\": \"initech\"}", + "error": { + "name": "RequestRefusal", + "message": "The tenant \"initech\" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first." + } + }, + { + "step": "query POST /v1/aggregate/Empty {}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 0 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 500 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/aggregate/Article {\"where\": {\"operator\": \"And\", \"operands\": [{\"path\": [\"published\"], \"operator\": \"Equal\", \"valueBoolean\": true}, {\"path\": [\"location\"], \"operator\": \"WithinGeoRange\", \"valueGeoRange\": {\"geoCoordinates\": {\"latitude\": 41, \"longitude\": 29}, \"distance\": {\"max\": 3000000}}}]}}", + "value": { + "fields": [ + "count" + ], + "rows": [ + { + "count": 333 + } + ], + "rowCount": 1, + "columnTypes": { + "count": "Int64, exact count" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + }, + { + "step": "query POST /v1/search/Article/bm25 {\"query\": \"vector\", \"where\": {\"path\": [\"tags\"], \"operator\": \"ContainsAny\", \"valueTextArray\": [\"graph\", \"shard\"]}, \"limit\": 50, \"returnProperties\": [\"title\"]}", + "value": { + "fields": [ + "$id", + "title" + ], + "rows": [ + { + "$id": "5878774a-b088-5365-803b-f38de3ae1785", + "title": "article 271 cosine schema" + }, + { + "$id": "0245f640-b59b-53d9-9c84-456331b99614", + "title": "article 260 vector recall" + }, + { + "$id": "78dfc127-4ef9-5643-9476-410f7efe648f", + "title": "article 405 cosine vector" + }, + { + "$id": "97059d77-2db1-5521-855a-7fe8043015cc", + "title": "article 273 vector property" + }, + { + "$id": "8fc2a823-3c0d-5585-87a8-ada81a6e779d", + "title": "article 065 property collection" + }, + { + "$id": "5950025b-9947-5837-bc3d-b08a911897a1", + "title": "article 262 vector node" + }, + { + "$id": "5e20ba2a-e7f3-5cf1-8515-7d74da53ab9f", + "title": "article 282 filter vector" + }, + { + "$id": "568019d7-fa21-5d7b-98a7-126890f32e51", + "title": "article 341 node index" + }, + { + "$id": "97bf6379-894b-5304-a05d-dc88e2efb96d", + "title": "article 334 quantize filter" + }, + { + "$id": "adbe9c20-828e-5543-ab79-5fe3cd27be37", + "title": "article 224 vector shard" + }, + { + "$id": "b181572c-0cdf-5f13-bde8-87fd7f1ce823", + "title": "article 328 filter property" + }, + { + "$id": "e66f149e-51db-5bdb-afb2-d0fb6d47873d", + "title": "article 164 keyword node" + }, + { + "$id": "9cd5f0ba-baff-56a1-a2a9-053ebc89309e", + "title": "article 403 search schema" + }, + { + "$id": "d84aef74-a1a2-5534-964c-4f2f13f5b040", + "title": "article 463 keyword cosine" + }, + { + "$id": "df43df7f-7493-5b64-b8d1-03be6a838dd8", + "title": "article 037 object node" + }, + { + "$id": "109ab621-699c-521a-a71d-8761665a0fd2", + "title": "article 240 filter keyword" + }, + { + "$id": "11910949-1a12-5d12-9c1c-015c150aa53c", + "title": "article 257 property graph" + }, + { + "$id": "154cade8-3800-54f7-86bf-11940efda50c", + "title": "article 063 replica keyword" + }, + { + "$id": "15a7167f-5614-5907-9c37-6ec7ac2faec3", + "title": "article 242 cosine shard" + }, + { + "$id": "15b9b024-cbbe-506e-8cc6-b547ef29d366", + "title": "article 427 engine object" + }, + { + "$id": "3bf3c3da-3b9d-586e-be52-058c017d408b", + "title": "article 034 cosine replica" + }, + { + "$id": "675a3068-3c33-5279-937b-a1e55d8858e5", + "title": "article 043 shard tenant" + }, + { + "$id": "71ad2be0-c4cb-5d55-ae14-45aaea14f4a9", + "title": "article 245 property shard" + }, + { + "$id": "83a602fc-404e-56fb-9faf-f9405e6f50eb", + "title": "article 426 cosine recall" + }, + { + "$id": "9eeef104-fb18-58a8-83ef-63db7229b331", + "title": "article 156 index hybrid" + }, + { + "$id": "aa03ca5a-de8c-5f92-b16e-f9e2c32edb5d", + "title": "article 385 hybrid cosine" + }, + { + "$id": "b32a7a72-6389-5bb4-9947-49abf9b9cd91", + "title": "article 278 shard engine" + }, + { + "$id": "c7a72ea7-5103-5ef4-b0b7-94052e81e528", + "title": "article 129 cosine tenant" + }, + { + "$id": "efe60c07-cd04-5435-955b-e0f657176bae", + "title": "article 324 tenant alias" + }, + { + "$id": "c9985312-f531-5ed2-a0f4-c4f070fcaffa", + "title": "article 492 search node" + }, + { + "$id": "00139992-3118-5ccc-bfac-42062afb1418", + "title": "article 042 index search" + }, + { + "$id": "16f723f0-5c76-5f11-9cae-c8d970510c4a", + "title": "article 023 shard search" + }, + { + "$id": "2716ffdb-f678-5f5e-a25b-7597d419a8f6", + "title": "article 040 shard graph" + }, + { + "$id": "28a5ee00-944b-5fbe-bb71-775ef97aae95", + "title": "article 024 filter vector" + }, + { + "$id": "30c49f98-46cc-51c8-9364-f0f544bd99f3", + "title": "article 161 object quantize" + }, + { + "$id": "3968998f-7416-5e44-a02b-3d4f6a76d28d", + "title": "article 047 hybrid property" + }, + { + "$id": "3b5e188a-dba4-551c-a4c2-2743202df1bb", + "title": "article 189 schema property" + }, + { + "$id": "4d89b5b1-1efa-561a-add6-06731ea73da5", + "title": "article 197 keyword node" + }, + { + "$id": "4e9f48c4-d174-52ff-becc-c2d72ea4fcde", + "title": "article 128 replica object" + }, + { + "$id": "536bc3a8-9bff-5042-bfb2-f9d9cbecc250", + "title": "article 066 shard object" + }, + { + "$id": "69b31860-8732-512f-aef1-79d35b48ed84", + "title": "article 244 cosine engine" + }, + { + "$id": "754bf866-c2db-5a9b-929e-f69ba6555b80", + "title": "article 185 search filter" + }, + { + "$id": "8d4e0b7b-e646-5fce-8c75-448bded66eb1", + "title": "article 044 quantize object" + }, + { + "$id": "a8212a0a-ba71-5ab9-9408-9158262a5711", + "title": "article 202 index tenant" + }, + { + "$id": "a8eadb65-e8e1-5db4-b088-9bae6988ee67", + "title": "article 144 collection graph" + }, + { + "$id": "a9d0efad-a959-552b-b65a-fda42cdbe2cd", + "title": "article 117 collection graph" + }, + { + "$id": "b3c2ed60-4a50-5b93-97f3-d379133c266c", + "title": "article 237 replica object" + }, + { + "$id": "b5391a2a-6084-55bd-ad80-c17ce6392439", + "title": "article 174 quantize tenant" + }, + { + "$id": "d976ca88-a069-5460-a816-70339070c4ce", + "title": "article 029 filter property" + }, + { + "$id": "fb3cde60-51fc-5a23-b3cd-5914001d0b7b", + "title": "article 264 recall quantize" + } + ], + "rowCount": 50, + "columnTypes": { + "$id": "uuid" + }, + "warnings": [ + { + "message": "Answered via REST search." + } + ] + } + } + ] +} diff --git a/tests/fixtures/weaviate/weaviate/surface.json b/tests/fixtures/weaviate/weaviate/surface.json new file mode 100644 index 0000000000..42c5648e8b --- /dev/null +++ b/tests/fixtures/weaviate/weaviate/surface.json @@ -0,0 +1,1708 @@ +{ + "$captured": { + "engine": "weaviate", + "service": "weaviate", + "scenario": "surface", + "image": "cr.weaviate.io/semitechnologies/weaviate:1.40.2", + "digest": "sha256:0083587dc01f33112e5406ce9b471df1abea480c71a0407af903929a389ae08a", + "version": "1.40.2", + "date": "2026-10-23T23:54:52.335Z", + "runtime": "bun 1.4.2", + "credential": "none" + }, + "transport": [ + { + "origin": "http://127.0.0.1:18280", + "tls": null, + "maxSockets": 4, + "headers": {} + } + ], + "exchanges": [ + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Article&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Article\",\"creationTimeUnix\":1792754764912,\"id\":\"00139992-3118-5ccc-bfac-42062afb1418\",\"lastUpdateTimeUnix\":1792754764912,\"properties\":{\"body\":\"engine shard tenant cosine recall filter schema quantize tenant hybrid vector cosine\",\"category\":\"gamma\",\"location\":{\"latitude\":59.479,\"longitude\":24.7536},\"meta\":{\"revision\":2,\"source\":\"seed\"},\"published\":false,\"publishedAt\":\"2026-10-01T12:00:00Z\",\"rating\":0.42,\"tags\":[\"replica\",\"schema\",\"shard\"],\"title\":\"article 042 index search\",\"wordCount\":142,\"writtenBy\":[{\"beacon\":\"weaviate://localhost/Author/c658ec06-90f5-53a8-9ff0-289860643683\",\"href\":\"/v1/objects/Author/c658ec06-90f5-53a8-9ff0-289860643683\"}]},\"vector\":[0.090872,-0.268579,0.799546,0.963254,0.140379,0.019355,-0.921561,0.336068,-0.831569,0.932756,-0.881524,0.622357,-0.189283,0.105446,0.013549,0.315139],\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Product&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Product\",\"creationTimeUnix\":1792754765214,\"id\":\"017df454-5e7d-575f-a30b-81ab587ab05f\",\"lastUpdateTimeUnix\":1792754765214,\"properties\":{\"name\":\"product 087\",\"price\":22.75,\"sku\":\"d73893f9-6387-5361-8190-44281f1fa3c9\"},\"vectorWeights\":null,\"vectors\":{\"image\":[-0.004234,0.925485,0.143918,-0.16418,0.567372,0.745523,0.214667,-0.240875],\"text\":[-0.095434,-0.084195,0.446122,-0.414162,-0.218631,0.110703,-0.230998,-0.356012,0.574156,0.699133,-0.0009,-0.111938,-0.631577,-0.391935,-0.710019,0.150866]}}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Author", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Author&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[{\"class\":\"Author\",\"creationTimeUnix\":1792754764874,\"id\":\"03a2e87a-c828-5d72-ba13-fee221989fe9\",\"lastUpdateTimeUnix\":1792754764874,\"properties\":{\"country\":\"DE\",\"name\":\"author 02\"},\"vectorWeights\":null}],\"totalResults\":1}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/objects?class=Empty&limit=1&include=vector", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"deprecations\":[],\"objects\":[]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Article/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"PqZ7DmG5G0U9\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Product/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"VC0BMTbIis9m\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Product", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":200,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotes/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"HOT\",\"name\":\"acme\"},{\"activityStatus\":\"HOT\",\"name\":\"globex\"},{\"activityStatus\":\"COLD\",\"name\":\"initech\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/TenantNotesAuto/tenants", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"activityStatus\":\"COLD\",\"name\":\"umbrella\"},{\"activityStatus\":\"HOT\",\"name\":\"hooli\"}]\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/aliases", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"aliases\":[{\"alias\":\"Articles\",\"class\":\"Article\"}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema/Empty/shards", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "[{\"name\":\"2nk4zUrnyCFk\",\"per_node_status\":{\"node1\":\"READY\"},\"status\":\"READY\",\"vectorQueueSize\":0}]\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/.well-known/ready", + "body": null, + "answer": { + "status": 200, + "contentType": null, + "retryAfter": null, + "text": "" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/meta", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"grpcMaxMessageSize\":104858000,\"hostname\":\"http://[::]:8080\",\"license\":{\"documentationHref\":\"https://docs.weaviate.io/deploy/enterprise\",\"edition\":\"community\"},\"modules\":{},\"version\":\"1.40.2\"}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Article", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":500,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Author", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":12,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/EdgeValues", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":8,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Empty", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":0,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "POST", + "path": "/v1/aggregate/Product", + "body": "{}", + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"count\":200,\"tookMs\":0}\n" + }, + "thrown": null + }, + { + "method": "GET", + "path": "/v1/schema", + "body": null, + "answer": { + "status": 200, + "contentType": "application/json", + "retryAfter": null, + "text": "{\"classes\":[{\"class\":\"Author\",\"description\":\"objects with no vector at all\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"country\",\"tokenization\":\"field\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotesAuto\",\"description\":\"multi-tenant with autoTenantActivation on\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":true,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"TenantNotes\",\"description\":\"multi-tenant, a read does not activate a tenant\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":true},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"note\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"seq\"}],\"shardingConfig\":{\"actualCount\":0,\"actualVirtualCount\":0,\"desiredCount\":0,\"desiredVirtualCount\":0,\"function\":\"\",\"key\":\"\",\"strategy\":\"\",\"virtualPerPhysical\":0},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"EdgeValues\",\"description\":\"int64 values a float64 cannot hold, one object per value\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"big\"},{\"dataType\":[\"int[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"bigs\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Article\",\"description\":\"one unnamed vector, a cross-reference and the common property types\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"indexTimestamps\":true,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"title\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"body\",\"tokenization\":\"word\"},{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"category\",\"tokenization\":\"field\"},{\"dataType\":[\"text[]\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"tags\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"wordCount\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"rating\"},{\"dataType\":[\"boolean\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"published\"},{\"dataType\":[\"date\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"publishedAt\"},{\"dataType\":[\"geoCoordinates\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"location\"},{\"dataType\":[\"object\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"meta\",\"nestedProperties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"source\",\"tokenization\":\"word\"},{\"dataType\":[\"int\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"revision\"}]},{\"dataType\":[\"Author\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"writtenBy\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Empty\",\"description\":\"no objects\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"label\",\"tokenization\":\"word\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":\"none\",\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}},{\"class\":\"Product\",\"description\":\"two named vectors with different dimensions and distances\",\"invertedIndexConfig\":{\"bm25\":{\"b\":0.75,\"k1\":1.2},\"cleanupIntervalSeconds\":60,\"stopwords\":{\"additions\":null,\"preset\":\"en\",\"removals\":null},\"usingBlockMaxWAND\":true},\"multiTenancyConfig\":{\"autoTenantActivation\":false,\"autoTenantCreation\":false,\"enabled\":false},\"properties\":[{\"dataType\":[\"text\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":true,\"name\":\"name\",\"tokenization\":\"word\"},{\"dataType\":[\"number\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"price\"},{\"dataType\":[\"uuid\"],\"indexFilterable\":true,\"indexRangeFilters\":false,\"indexSearchable\":false,\"name\":\"sku\"}],\"shardingConfig\":{\"actualCount\":1,\"actualVirtualCount\":128,\"desiredCount\":1,\"desiredVirtualCount\":128,\"function\":\"murmur3\",\"key\":\"_id\",\"strategy\":\"hash\",\"virtualPerPhysical\":128},\"vectorConfig\":{\"image\":{\"vectorIndexConfig\":{\"bq\":{\"enabled\":false},\"cleanupIntervalSeconds\":300,\"distance\":\"cosine\",\"dynamicEfFactor\":8,\"dynamicEfMax\":500,\"dynamicEfMin\":100,\"ef\":-1,\"efConstruction\":128,\"filterStrategy\":\"acorn\",\"flatSearchCutoff\":40000,\"maxConnections\":32,\"multivector\":{\"aggregation\":\"maxSim\",\"enabled\":false,\"muvera\":{\"dprojections\":16,\"enabled\":false,\"ksim\":4,\"repetitions\":10}},\"pq\":{\"bitCompression\":false,\"centroids\":256,\"enabled\":false,\"encoder\":{\"distribution\":\"log-normal\",\"type\":\"kmeans\"},\"segments\":0,\"trainingLimit\":100000},\"rq\":{\"bits\":8,\"centering\":false,\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":10000},\"skip\":false,\"skipDefaultQuantization\":false,\"sq\":{\"enabled\":false,\"rescoreLimit\":20,\"trainingLimit\":100000},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"hnsw\",\"vectorizer\":{\"none\":{}}},\"text\":{\"vectorIndexConfig\":{\"bq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"distance\":\"dot\",\"pq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"rq\":{\"bits\":8,\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"skipDefaultQuantization\":false,\"sq\":{\"cache\":false,\"enabled\":false,\"rescoreLimit\":-1},\"trackDefaultQuantization\":false,\"vectorCacheMaxObjects\":1000000000000},\"vectorIndexType\":\"flat\",\"vectorizer\":{\"none\":{}}}},\"replicationConfig\":{\"deletionStrategy\":\"TimeBasedResolution\",\"factor\":1,\"asyncEnabled\":false}}]}\n" + }, + "thrown": null + } + ], + "outcomes": [ + { + "step": "connect", + "value": null + }, + { + "step": "connectWarnings", + "value": [] + }, + { + "step": "listContainers", + "value": [] + }, + { + "step": "countObjects", + "value": { + "collection": { + "count": 7 + } + } + }, + { + "step": "listObjects", + "value": [ + { + "path": [ + "Article" + ], + "name": "Article", + "kind": "collection" + }, + { + "path": [ + "Author" + ], + "name": "Author", + "kind": "collection" + }, + { + "path": [ + "EdgeValues" + ], + "name": "EdgeValues", + "kind": "collection" + }, + { + "path": [ + "Empty" + ], + "name": "Empty", + "kind": "collection" + }, + { + "path": [ + "Product" + ], + "name": "Product", + "kind": "collection" + }, + { + "path": [ + "TenantNotes" + ], + "name": "TenantNotes", + "kind": "collection" + }, + { + "path": [ + "TenantNotesAuto" + ], + "name": "TenantNotesAuto", + "kind": "collection" + } + ] + }, + { + "step": "describeObjects", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "EdgeValues" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "big", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "bigs", + "type": "int[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(?, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "TenantNotesAuto" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ] + } + }, + { + "step": "describeObjects limit 2", + "value": { + "details": [ + { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + }, + { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + ], + "truncated": { + "limit": 2, + "reason": "the bulk column read was bounded at 2 objects by its caller" + } + } + }, + { + "step": "describeObject Article", + "value": { + "path": [ + "Article" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "title", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "body", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "category", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "tags", + "type": "text[]", + "nullable": true, + "isPrimary": false + }, + { + "name": "wordCount", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "rating", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "published", + "type": "boolean", + "nullable": true, + "isPrimary": false + }, + { + "name": "publishedAt", + "type": "date", + "nullable": true, + "isPrimary": false + }, + { + "name": "location", + "type": "geoCoordinates", + "nullable": true, + "isPrimary": false + }, + { + "name": "meta", + "type": "object", + "nullable": true, + "isPrimary": false + }, + { + "name": "writtenBy", + "type": "ref → Author", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(16, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Product", + "value": { + "path": [ + "Product" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "price", + "type": "number", + "nullable": true, + "isPrimary": false + }, + { + "name": "sku", + "type": "uuid", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.image", + "type": "Vector(8, cosine, hnsw)", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector.text", + "type": "Vector(16, dot, flat)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector.image", + "columns": [ + "$vector.image" + ], + "unique": false + }, + { + "name": "$vector.text", + "columns": [ + "$vector.text" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Author", + "value": { + "path": [ + "Author" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "name", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "country", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "note", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "seq", + "type": "int", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "describeObject Empty", + "value": { + "path": [ + "Empty" + ], + "columns": [ + { + "name": "$id", + "type": "uuid", + "nullable": false, + "isPrimary": true + }, + { + "name": "label", + "type": "text", + "nullable": true, + "isPrimary": false + }, + { + "name": "$vector", + "type": "Vector(?, cosine, hnsw)", + "nullable": true, + "isPrimary": false + } + ], + "indexes": [ + { + "name": "$vector", + "columns": [ + "$vector" + ], + "unique": false + } + ], + "foreignKeys": [] + } + }, + { + "step": "readObjectSource Article", + "value": { + "path": [ + "Article" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Article\",\n \"description\": \"one unnamed vector, a cross-reference and the common property types\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"indexTimestamps\": true,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"title\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"body\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"category\",\n \"tokenization\": \"field\"\n },\n {\n \"dataType\": [\n \"text[]\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"tags\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"wordCount\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"rating\"\n },\n {\n \"dataType\": [\n \"boolean\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"published\"\n },\n {\n \"dataType\": [\n \"date\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"publishedAt\"\n },\n {\n \"dataType\": [\n \"geoCoordinates\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"location\"\n },\n {\n \"dataType\": [\n \"object\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"meta\",\n \"nestedProperties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"source\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"revision\"\n }\n ]\n },\n {\n \"dataType\": [\n \"Author\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"writtenBy\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [\n \"Articles\"\n ],\n \"shards\": [\n {\n \"name\": \"PqZ7DmG5G0U9\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 500,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Product", + "value": { + "path": [ + "Product" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Product\",\n \"description\": \"two named vectors with different dimensions and distances\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"name\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"number\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"price\"\n },\n {\n \"dataType\": [\n \"uuid\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"sku\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorConfig\": {\n \"image\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": {\n \"none\": {}\n }\n },\n \"text\": {\n \"vectorIndexConfig\": {\n \"bq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"distance\": \"dot\",\n \"pq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"rq\": {\n \"bits\": 8,\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"cache\": false,\n \"enabled\": false,\n \"rescoreLimit\": -1\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"flat\",\n \"vectorizer\": {\n \"none\": {}\n }\n }\n },\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"VC0BMTbIis9m\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 200,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotes", + "value": { + "path": [ + "TenantNotes" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotes\",\n \"description\": \"multi-tenant, a read does not activate a tenant\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": false,\n \"aliases\": [],\n \"tenantCount\": 3,\n \"tenants\": [\n {\n \"name\": \"acme\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"globex\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"initech\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource TenantNotesAuto", + "value": { + "path": [ + "TenantNotesAuto" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"TenantNotesAuto\",\n \"description\": \"multi-tenant with autoTenantActivation on\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": true,\n \"autoTenantCreation\": false,\n \"enabled\": true\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"note\",\n \"tokenization\": \"word\"\n },\n {\n \"dataType\": [\n \"int\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": false,\n \"name\": \"seq\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 0,\n \"actualVirtualCount\": 0,\n \"desiredCount\": 0,\n \"desiredVirtualCount\": 0,\n \"function\": \"\",\n \"key\": \"\",\n \"strategy\": \"\",\n \"virtualPerPhysical\": 0\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": true,\n \"autoTenantActivation\": true,\n \"aliases\": [],\n \"tenantCount\": 2,\n \"tenants\": [\n {\n \"name\": \"hooli\",\n \"activityStatus\": \"HOT\"\n },\n {\n \"name\": \"umbrella\",\n \"activityStatus\": \"COLD\"\n }\n ],\n \"objectCount\": \"Per-tenant counts are not read here: run POST /v1/aggregate/ {\\\"tenant\\\": \\\"\\\"} for one HOT tenant.\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "readObjectSource Empty", + "value": { + "path": [ + "Empty" + ], + "kind": "collection", + "parts": [ + { + "id": "schema", + "label": "Schema", + "text": "{\n \"class\": \"Empty\",\n \"description\": \"no objects\",\n \"invertedIndexConfig\": {\n \"bm25\": {\n \"b\": 0.75,\n \"k1\": 1.2\n },\n \"cleanupIntervalSeconds\": 60,\n \"stopwords\": {\n \"additions\": null,\n \"preset\": \"en\",\n \"removals\": null\n },\n \"usingBlockMaxWAND\": true\n },\n \"multiTenancyConfig\": {\n \"autoTenantActivation\": false,\n \"autoTenantCreation\": false,\n \"enabled\": false\n },\n \"properties\": [\n {\n \"dataType\": [\n \"text\"\n ],\n \"indexFilterable\": true,\n \"indexRangeFilters\": false,\n \"indexSearchable\": true,\n \"name\": \"label\",\n \"tokenization\": \"word\"\n }\n ],\n \"shardingConfig\": {\n \"actualCount\": 1,\n \"actualVirtualCount\": 128,\n \"desiredCount\": 1,\n \"desiredVirtualCount\": 128,\n \"function\": \"murmur3\",\n \"key\": \"_id\",\n \"strategy\": \"hash\",\n \"virtualPerPhysical\": 128\n },\n \"vectorIndexConfig\": {\n \"bq\": {\n \"enabled\": false\n },\n \"cleanupIntervalSeconds\": 300,\n \"distance\": \"cosine\",\n \"dynamicEfFactor\": 8,\n \"dynamicEfMax\": 500,\n \"dynamicEfMin\": 100,\n \"ef\": -1,\n \"efConstruction\": 128,\n \"filterStrategy\": \"acorn\",\n \"flatSearchCutoff\": 40000,\n \"maxConnections\": 32,\n \"multivector\": {\n \"aggregation\": \"maxSim\",\n \"enabled\": false,\n \"muvera\": {\n \"dprojections\": 16,\n \"enabled\": false,\n \"ksim\": 4,\n \"repetitions\": 10\n }\n },\n \"pq\": {\n \"bitCompression\": false,\n \"centroids\": 256,\n \"enabled\": false,\n \"encoder\": {\n \"distribution\": \"log-normal\",\n \"type\": \"kmeans\"\n },\n \"segments\": 0,\n \"trainingLimit\": 100000\n },\n \"rq\": {\n \"bits\": 8,\n \"centering\": false,\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 10000\n },\n \"skip\": false,\n \"skipDefaultQuantization\": false,\n \"sq\": {\n \"enabled\": false,\n \"rescoreLimit\": 20,\n \"trainingLimit\": 100000\n },\n \"trackDefaultQuantization\": false,\n \"vectorCacheMaxObjects\": 1000000000000\n },\n \"vectorIndexType\": \"hnsw\",\n \"vectorizer\": \"none\",\n \"replicationConfig\": {\n \"deletionStrategy\": \"TimeBasedResolution\",\n \"factor\": 1,\n \"asyncEnabled\": false\n }\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + }, + { + "id": "state", + "label": "State", + "text": "{\n \"multiTenant\": false,\n \"aliases\": [],\n \"shards\": [\n {\n \"name\": \"2nk4zUrnyCFk\",\n \"status\": \"READY\",\n \"vectorQueueSize\": 0\n }\n ],\n \"objectCount\": 0,\n \"objectCountKind\": \"exact, aggregate meta.count\"\n}", + "language": "json", + "form": "complete", + "origin": "rendered" + } + ] + } + }, + { + "step": "getHealth", + "value": { + "databaseSize": "N/A", + "cacheHitRatio": "N/A", + "slowQueries": [], + "activeSessions": [] + } + }, + { + "step": "getOverview", + "value": { + "version": "1.40.2", + "uptime": "N/A", + "maxConnections": 0, + "databaseSize": "N/A", + "tableCount": 7, + "indexCount": 8 + } + }, + { + "step": "getTableStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "rowCount": 500, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "rowCount": 12, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "rowCount": 8, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "rowCount": 0, + "totalSize": "N/A", + "totalSizeBytes": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "rowCount": 200, + "totalSize": "N/A", + "totalSizeBytes": 0 + } + ] + }, + { + "step": "getIndexStats", + "value": [ + { + "schemaName": "", + "tableName": "Article", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Author", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "EdgeValues", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Empty", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.image", + "indexType": "hnsw, cosine", + "columns": [ + "$vector.image" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "Product", + "indexName": "$vector.text", + "indexType": "flat, dot", + "columns": [ + "$vector.text" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotes", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + }, + { + "schemaName": "", + "tableName": "TenantNotesAuto", + "indexName": "$vector", + "indexType": "hnsw, cosine", + "columns": [ + "$vector" + ], + "isUnique": false, + "isPrimary": false, + "indexSize": "N/A", + "scans": 0 + } + ] + } + ] +} diff --git a/tests/helpers/census-connection.ts b/tests/helpers/census-connection.ts index bc0d31e27d..63699f2561 100644 --- a/tests/helpers/census-connection.ts +++ b/tests/helpers/census-connection.ts @@ -85,6 +85,7 @@ export const CENSUS_CONNECTION: Readonly weaviatePhase0(parseWeaviateRequest(text)); + +/** The body phase 0 hands on, as JSON text. */ +export const bodyText = (text: string): string | null => { + const body = plan(text).body; + return body === null ? null : toJsonText(body); +}; + +export const searchOf = (text: string): WeaviateSearchModel => plan(text).search as WeaviateSearchModel; + +/** The refusal a call throws; anything else, or no throw, fails the test. */ +export function refusalOf(run: () => unknown): RequestRefusal { + try { + run(); + } catch (error) { + if (error instanceof RequestRefusal) return error; + throw error; + } + throw new Error("accepted"); +} + +/** Phase 0's refusal of a text, as the three facts a test compares. */ +export function refused(text: string): { phase: number; key: string | null; message: string } { + const error = refusalOf(() => plan(text)); + return { phase: error.phase, key: error.key, message: error.message }; +} + +interface RecordedExchange { + readonly method: string; + readonly path: string; + readonly body: string | null; + readonly answer: { readonly status: number; readonly text: string } | null; +} + +const FIXTURES = join(import.meta.dir, "..", "fixtures", "weaviate"); + +export function recordedExchanges(service: string, file: string): readonly RecordedExchange[] { + return ( + JSON.parse(readFileSync(join(FIXTURES, service, `${file}.json`), "utf8")) as { exchanges: RecordedExchange[] } + ).exchanges; +} + +/** A collection's facts as the seeded server's `GET /v1/schema` described it: Article, Product, TenantNotes, ... */ +export function recordedFacts(collection: string): WeaviateCollectionFacts { + const exchange = recordedExchanges("weaviate", "surface").find( + (entry) => entry.method === "GET" && entry.path === "/v1/schema" && entry.answer?.status === 200, + ); + const found = readWeaviateSchema(JSON.parse(exchange?.answer?.text ?? "{}")).find( + (definition) => definition.name === collection, + ); + if (found === undefined) throw new Error(`no recorded definition of ${collection}`); + return weaviateCollectionFacts(found); +} + +/** Every distinct GraphQL body the 1.37.4 server answered, in the order first sent, across its records. */ +export function recordedGraphqlBodies(): readonly string[] { + const bodies = ["searches", "surface", "reads"].flatMap((file) => + recordedExchanges("weaviate-1-37", file) + .filter((entry) => entry.path === "/v1/graphql" && entry.body !== null) + .map((entry) => entry.body as string), + ); + return [...new Set(bodies)]; +} + +const vector = (name: string, vectorizer = "none"): WeaviateVector => ({ + name, + vectorizer, + indexType: "hnsw", + distance: "cosine", + quantization: null, +}); + +/** Facts written by hand: plain text properties, the vectors named, and optionally a reference and tenancy. */ +export function handFacts(options: { + readonly name?: string; + readonly vectors?: readonly (string | readonly [string, string])[]; + readonly properties?: readonly string[]; + readonly references?: readonly string[]; + readonly multiTenant?: boolean; +}): WeaviateCollectionFacts { + const properties = options.properties ?? ["title"]; + return { + name: options.name ?? "Doc", + multiTenant: options.multiTenant ?? false, + autoTenantActivation: false, + vectors: (options.vectors ?? [""]).map((entry) => + typeof entry === "string" ? vector(entry) : vector(entry[0], entry[1]), + ), + selections: new Map(properties.map((name) => [name, { name }])), + plainProperties: properties, + intProperties: new Set(), + referenceProperties: new Set(options.references ?? []), + }; +} diff --git a/tests/helpers/weaviate-scenario.ts b/tests/helpers/weaviate-scenario.ts new file mode 100644 index 0000000000..6b18d022aa --- /dev/null +++ b/tests/helpers/weaviate-scenario.ts @@ -0,0 +1,239 @@ +/** + * What the Weaviate evidence harness and the integration test share (#1566 spec 7.3): the connection a scenario of + * tests/live/weaviate-scenarios.ts opens, the provider calls it makes, how an outcome is written down, and the two + * transports, one that records what a live server answered and one that answers from that record. + * + * An outcome keeps what the user is shown: a result's fields, rows, count and warnings, a surface call's value, or an + * error's class and message. The run time is dropped, since it differs on every run and nothing is decided by it. + */ +import type { NodeRequest, NodeResponse, NodeTransport, NodeTransportOptions } from "@/lib/db/http/node-transport"; +import { TransportError } from "@/lib/db/http/node-transport"; +import { WeaviateProvider } from "@/lib/db/providers/vector/weaviate"; +import { createRestWeaviateClient } from "@/lib/db/providers/vector/weaviate/rest-client"; +import type { DatabaseConnection, QueryResult } from "@/lib/types"; +import { + WEAVIATE_SERVICES, + type WeaviateCredential, + type WeaviateScenario, + type WeaviateStep, +} from "../live/weaviate-scenarios"; + +/** The credential values a scenario's connection carries. A replay uses stand-ins, a live run the real keys. */ +export interface WeaviateSecrets { + readonly root: string; + readonly reader: string; + readonly wrong: string; + /** The PEM of the CA weaviate-tls's certificate chains to. */ + readonly ca: string; +} + +/** What a replay sends in place of a key: the record holds no key, so no value is compared. */ +export const REPLAY_SECRETS: WeaviateSecrets = { + root: "replay-root-key", + reader: "replay-reader-key", + wrong: "replay-wrong-key", + ca: "-----BEGIN CERTIFICATE-----\nreplay\n-----END CERTIFICATE-----\n", +}; + +function keyOf(credential: WeaviateCredential, secrets: WeaviateSecrets): string | undefined { + return credential === "none" ? undefined : secrets[credential]; +} + +/** The connection a scenario opens, the same in a live run and in its replay but for the secrets. */ +export function scenarioConnection(scenario: WeaviateScenario, secrets: WeaviateSecrets): DatabaseConnection { + const service = WEAVIATE_SERVICES[scenario.service]; + const password = keyOf(scenario.credential, secrets); + return { + id: `weaviate-${scenario.service}-${scenario.name}`, + name: `${scenario.service} ${scenario.name}`, + type: "weaviate", + host: "127.0.0.1", + port: service.port, + ...(password === undefined ? {} : { password }), + ...(scenario.ssl === "verify-ca" ? { ssl: { mode: "verify-ca", caCert: secrets.ca } } : {}), + ...(scenario.ssl === "disable" ? { ssl: { mode: "disable" } } : {}), + ...(scenario.readOnly === true ? { readOnly: true, managed: true } : {}), + } as DatabaseConnection; +} + +/** One request as the provider put it on the wire, and what came back: an answer, or the error the transport threw. */ +export interface WeaviateExchange { + readonly method: "GET" | "POST"; + /** The path and query, without the origin. */ + readonly path: string; + readonly body: string | null; + readonly answer: NodeResponse | null; + readonly thrown: { readonly kind: TransportError["kind"]; readonly message: string } | null; +} + +export type WeaviateOutcome = + | { readonly step: string; readonly value: unknown } + | { readonly step: string; readonly error: { readonly name: string; readonly message: string } }; + +function pathOf(request: NodeRequest): string { + const url = new URL(request.url); + return `${url.pathname}${url.search}`; +} + +/** A transport that hands each request to `inner` and writes the exchange down, a thrown error included. */ +export function recordingTransport( + inner: (options: NodeTransportOptions) => NodeTransport, + exchanges: WeaviateExchange[], + built: NodeTransportOptions[], +): (options: NodeTransportOptions) => NodeTransport { + return (options) => { + built.push(options); + const transport = inner(options); + return { + async request(request) { + const entry = { method: request.method, path: pathOf(request), body: request.body ?? null }; + try { + const answer = await transport.request(request); + exchanges.push({ ...entry, answer, thrown: null }); + return answer; + } catch (error) { + const thrown = + error instanceof TransportError + ? { kind: error.kind, message: error.message } + : { kind: "network" as const, message: (error as Error).message }; + exchanges.push({ ...entry, answer: null, thrown }); + throw error; + } + }, + close() { + transport.close(); + }, + }; + }; +} + +/** + * A transport that answers from a record: each request must equal, method, path and body, an exchange not yet used, + * and gets that exchange's answer or error. Requests sent at once may arrive in any order, so the match is by value, + * never by position. A request the record does not hold throws by name, and `unused()` lists what was never asked. + */ +export function replayTransport(record: readonly WeaviateExchange[]): { + readonly factory: (options: NodeTransportOptions) => NodeTransport; + readonly sent: WeaviateExchange[]; + readonly built: NodeTransportOptions[]; + unused(): readonly WeaviateExchange[]; +} { + const pending = [...record]; + const sent: WeaviateExchange[] = []; + const built: NodeTransportOptions[] = []; + const factory = (options: NodeTransportOptions): NodeTransport => { + built.push(options); + return { + async request(request) { + const path = pathOf(request); + const body = request.body ?? null; + const index = pending.findIndex( + (exchange) => exchange.method === request.method && exchange.path === path && exchange.body === body, + ); + if (index < 0) throw new Error(`no recorded exchange answers ${request.method} ${path} ${body ?? ""}`); + const [exchange] = pending.splice(index, 1); + sent.push(exchange); + if (exchange.thrown !== null) throw new TransportError(exchange.thrown.kind, exchange.thrown.message); + return exchange.answer as NodeResponse; + }, + close() {}, + }; + }; + return { factory, sent, built, unused: () => pending }; +} + +/** A provider over the given transport, built as the factory builds one. */ +export function scenarioProvider( + connection: DatabaseConnection, + transport: (options: NodeTransportOptions) => NodeTransport, +): WeaviateProvider { + return new WeaviateProvider(connection, {}, {}, (options, routes) => + createRestWeaviateClient(options, routes, transport), + ); +} + +function resultOf(result: QueryResult): unknown { + return { + fields: result.fields, + rows: result.rows, + rowCount: result.rowCount, + ...(result.columnTypes === undefined ? {} : { columnTypes: result.columnTypes }), + ...(result.vectorColumns === undefined ? {} : { vectorColumns: result.vectorColumns }), + ...(result.resultSets === undefined ? {} : { resultSets: result.resultSets }), + ...(result.warnings === undefined ? {} : { warnings: result.warnings }), + ...(result.pagination === undefined ? {} : { pagination: result.pagination }), + }; +} + +function stepName(step: WeaviateStep): string { + if (step.call === "query") return `query ${step.text}`; + if (step.call === "describeObject" || step.call === "readObjectSource") return `${step.call} ${step.name}`; + if (step.call === "describeObjects" && step.limit !== undefined) return `describeObjects limit ${step.limit}`; + return step.call; +} + +async function callOf(provider: WeaviateProvider, step: WeaviateStep): Promise { + switch (step.call) { + case "query": + return resultOf(await provider.query(step.text)); + case "listContainers": + return provider.listContainers(); + case "countObjects": + return provider.countObjects([]); + case "listObjects": + return provider.listObjects([], "collection"); + case "describeObject": + return provider.describeObject([step.name], "collection"); + case "describeObjects": + return provider.describeObjects([], "collection", step.limit); + case "readObjectSource": + return provider.readObjectSource([step.name], "collection"); + case "getHealth": { + const { responseTime: _responseTime, ...health } = (await provider.getHealth()) as unknown as Record< + string, + unknown + >; + return health; + } + case "getOverview": + return provider.getOverview(); + case "getTableStats": + return provider.getTableStats(); + case "getIndexStats": + return provider.getIndexStats(); + case "connectWarnings": + return provider.connectWarnings(); + } +} + +function errorOf(step: string, error: unknown): WeaviateOutcome { + const thrown = error as Error; + return { step, error: { name: thrown.constructor.name, message: thrown.message } }; +} + +/** + * Connects, makes every call in order and disconnects, writing down each outcome; a failed connect is the only + * outcome, since nothing else can run. JSON round-trips each value so a live run and a replay compare as text does. + */ +export async function runScenario( + provider: WeaviateProvider, + steps: readonly WeaviateStep[], +): Promise { + const outcomes: WeaviateOutcome[] = []; + try { + await provider.connect(); + } catch (error) { + return [errorOf("connect", error)]; + } + outcomes.push({ step: "connect", value: null }); + for (const step of steps) { + const name = stepName(step); + try { + outcomes.push({ step: name, value: JSON.parse(JSON.stringify((await callOf(provider, step)) ?? null)) }); + } catch (error) { + outcomes.push(errorOf(name, error)); + } + } + await provider.disconnect(); + return outcomes; +} diff --git a/tests/helpers/weaviate-surface.ts b/tests/helpers/weaviate-surface.ts new file mode 100644 index 0000000000..03283df6bf --- /dev/null +++ b/tests/helpers/weaviate-surface.ts @@ -0,0 +1,220 @@ +/** + * What the Weaviate unit tests share (#1566 spec 3.1, 7.3): the answers the captures under tests/fixtures/weaviate/ + * hold, looked up by the request Studio would put on the wire, and a fake client that records every request it is + * sent and answers from a function a test writes. + * + * A captured answer is found by method, path and body through the real REST client, so a request is matched as + * `rest-client.ts` spells it; unlike the replay transport of weaviate-scenario.ts, an exchange may be asked for + * again, and a request the capture does not hold throws by name. + */ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import type { NodeTransport } from "@/lib/db/http/node-transport"; +import type { + WeaviateAnswer, + WeaviateClient, + WeaviateOp, + WeaviateRequest, +} from "@/lib/db/providers/vector/weaviate/client"; +import { + buildWeaviateConnectionOptions, + type WeaviateConnectionOptions, +} from "@/lib/db/providers/vector/weaviate/connection-options"; +import type { WeaviatePathState } from "@/lib/db/providers/vector/weaviate/execute"; +import type { WeaviateClientFactory } from "@/lib/db/providers/vector/weaviate/index"; +import type { WeaviateSurfaceContext } from "@/lib/db/providers/vector/weaviate/objects"; +import { createRestWeaviateClient } from "@/lib/db/providers/vector/weaviate/rest-client"; +import { WEAVIATE_CLIENT_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; +import { + readWeaviateVersion, + type WeaviatePath, + type WeaviatePathKind, + type WeaviateVersion, +} from "@/lib/db/providers/vector/weaviate/versions"; +import type { ObjectSourcePart } from "@/lib/db/types"; +import type { DatabaseConnection } from "@/lib/types"; +import type { LoggedCall } from "./call-log"; +import type { WeaviateExchange } from "./weaviate-scenario"; + +const FIXTURES = join(import.meta.dir, "..", "fixtures", "weaviate"); + +export const WEAVIATE_TEST_CONNECTION: DatabaseConnection = { + id: "weaviate-unit", + name: "Weaviate", + type: "weaviate", + host: "127.0.0.1", + port: 8080, + createdAt: new Date(0), +}; + +/** The options a plain connection to 127.0.0.1:8080 is built with. */ +export function testOptions(): WeaviateConnectionOptions { + return buildWeaviateConnectionOptions(WEAVIATE_TEST_CONNECTION, { executionReadOnly: false, queryTimeout: 30_000 }); +} + +/** A version as `GET /v1/meta` reports it. */ +export function version(text: string): WeaviateVersion { + return readWeaviateVersion(JSON.stringify({ version: text })); +} + +export function answer(status: number, text: string, contentType: string | null = "application/json"): WeaviateAnswer { + return { status, contentType, retryAfter: null, text }; +} + +export function json(value: unknown, status = 200): WeaviateAnswer { + return answer(status, JSON.stringify(value)); +} + +/** The words Weaviate answers when a path is switched off, in the shapes measured on 1.37.4 and 1.40.2. */ +export const GRAPHQL_DISABLED = json({ error: [{ message: "graphql api is disabled" }] }, 422); +export const REST_SEARCH_DISABLED = json( + { error: [{ message: "rest search api is experimental and not enabled" }] }, + 422, +); +export const routeAbsent = (path: string): WeaviateAnswer => + json({ code: 404, message: `path ${path} was not found` }, 404); + +export function captureExchanges(file: string): readonly WeaviateExchange[] { + return (JSON.parse(readFileSync(join(FIXTURES, file), "utf8")) as { exchanges: WeaviateExchange[] }).exchanges; +} + +/** One captured answer's text, by method and path (and body, where given). */ +export function capturedText(file: string, method: string, path: string, body: string | null = null): string { + const found = captureExchanges(file).find( + (exchange) => exchange.method === method && exchange.path === path && exchange.body === body, + ); + if (found?.answer == null) throw new Error(`${file} holds no answer to ${method} ${path}`); + return found.answer.text; +} + +/** The server a capture recorded, answering any request it holds, as often as it is asked. */ +export function capturedServer(file: string): (request: WeaviateRequest) => Promise { + const exchanges = captureExchanges(file); + const transport: NodeTransport = { + async request(request) { + const url = new URL(request.url); + const path = `${url.pathname}${url.search}`; + const body = request.body ?? null; + const found = exchanges.find( + (exchange) => exchange.method === request.method && exchange.path === path && exchange.body === body, + ); + if (found?.answer == null) throw new Error(`${file} holds no answer to ${request.method} ${path} ${body ?? ""}`); + return found.answer; + }, + close() {}, + }; + const client = createRestWeaviateClient(testOptions(), WEAVIATE_CLIENT_ROUTES, () => transport); + return (request) => client.send(request, new AbortController().signal); +} + +export type Answering = (request: WeaviateRequest, signal: AbortSignal) => WeaviateAnswer | Promise; + +/** The capture's server with some operations answered otherwise. */ +export function overriding(base: Answering, answers: Partial>): Answering { + return (request, signal) => (answers[request.op] ?? base)(request, signal); +} + +export interface FakeClients { + readonly factory: WeaviateClientFactory; + /** The options each client was built with, in order. */ + readonly built: WeaviateConnectionOptions[]; + /** Every request sent, as `{ method: op, args: [request] }`. */ + readonly calls: LoggedCall[]; + readonly signals: AbortSignal[]; + closed: number; + inFlight: number; + maxInFlight: number; +} + +/** A client factory whose clients record every request and answer through `answering`. */ +export function fakeClients(answering: Answering): FakeClients { + const record: FakeClients = { + factory: undefined as unknown as WeaviateClientFactory, + built: [], + calls: [], + signals: [], + closed: 0, + inFlight: 0, + maxInFlight: 0, + }; + (record as { factory: WeaviateClientFactory }).factory = (options) => { + record.built.push(options); + const client: WeaviateClient = { + async send(request, signal) { + record.calls.push({ method: request.op, args: [request] }); + record.signals.push(signal); + record.inFlight += 1; + record.maxInFlight = Math.max(record.maxInFlight, record.inFlight); + try { + return await answering(request, signal); + } finally { + record.inFlight -= 1; + } + }, + close() { + record.closed += 1; + }, + }; + return client; + }; + return record; +} + +/** An answer that never comes: it rejects with the signal's reason once the signal aborts. */ +export function hanging(_request: WeaviateRequest, signal: AbortSignal): Promise { + return new Promise((_resolve, reject) => { + if (signal.aborted) reject(signal.reason); + signal.addEventListener("abort", () => reject(signal.reason), { once: true }); + }); +} + +export async function rejection(promise: Promise): Promise { + try { + await promise; + } catch (error) { + return error; + } + throw new Error("resolved"); +} + +/** The session's path memory, as index.ts keeps it, with what it holds visible to a test. */ +export function pathMemory(initial: Partial> = {}): WeaviatePathState & { + readonly known: Map; +} { + const known = new Map(Object.entries(initial) as [WeaviatePathKind, WeaviatePath][]); + return { + known, + get: (kind) => known.get(kind), + set: (kind, path) => { + known.set(kind, path); + }, + }; +} + +/** A surface context over `answering`, recording every request it sends. */ +export function surfaceContext( + answering: Answering, + over: { readonly version?: string; readonly scoped?: boolean; readonly paths?: WeaviatePathState } = {}, +): { readonly context: WeaviateSurfaceContext; readonly calls: LoggedCall[] } { + const calls: LoggedCall[] = []; + const signal = new AbortController().signal; + return { + calls, + context: { + send: async (request, given) => { + calls.push({ method: request.op, args: [request] }); + return answering(request, given); + }, + signal, + version: version(over.version ?? "1.40.2"), + paths: over.paths ?? pathMemory(), + scoped: over.scoped ?? false, + }, + }; +} + +/** A Source part with its text: what every Weaviate part is, since none is ever unavailable. */ +export function renderedPart(part: ObjectSourcePart): Extract { + if (!("text" in part)) throw new Error(`the part ${part.id} has no text`); + return part; +} diff --git a/tests/helpers/weaviate-wire.ts b/tests/helpers/weaviate-wire.ts new file mode 100644 index 0000000000..f66c1bbe0e --- /dev/null +++ b/tests/helpers/weaviate-wire.ts @@ -0,0 +1,79 @@ +/** + * Wire stand-ins for the Weaviate unit tests (#1566 spec 7.3): a recording transport `createRestWeaviateClient` + * takes in place of the shared `createNodeTransport`, so a test sees every request the client would have put on the + * wire with no socket and no `mock.module()`, and the answers live servers gave, read from the captures under + * tests/fixtures/weaviate/. + * + * `calls` is the `LoggedCall` log `expectCalls` reads (tests/helpers/call-log.ts): the method is the request line + * without the origin, `GET /v1/schema/Article`, and the one argument is the body, or null where there is none. + */ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import type { NodeRequest, NodeResponse, NodeTransport, NodeTransportOptions } from "@/lib/db/http/node-transport"; +import type { WeaviateAnswer } from "@/lib/db/providers/vector/weaviate/client"; +import type { WeaviateTransportFactory } from "@/lib/db/providers/vector/weaviate/rest-client"; +import type { LoggedCall } from "./call-log"; + +export type RecordedAnswer = (request: NodeRequest, line: string) => NodeResponse | Promise; + +export interface RecordingWeaviateTransport { + readonly factory: WeaviateTransportFactory; + /** One entry per request, in order: `{ method: "POST /v1/search/Article/bm25", args: [body] }`. */ + readonly calls: LoggedCall[]; + /** Every request as the client handed it to the transport. */ + readonly requests: NodeRequest[]; + /** The options of every transport the factory built: one per client. */ + readonly built: NodeTransportOptions[]; + /** How many times a transport was closed. */ + closed(): number; +} + +/** A 200 JSON answer with the text `text`. */ +export function okAnswer(text: string): NodeResponse { + return { status: 200, contentType: "application/json", retryAfter: null, text }; +} + +function requestLine(request: NodeRequest): string { + const url = new URL(request.url); + return `${request.method} ${url.pathname}${url.search}`; +} + +export function recordingWeaviateTransport(answer: RecordedAnswer = () => okAnswer("{}")): RecordingWeaviateTransport { + const calls: LoggedCall[] = []; + const requests: NodeRequest[] = []; + const built: NodeTransportOptions[] = []; + let closed = 0; + const factory: WeaviateTransportFactory = (options): NodeTransport => { + built.push(options); + return { + async request(request) { + const line = requestLine(request); + requests.push(request); + calls.push({ method: line, args: [request.body ?? null] }); + return answer(request, line); + }, + close() { + closed += 1; + }, + }; + }; + return { factory, calls, requests, built, closed: () => closed }; +} + +const FIXTURES = join(import.meta.dir, "..", "fixtures", "weaviate"); + +interface CapturedExchange { + readonly method: string; + readonly path: string; + readonly answer: WeaviateAnswer | null; +} + +/** The answer a live server gave to `line` (`GET /v1/meta`) in the capture `file`, as it crossed the seam. */ +export function capturedAnswer(file: string, line: string): WeaviateAnswer { + const capture = JSON.parse(readFileSync(join(FIXTURES, file), "utf8")) as { + readonly exchanges: readonly CapturedExchange[]; + }; + const found = capture.exchanges.find((exchange) => `${exchange.method} ${exchange.path}` === line)?.answer; + if (found === undefined || found === null) throw new Error(`${file} holds no answer to ${line}`); + return { status: found.status, contentType: found.contentType, retryAfter: found.retryAfter, text: found.text }; +} diff --git a/tests/integration/db/weaviate-provider.test.ts b/tests/integration/db/weaviate-provider.test.ts new file mode 100644 index 0000000000..06e06a05a9 --- /dev/null +++ b/tests/integration/db/weaviate-provider.test.ts @@ -0,0 +1,156 @@ +/** + * The Weaviate provider over what live servers answered (#1566 spec 7.3). Each capture under + * tests/fixtures/weaviate/ is one scenario of tests/live/weaviate-scenarios.ts, written by + * tests/live/weaviate-evidence.ts against the servers of docker/weaviate/README.md: every request the provider sent, + * the answer it got, and what each call returned or threw. + * + * Here the same provider is built over a transport that answers from the capture (tests/helpers/weaviate-scenario.ts) + * and makes the same calls. Three things are held: every request it sends is one the capture holds, every request + * the capture holds is sent, and every outcome is the one recorded. So a module change that alters a request, a + * path decision, a column, a sentence or a refusal fails here by scenario and step, with no socket and no + * `mock.module()`. + */ +import { describe, expect, test } from "bun:test"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { + REPLAY_SECRETS, + replayTransport, + runScenario, + scenarioConnection, + scenarioProvider, + type WeaviateExchange, + type WeaviateOutcome, +} from "../../helpers/weaviate-scenario"; +import { scenarioFile, WEAVIATE_SCENARIOS, WEAVIATE_SERVICES } from "../../live/weaviate-scenarios"; + +const FIXTURES = join(import.meta.dir, "..", "..", "fixtures", "weaviate"); + +interface Capture { + readonly $captured: { readonly service: string; readonly scenario: string; readonly version: string }; + readonly transport: readonly { readonly origin: string; readonly headers: Record }[]; + readonly exchanges: readonly WeaviateExchange[]; + readonly outcomes: readonly WeaviateOutcome[]; +} + +function captureOf(file: string): Capture { + return JSON.parse(readFileSync(join(FIXTURES, file), "utf8")) as Capture; +} + +describe("the Weaviate provider over the captures", () => { + for (const scenario of WEAVIATE_SCENARIOS) { + const file = scenarioFile(scenario); + test(`${file}: the same requests and the same outcomes`, async () => { + const capture = captureOf(file); + expect(capture.$captured.service).toBe(scenario.service); + expect(capture.$captured.scenario).toBe(scenario.name); + expect(capture.$captured.version).toBe(WEAVIATE_SERVICES[scenario.service].version); + const replay = replayTransport(capture.exchanges); + const provider = scenarioProvider(scenarioConnection(scenario, REPLAY_SECRETS), replay.factory); + const outcomes = await runScenario(provider, scenario.steps); + expect(outcomes).toEqual(JSON.parse(JSON.stringify(capture.outcomes))); + expect(replay.unused()).toEqual([]); + // One transport per connect, built with the recorded origin and header names. + expect( + replay.built.map((options) => `${options.origin.scheme}://${options.origin.host}:${options.origin.port}`), + ).toEqual(capture.transport.map((entry) => entry.origin)); + expect(replay.built.map((options) => Object.keys(options.headers).sort())).toEqual( + capture.transport.map((entry) => Object.keys(entry.headers).sort()), + ); + }); + } +}); + +describe("what the captures show", () => { + const outcome = (file: string, step: string): WeaviateOutcome => { + const found = captureOf(file).outcomes.find((entry) => entry.step === step); + if (found === undefined) throw new Error(`${file} has no step ${step}`); + return found; + }; + const lines = (file: string): string[] => + captureOf(file).exchanges.map((exchange) => `${exchange.method} ${exchange.path}`); + + test("a search runs over REST on 1.40 and over GraphQL on 1.38 and 1.37", () => { + expect(lines("weaviate/searches.json")).toContain("POST /v1/search/Article/bm25"); + expect(lines("weaviate/searches.json")).not.toContain("POST /v1/graphql"); + for (const file of ["weaviate-1-38/searches.json", "weaviate-1-37/searches.json"]) { + expect(lines(file)).toContain("POST /v1/graphql"); + expect(lines(file).some((line) => line.startsWith("POST /v1/search/"))).toBe(false); + } + }); + + test("a value list filter answers the same rows over GraphQL as over REST", () => { + const step = + 'query POST /v1/search/Article/bm25 {"query": "vector", "where": {"path": ["tags"], "operator": "ContainsAny", "valueTextArray": ["graph", "shard"]}, "limit": 50, "returnProperties": ["title"]}'; + const ids = (file: string) => + ((outcome(file, step) as { value: { rows: { $id: string }[] } }).value.rows.map((row) => row.$id) ?? []).sort(); + expect(ids("weaviate-1-37/searches.json")).toEqual(ids("weaviate/searches.json")); + expect(ids("weaviate-1-38/searches.json")).toEqual(ids("weaviate/searches.json")); + expect(ids("weaviate/searches.json")).toHaveLength(50); + }); + + test("a WithinGeoRange aggregate on 1.37 carries the server's 0 with a note; 1.38 and 1.40 count the objects", () => { + const step = + 'query POST /v1/aggregate/Article {"where": {"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}}'; + const value = (file: string) => + (outcome(file, step) as { value: { rows: { count: number }[]; warnings: { message: string }[] } }).value; + expect(value("weaviate-1-37/searches.json").rows[0]?.count).toBe(0); + expect(value("weaviate-1-37/searches.json").warnings.map((w) => w.message)).toContain( + "Weaviate 1.37.4 counts an aggregate filtered by WithinGeoRange as 0 even where objects match (measured on 1.37.4); read the objects with a search, or count on 1.38 or later.", + ); + for (const file of ["weaviate/searches.json", "weaviate-1-38/searches.json"]) { + expect(value(file).rows[0]?.count).toBe(500); + expect(value(file).warnings.some((w) => w.message.includes("WithinGeoRange"))).toBe(false); + } + }); + + test("a BM25 score is a number over GraphQL as it is over REST", () => { + const step = + 'query POST /v1/search/Article/bm25 {"query": "vector", "limit": 3, "returnProperties": ["title", "wordCount"], "returnMetadata": ["score"]}'; + for (const file of ["weaviate/searches.json", "weaviate-1-37/searches.json"]) { + const found = outcome(file, step) as { value: { rows: { $score: unknown }[] } }; + expect(found.value.rows.every((row) => typeof row.$score === "number")).toBe(true); + } + }); + + test("with GraphQL disabled on 1.40 every search still runs, over REST", () => { + expect(lines("weaviate-nographql/searches.json")).not.toContain("POST /v1/graphql"); + expect( + "value" in + outcome("weaviate-nographql/searches.json", 'query POST /v1/aggregate/Article {"groupBy": "category"}'), + ).toBe(true); + }); + + test("a COLD tenant is refused after one read of its own record, and no data read names it", () => { + for (const file of ["weaviate/reads.json", "weaviate-1-37/reads.json"]) { + const named = lines(file).filter((line) => line.includes("initech") || line.includes("umbrella")); + expect(named.every((line) => line.startsWith("GET /v1/schema/"))).toBe(true); + expect(named.some((line) => line.includes("/shards"))).toBe(false); + } + }); + + test("a refused request sends nothing past the connect read; an unknown tenant is looked up, never read", () => { + expect(lines("weaviate/refusals.json").filter((line) => line !== "GET /v1/meta")).toEqual([ + "GET /v1/schema/TenantNotes", + "GET /v1/schema/TenantNotes/tenants/nobody", + ]); + }); + + test("the key travels as a bearer header and is never recorded", () => { + const reader = captureOf("weaviate-auth/reader.json"); + expect(reader.transport.every((entry) => entry.headers.authorization === "Bearer ")).toBe(true); + expect(captureOf("weaviate/surface.json").transport.every((entry) => !("authorization" in entry.headers))).toBe( + true, + ); + expect(outcome("weaviate-auth/no-key.json", "connect")).toMatchObject({ error: { name: "AuthenticationError" } }); + expect(outcome("weaviate-auth/wrong-key.json", "connect")).toMatchObject({ + error: { name: "AuthenticationError" }, + }); + }); + + test("plain HTTP to the TLS port asks for an SSL mode", () => { + expect(outcome("weaviate-tls/plain-to-tls.json", "connect")).toMatchObject({ + error: { name: "ConnectionError", message: expect.stringContaining("choose an SSL mode") }, + }); + }); +}); diff --git a/tests/isolated/factory.test.ts b/tests/isolated/factory.test.ts index d848c00d75..3a46ef2fd6 100644 --- a/tests/isolated/factory.test.ts +++ b/tests/isolated/factory.test.ts @@ -832,6 +832,28 @@ describe("createDatabaseProvider", () => { expect((await createDatabaseProvider(conn)).type).toBe("qdrant"); }); + test('creates provider for type "weaviate"', async () => { + // No user and no database: Weaviate takes a bearer token alone and has no container level. The constructor + // validates nothing and opens nothing, as Qdrant's, so the provider is built with no Weaviate running. + const conn = makeConnection("weaviate", { port: 8080, user: undefined, database: undefined }); + const provider = await createDatabaseProvider(conn); + expect(provider.type).toBe("weaviate"); + expect(provider.getCapabilities().queryLanguage).toBe("json"); + expect(provider.getCapabilities().queryDialect).toBe("weaviate"); + expect(provider.getCapabilities().enforcesReadOnly).toBe(true); + expect(provider.getCapabilities().supportsMaintenance).toBe(false); + expect(provider.isConnected()).toBe(false); + }); + + test("a weaviate connection with readOnly: true is built, since its provider keeps the mode (#1566 spec 3.5)", async () => { + const conn = { + ...makeConnection("weaviate", { port: 8080, user: undefined, database: undefined }), + readOnly: true, + }; + expect(() => assertReadOnlyHonoured(conn)).not.toThrow(); + expect((await createDatabaseProvider(conn)).type).toBe("weaviate"); + }); + test('creates provider for type "oxia"', async () => { // No user and no namespace: Oxia has no user name, and an empty namespace means default. The constructor // validates nothing and opens nothing, so the provider is built, and declares its language, its dialect and @@ -879,7 +901,7 @@ describe("createDatabaseProvider", () => { test("the factory error lists milvus among the supported types, before qdrant and the embedded store", async () => { const conn = makeConnection("not-an-engine"); await expect(createDatabaseProvider(conn)).rejects.toThrow( - /Supported types: .*\bneo4j, milvus, qdrant, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb$/, + /Supported types: .*\bneo4j, milvus, qdrant, weaviate, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb$/, ); }); @@ -915,6 +937,13 @@ describe("createDatabaseProvider", () => { lifetime.abort(); }); + test("the factory error lists weaviate between qdrant and s3", async () => { + const conn = makeConnection("not-an-engine"); + await expect(createDatabaseProvider(conn)).rejects.toThrow( + /Supported types: .*\bqdrant, weaviate, s3\b.*, libredb$/, + ); + }); + test("the factory error lists qdrant among the supported types, before the embedded store", async () => { const conn = makeConnection("not-an-engine"); await expect(createDatabaseProvider(conn)).rejects.toThrow(/Supported types: .*\bqdrant\b.*, libredb$/); @@ -945,7 +974,7 @@ describe("createDatabaseProvider", () => { test("the factory error lists s3 between qdrant and kubernetes, kubernetes before the embedded store", async () => { const conn = makeConnection("not-an-engine"); await expect(createDatabaseProvider(conn)).rejects.toThrow( - /Supported types: .*\bqdrant, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb$/, + /Supported types: .*\bqdrant, weaviate, s3, mqtt, opcua, mtconnect, modbus, snmp, rabbitmq, kubernetes, netconf, sparkplug, libredb$/, ); }); diff --git a/tests/isolated/monaco-language-ids.test.ts b/tests/isolated/monaco-language-ids.test.ts index 622a48e491..ca0b0fcc0c 100644 --- a/tests/isolated/monaco-language-ids.test.ts +++ b/tests/isolated/monaco-language-ids.test.ts @@ -360,8 +360,9 @@ describe("the installed editor's language ids", () => { // than a near relative: the installed bundle registers no YANG, and declaring `ini` or `sql` // for a module's text would colour it as something it is not. // 146 with that pair, and 148 since Sparkplug B's two kinds joined (#1720): a node and a device - // each declare `json`, the payload this provider decodes a birth certificate into. - expect(declared).toHaveLength(148); + // each declare `json`, the payload this provider decodes a birth certificate into. 149 since Weaviate's + // collection joined (#1566), declaring `json`, the two-part Source of its schema and its state. + expect(declared).toHaveLength(149); const unregistered = declared.filter((entry) => !registered.has(entry.language)); // Named, so a failure says which kind on which engine declared what, rather than false. This diff --git a/tests/isolated/object-column-declarations.test.ts b/tests/isolated/object-column-declarations.test.ts index 665bd3c415..7b9fc8fcad 100644 --- a/tests/isolated/object-column-declarations.test.ts +++ b/tests/isolated/object-column-declarations.test.ts @@ -118,6 +118,7 @@ const EXPECTED_COLUMN_KINDS: Readonly> = milvus: ["collection"], // One kind, a collection, whose columns are its id, its vectors and its payload fields (vector-family spec 6.3). qdrant: ["collection"], + weaviate: ["collection"], // One kind each: a measurement, whose columns are its time, tag keys and field keys, and an InfluxDB 3 table, whose // columns are its information-schema columns (InfluxDB spec I11, R16). influxdb: ["measurement"], @@ -247,7 +248,7 @@ describe("the fleet census of object column declarations", () => { // `EXTERNAL_DATABASE_TYPES.length` plus the embedded store. The names are not repeated here, // because a prose list of them is what goes stale while the assertion stays green: the registry // is the list, and this numeral only says how long it is. - expect(CENSUS_TYPES).toHaveLength(42); + expect(CENSUS_TYPES).toHaveLength(43); expect(Object.keys(EXPECTED_COLUMN_KINDS).sort()).toEqual([...SHIPPED_DATABASE_TYPES].sort()); // A row naming nothing would make its type-id's census pass on the empty set, so the design's // table has three such rows, and they are named here: every engine but Oxia, S3, Kubernetes, MQTT, OPC UA and Modbus has at least one diff --git a/tests/isolated/object-source-declarations.test.ts b/tests/isolated/object-source-declarations.test.ts index 313b7d4638..dcc36ea563 100644 --- a/tests/isolated/object-source-declarations.test.ts +++ b/tests/isolated/object-source-declarations.test.ts @@ -149,6 +149,7 @@ const SOURCE_DECLARATIONS: Readonly> = O milvus: ["collection/json"], // A collection's two-part Source, JSON under the declared language (vector-family spec 6.3). qdrant: ["collection/json"], + weaviate: ["collection/json"], // No kind has a source in v1 (InfluxDB spec I11): a measurement and an InfluxDB 3 table are listed and described, // and neither provider implements readObjectSource. influxdb: [], @@ -343,7 +344,7 @@ describe("the fleet census of object source declarations", () => { // EXTERNAL_DATABASE_TYPES.length (38 with db2, neo4j, milvus, qdrant, influxdb, influxdb3, oxia, databend, // bigquery, snowflake, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect and sparkplug) plus the // embedded store. - expect(CENSUS_TYPES).toHaveLength(42); + expect(CENSUS_TYPES).toHaveLength(43); expect(Object.keys(SOURCE_DECLARATIONS).sort()).toEqual([...SHIPPED_DATABASE_TYPES].sort()); }); @@ -361,8 +362,8 @@ describe("the fleet census of object source declarations", () => { // `hasSource` moves between the two halves, so both halves must be pinned or the total alone // would still be satisfied. Neither half may be edited to match a build: if this fails, the // DECLARATION is wrong or the design's table is, and the repair is one of those two. - expect(UNCONNECTED_SOURCE_KINDS).toHaveLength(146); - expect(rows.filter((row) => row.kind.hasSource === true)).toHaveLength(146); + expect(UNCONNECTED_SOURCE_KINDS).toHaveLength(147); + expect(rows.filter((row) => row.kind.hasSource === true)).toHaveLength(147); // neo4j added four kinds, none source-bearing, db2 five source-bearing kinds and four others, milvus and // qdrant one source-bearing kind each, influxdb and influxdb3 one kind each, neither source-bearing, oxia // two source-bearing kinds, databend four source-bearing kinds, bigquery three kinds, snowflake nine source-bearing @@ -371,9 +372,9 @@ describe("the fleet census of object source declarations", () => { // source-bearing kind, spark two source-bearing kinds and its function kind, mtconnect three // kinds of which two are not source-bearing, snmp two kinds, NEITHER source-bearing (an SNMP // object is a value at a numbered place, with no text behind it to show), netconf two kinds, - // BOTH source-bearing, and sparkplug two kinds, BOTH source-bearing. + // BOTH source-bearing, sparkplug two kinds, BOTH source-bearing, and weaviate one kind, source-bearing (#1566). expect(rows.filter((row) => row.kind.hasSource !== true)).toHaveLength(48); - expect(rows).toHaveLength(194); + expect(rows).toHaveLength(195); }); test("the MariaDB branch declares two more, which an unconnected provider cannot show", async () => { @@ -402,7 +403,7 @@ describe("the fleet census of object source declarations", () => { // 126 on a MariaDB connection against 124 unconnected: the design states both numbers because // criterion 2's evidence method reads an unconnected provider and would otherwise // structurally exclude the two riskiest declarations in the phase. 142 since MTConnect's `asset` - expect(UNCONNECTED_SOURCE_KINDS.length + MARIADB_EXTRA_SOURCE_KINDS.length).toBe(148); + expect(UNCONNECTED_SOURCE_KINDS.length + MARIADB_EXTRA_SOURCE_KINDS.length).toBe(149); }); /* @@ -490,8 +491,8 @@ describe("the fleet census of object source declarations", () => { } // 181 unconnected kinds plus the MariaDB branch's eight, and the kinds each new provider // brought: MTConnect's three (#1722), NETCONF's and Modbus's, SNMP's two (#1721) and - // Sparkplug B's two (#1720). - expect(rows).toHaveLength(202); + // Sparkplug B's two (#1720), and Weaviate's one (#1566). + expect(rows).toHaveLength(203); const halfDeclared = rows .filter((row) => row.kind.sourceLanguage !== undefined && row.kind.hasSource !== true) diff --git a/tests/live/weaviate-evidence.ts b/tests/live/weaviate-evidence.ts new file mode 100644 index 0000000000..6956fe796e --- /dev/null +++ b/tests/live/weaviate-evidence.ts @@ -0,0 +1,126 @@ +/** + * The Weaviate provider's evidence harness (#1566 spec 7.3). It drives every scenario of + * tests/live/weaviate-scenarios.ts through the provider against the live servers of docker/weaviate/README.md, over + * the real `node:http(s)` transport, and writes tests/fixtures/weaviate//.json: the image and its + * digest, the server version, the date and the runtime, every request the provider sent with the answer it got, and + * the outcome of every call. The integration test replays these files (tests/integration/db/weaviate-provider.test.ts). + * + * It only reads: every scenario's requests are the provider's own, and the provider has no write route. It never + * sends `/v1/schema/{collection}/shards?tenant=` for a COLD tenant, which hangs the 1.37 line + * (docker/weaviate/README.md, "Reading a cold tenant wakes it"), because the provider's tenant guard refuses it. + * + * No key is written: the credential header is recorded as `Bearer `, and every file is checked for every key + * this run holds before anything is written; one that holds a key stops the run with nothing written. + * + * Run by hand, never by `bun run test` (tests/runner/discover.ts excludes tests/live/): + * bun tests/live/weaviate-evidence.ts --keys [--only ] + * is a copy of the keys volume (`docker cp libredb-weaviate-auth:/keys `), outside the repository. + */ +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import path from "node:path"; +import { createNodeTransport, type NodeTransportOptions } from "@/lib/db/http/node-transport"; +import { + recordingTransport, + runScenario, + scenarioConnection, + scenarioProvider, + type WeaviateExchange, + type WeaviateSecrets, +} from "../helpers/weaviate-scenario"; +import { scenarioFile, WEAVIATE_SCENARIOS, WEAVIATE_SERVICES, type WeaviateService } from "./weaviate-scenarios"; + +const ROOT = path.join(import.meta.dir, "..", ".."); +const FIXTURES = path.join(ROOT, "tests", "fixtures", "weaviate"); + +function argument(name: string): string | undefined { + const index = process.argv.indexOf(name); + return index < 0 ? undefined : process.argv[index + 1]; +} + +/** The image a service runs, by tag and digest, as the compose file pins it. */ +function imageOf(service: WeaviateService): string { + const compose = readFileSync(path.join(ROOT, "database-compose.yml"), "utf8"); + const block = compose.split(`\n ${service}:\n`)[1]; + const image = block?.match(/^\s+image: (\S+)$/m)?.[1]; + if (image === undefined) throw new Error(`database-compose.yml pins no image for ${service}`); + return image; +} + +function secretsFrom(dir: string): WeaviateSecrets { + const read = (file: string) => readFileSync(path.join(dir, file), "utf8").trim(); + return { + root: read("root.key"), + reader: read("auth/reader.key"), + wrong: "weaviate-evidence-not-a-key", + ca: readFileSync(path.join(dir, "ca.pem"), "utf8"), + }; +} + +/** The transport options as written down: the credential header's value never, only that it was set. */ +function transportRecord(built: readonly NodeTransportOptions[]): unknown { + return built.map((options) => ({ + origin: `${options.origin.scheme}://${options.origin.host}:${options.origin.port}`, + tls: + options.tls === null + ? null + : { rejectUnauthorized: options.tls.rejectUnauthorized, ca: options.tls.ca !== undefined }, + maxSockets: options.maxSockets, + headers: Object.fromEntries( + Object.entries(options.headers).map(([name, value]) => [name, name === "authorization" ? "Bearer " : value]), + ), + })); +} + +const keys = argument("--keys"); +if (keys === undefined) throw new Error("--keys is required: a copy of the weaviate-keys volume"); +const secrets = secretsFrom(keys); +const tlsReader = readFileSync(path.join(keys, "tls/reader.key"), "utf8").trim(); +const only = argument("--only")?.split(","); +const held = [secrets.root, secrets.reader, tlsReader]; + +const files: { file: string; text: string }[] = []; +for (const scenario of WEAVIATE_SCENARIOS) { + if (only !== undefined && !only.includes(scenario.service)) continue; + // The TLS server's reader is its own user, so its key is that server's. + const scenarioSecrets = scenario.service === "weaviate-tls" ? { ...secrets, reader: tlsReader } : secrets; + const exchanges: WeaviateExchange[] = []; + const built: NodeTransportOptions[] = []; + const provider = scenarioProvider( + scenarioConnection(scenario, scenarioSecrets), + recordingTransport(createNodeTransport, exchanges, built), + ); + const outcomes = await runScenario(provider, scenario.steps); + const service = WEAVIATE_SERVICES[scenario.service]; + const [image, digest] = imageOf(scenario.service).split("@"); + const record = { + $captured: { + engine: "weaviate", + service: scenario.service, + scenario: scenario.name, + image, + digest, + version: service.version, + date: new Date().toISOString(), + runtime: `bun ${Bun.version}`, + credential: scenario.credential, + }, + transport: transportRecord(built), + exchanges, + outcomes, + }; + const text = `${JSON.stringify(record, null, 2)}\n`; + for (const secret of held) { + if (text.includes(secret)) throw new Error(`${scenarioFile(scenario)} would hold a key; nothing was written`); + } + files.push({ file: scenarioFile(scenario), text }); + const failed = outcomes.filter((outcome) => "error" in outcome).length; + console.log( + `${scenarioFile(scenario)}: ${exchanges.length} requests, ${outcomes.length} outcomes, ${failed} refused or failed`, + ); +} + +for (const { file, text } of files) { + mkdirSync(path.dirname(path.join(FIXTURES, file)), { recursive: true }); + writeFileSync(path.join(FIXTURES, file), text); +} +console.log(`wrote ${files.length} captures under tests/fixtures/weaviate/`); diff --git a/tests/live/weaviate-live-check.ts b/tests/live/weaviate-live-check.ts new file mode 100644 index 0000000000..5a855a7009 --- /dev/null +++ b/tests/live/weaviate-live-check.ts @@ -0,0 +1,148 @@ +/** + * The Weaviate provider's live check (#1566 spec 7.4). It runs every scenario of tests/live/weaviate-scenarios.ts + * against the live servers of docker/weaviate/README.md and holds each run to its capture under + * tests/fixtures/weaviate/: the same requests, and the same outcomes. A difference means the server or the provider + * changed since the capture was written, and is printed by scenario and step. + * + * Weaviate's own order is not stable between two identical reads (the classes of `/v1/schema`, the shards of + * `/v1/nodes`, the groups of an aggregate), and the console shows a server's answer in the server's order, so both + * sides are compared in a canonical form: object keys sorted and every array sorted. The order a surface call + * imposes is held exactly by the replay in tests/integration/db/weaviate-provider.test.ts instead. + * + * It also snapshots, on every plaintext anonymous server, the schema, the aliases and every tenant's activity status + * before the run and after it, and fails on any change: the provider only reads, and no read may wake a COLD tenant. + * + * Run by hand, never by `bun run test` (tests/runner/discover.ts excludes tests/live/): + * bun tests/live/weaviate-live-check.ts --keys [--only ] + * is a copy of the keys volume (`docker cp libredb-weaviate-auth:/keys `), outside the repository. + * Exit 0 when every scenario matches and nothing changed, 1 otherwise. + */ +import { readFileSync } from "node:fs"; +import http from "node:http"; +import path from "node:path"; +import { isDeepStrictEqual } from "node:util"; +import { createNodeTransport, type NodeTransportOptions } from "@/lib/db/http/node-transport"; +import { + recordingTransport, + runScenario, + scenarioConnection, + scenarioProvider, + type WeaviateExchange, + type WeaviateOutcome, + type WeaviateSecrets, +} from "../helpers/weaviate-scenario"; +import { scenarioFile, WEAVIATE_SCENARIOS, WEAVIATE_SERVICES, type WeaviateService } from "./weaviate-scenarios"; + +const FIXTURES = path.join(import.meta.dir, "..", "fixtures", "weaviate"); +const SNAPSHOT_SERVICES: readonly WeaviateService[] = [ + "weaviate", + "weaviate-1-38", + "weaviate-1-37", + "weaviate-nographql", +]; + +/** Object keys sorted and every array sorted by its members' canonical text. */ +function canonical(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(canonical).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b))); + } + if (value !== null && typeof value === "object") { + return Object.fromEntries( + Object.entries(value as Record) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([key, entry]) => [key, canonical(entry)]), + ); + } + return value; +} + +const same = (a: unknown, b: unknown): boolean => isDeepStrictEqual(canonical(a), canonical(b)); + +function argument(name: string): string | undefined { + const index = process.argv.indexOf(name); + return index < 0 ? undefined : process.argv[index + 1]; +} + +function get(port: number, route: string): Promise { + return new Promise((resolve, reject) => { + http + .get({ host: "127.0.0.1", port, path: route, agent: false }, (response) => { + let text = ""; + response.setEncoding("utf8"); + response.on("data", (chunk: string) => { + text += chunk; + }); + response.on("end", () => resolve(text)); + }) + .on("error", reject); + }); +} + +/** The schema, the aliases and every multi-tenant collection's tenants with their statuses. */ +async function snapshot(service: WeaviateService): Promise { + const { port } = WEAVIATE_SERVICES[service]; + const schema = JSON.parse(await get(port, "/v1/schema")) as { + classes?: { class: string; multiTenancyConfig?: { enabled?: boolean } }[]; + }; + const tenants: Record = {}; + for (const entry of schema.classes ?? []) { + if (entry.multiTenancyConfig?.enabled === true) { + tenants[entry.class] = JSON.parse(await get(port, `/v1/schema/${encodeURIComponent(entry.class)}/tenants`)); + } + } + return { schema, aliases: JSON.parse(await get(port, "/v1/aliases")), tenants }; +} + +const keys = argument("--keys"); +if (keys === undefined) throw new Error("--keys is required: a copy of the weaviate-keys volume"); +const read = (file: string) => readFileSync(path.join(keys, file), "utf8"); +const secrets: WeaviateSecrets = { + root: read("root.key").trim(), + reader: read("auth/reader.key").trim(), + wrong: "weaviate-evidence-not-a-key", + ca: read("ca.pem"), +}; +const tlsReader = read("tls/reader.key").trim(); +const only = argument("--only")?.split(","); +const selected = WEAVIATE_SCENARIOS.filter((scenario) => only === undefined || only.includes(scenario.service)); +const snapshotted = SNAPSHOT_SERVICES.filter((service) => selected.some((scenario) => scenario.service === service)); + +const before = new Map(); +for (const service of snapshotted) before.set(service, await snapshot(service)); + +const line = (exchange: WeaviateExchange) => `${exchange.method} ${exchange.path} ${exchange.body ?? ""}`; +let failures = 0; +for (const scenario of selected) { + const capture = JSON.parse(readFileSync(path.join(FIXTURES, scenarioFile(scenario)), "utf8")) as { + readonly exchanges: readonly WeaviateExchange[]; + readonly outcomes: readonly WeaviateOutcome[]; + }; + const exchanges: WeaviateExchange[] = []; + const built: NodeTransportOptions[] = []; + const scenarioSecrets = scenario.service === "weaviate-tls" ? { ...secrets, reader: tlsReader } : secrets; + const provider = scenarioProvider( + scenarioConnection(scenario, scenarioSecrets), + recordingTransport(createNodeTransport, exchanges, built), + ); + const outcomes = JSON.parse(JSON.stringify(await runScenario(provider, scenario.steps))) as WeaviateOutcome[]; + const problems: string[] = []; + const sent = exchanges.map(line).sort(); + const recorded = capture.exchanges.map(line).sort(); + if (!same(sent, recorded)) problems.push("the requests differ from the capture's"); + outcomes.forEach((outcome, index) => { + if (!same(outcome, capture.outcomes[index])) problems.push(`step ${index}: ${outcome.step}`); + }); + if (outcomes.length !== capture.outcomes.length) problems.push("the number of outcomes differs"); + failures += problems.length; + console.log(`${problems.length === 0 ? "PASS" : "FAIL"} ${scenarioFile(scenario)}`); + for (const problem of problems) console.log(` ${problem}`); +} + +for (const service of snapshotted) { + const unchanged = same(before.get(service), await snapshot(service)); + if (!unchanged) failures += 1; + console.log(`${unchanged ? "PASS" : "FAIL"} ${service}: schema, aliases and tenant statuses unchanged by the run`); +} + +console.log(failures === 0 ? "live check passed" : `live check failed: ${failures} differences`); +process.exit(failures === 0 ? 0 : 1); diff --git a/tests/live/weaviate-path-parity.ts b/tests/live/weaviate-path-parity.ts new file mode 100644 index 0000000000..c5197be148 --- /dev/null +++ b/tests/live/weaviate-path-parity.ts @@ -0,0 +1,151 @@ +/** + * The Weaviate provider's path parity check (#1566 spec 3.3): the same console request on 1.40.2, which answers + * it over REST search, and on 1.38.22 and 1.37.4, which answer it over GraphQL, compared row for row once the + * path note is set aside. Every where operator and value type, every search kind, the aggregate with and without + * groupBy, and the metadata cell types. It caught the GraphQL spelling of a value list (valueText, never + * valueTextArray) and the 1.37 line's WithinGeoRange aggregate count of 0. + * + * Two differences are the servers' own and are expected: a grouped aggregate's groups come in no defined order (and + * where counts tie, a limit picks any of them), and 1.37 counts a WithinGeoRange aggregate as 0, which the provider + * notes. Anything else fails the run. + * + * Run by hand, never by `bun run test`, from a process that reaches the compose service names (the servers of + * docker/weaviate/README.md, `weaviate`, `weaviate-1-38` and `weaviate-1-37`): + * bun tests/live/weaviate-path-parity.ts + */ +import { WeaviateProvider } from "@/lib/db/providers/vector/weaviate"; + +const SERVERS = [ + ["1.40 REST", "weaviate"], + ["1.38 GraphQL", "weaviate-1-38"], + ["1.37 GraphQL", "weaviate-1-37"], +] as const; +const V16 = "[0.1, -0.2, 0.3, 0.4, -0.5, 0.6, 0.7, -0.8, 0.9, 0.1, 0.2, -0.3, 0.4, 0.5, -0.6, 0.7]"; +const W = (where: string) => `"where": ${where}`; +const FILTERS = [ + '{"path": ["category"], "operator": "Equal", "valueText": "alpha"}', + '{"path": ["category"], "operator": "NotEqual", "valueText": "alpha"}', + '{"path": ["wordCount"], "operator": "GreaterThan", "valueInt": 400}', + '{"path": ["wordCount"], "operator": "GreaterThanEqual", "valueInt": 400}', + '{"path": ["wordCount"], "operator": "LessThan", "valueInt": 120}', + '{"path": ["wordCount"], "operator": "LessThanEqual", "valueInt": 120}', + '{"path": ["rating"], "operator": "GreaterThan", "valueNumber": 3.5}', + '{"path": ["published"], "operator": "Equal", "valueBoolean": false}', + '{"path": ["publishedAt"], "operator": "LessThan", "valueDate": "2026-01-01T00:00:00Z"}', + '{"path": ["title"], "operator": "Like", "valueText": "article 0*"}', + '{"path": ["tags"], "operator": "ContainsAny", "valueTextArray": ["graph", "shard"]}', + '{"path": ["tags"], "operator": "ContainsAll", "valueTextArray": ["graph", "vector"]}', + '{"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}', + '{"operator": "And", "operands": [{"path": ["category"], "operator": "Equal", "valueText": "beta"}, {"path": ["wordCount"], "operator": "GreaterThan", "valueInt": 300}]}', + '{"operator": "Or", "operands": [{"path": ["category"], "operator": "Equal", "valueText": "beta"}, {"path": ["category"], "operator": "Equal", "valueText": "gamma"}]}', + '{"operator": "Not", "operands": [{"path": ["category"], "operator": "Equal", "valueText": "beta"}]}', + '{"operator": "And", "operands": [{"operator": "Or", "operands": [{"path": ["published"], "operator": "Equal", "valueBoolean": true}, {"path": ["rating"], "operator": "LessThan", "valueNumber": 1}]}, {"path": ["title"], "operator": "Like", "valueText": "*vector*"}]}', +]; +const REQUESTS: string[] = []; +for (const f of FILTERS) { + REQUESTS.push( + `POST /v1/search/Article/bm25 {"query": "vector", ${W(f)}, "limit": 50, "returnProperties": ["title"]}`, + ); + REQUESTS.push(`POST /v1/aggregate/Article {${W(f)}}`); + REQUESTS.push( + `POST /v1/search/Article/near-vector {"vector": ${V16}, ${W(f)}, "limit": 20, "returnProperties": ["title"], "returnMetadata": ["distance"]}`, + ); +} +REQUESTS.push( + 'POST /v1/search/Article/bm25 {"query": "vector graph", "limit": 30, "returnProperties": ["title", "wordCount", "rating", "published", "publishedAt", "tags", "category"], "returnMetadata": ["score", "creationTime", "lastUpdateTime"]}', + 'POST /v1/search/Article/bm25 {"query": "vector", "queryProperties": ["title"], "limit": 30}', + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 10, "offset": 5}', + 'POST /v1/search/Article/bm25 {"query": "vector", "autoLimit": 1}', + 'POST /v1/search/Article/hybrid {"query": "vector", "alpha": 0, "limit": 25, "returnProperties": ["title"]}', + 'POST /v1/search/Article/hybrid {"query": "vector", "alpha": 0, "queryProperties": ["body"], "limit": 25}', + `POST /v1/search/Article/near-vector {"vector": ${V16}, "limit": 25, "returnMetadata": ["distance", "certainty"]}`, + `POST /v1/search/Article/near-vector {"vector": ${V16}, "distance": 0.8, "limit": 100}`, + 'POST /v1/search/Article/near-object {"id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", "limit": 25, "returnMetadata": ["distance"]}', + 'POST /v1/search/Product/near-vector {"vector": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], "targetVector": "image", "limit": 25, "returnProperties": ["name", "price", "sku"]}', + `POST /v1/search/Product/near-vector {"vector": ${V16}, "targetVector": "text", "limit": 25}`, + 'POST /v1/search/Product/bm25 {"query": "product", "limit": 25}', + 'POST /v1/search/TenantNotes/bm25 {"query": "note", "tenant": "globex", "limit": 25}', + 'POST /v1/search/EdgeValues/bm25 {"query": "edge", "returnProperties": ["label", "big", "bigs"]}', + 'POST /v1/search/Author/bm25 {"query": "author", "limit": 25}', + "POST /v1/aggregate/Article {}", + 'POST /v1/aggregate/Article {"groupBy": "category"}', + 'POST /v1/aggregate/Article {"groupBy": "category", "limit": 3}', + 'POST /v1/aggregate/Product {"groupBy": "name", "limit": 1000}', + 'POST /v1/aggregate/TenantNotes {"tenant": "acme"}', + 'POST /v1/aggregate/TenantNotesAuto {"tenant": "hooli", "groupBy": "note"}', +); + +type Row = Record; +const canonical = (rows: Row[], fields: string[]) => + rows.map((row) => JSON.stringify(fields.map((f) => [f, row[f]]))).sort(); +const providers = await Promise.all( + SERVERS.map(async ([, host]) => { + const p = new WeaviateProvider({ id: host, name: host, type: "weaviate", host, port: 8080 } as never); + await p.connect(); + return p; + }), +); +let same = 0; +const differ: string[] = []; +let unexpected = 0; +/** The servers' own differences: a grouped aggregate's order and tie-breaking, and 1.37's geo aggregate. */ +const expectedDifference = (text: string, problem: string) => + (/"groupBy"/.test(text) && /other order|different rows/.test(problem)) || + (/WithinGeoRange/.test(text) && + text.startsWith("POST /v1/aggregate/") && + problem.startsWith("1.37 GraphQL: different rows")); +for (const text of REQUESTS) { + const outs = await Promise.all( + providers.map(async (p) => { + try { + const r = await p.query(text); + const fields = r.fields.filter( + (f) => !/^\$(score|explainScore|creationTime|lastUpdateTime|distance|certainty)$/.test(f), + ); + const ordered = r.rows.map((row) => JSON.stringify(fields.map((f) => row[f]))); + return { + ok: true, + rows: r.rowCount, + fields: r.fields.join(","), + set: canonical(r.rows as Row[], fields).join("|"), + order: ordered.join("|"), + types: JSON.stringify(r.columnTypes), + metaTypes: r.fields + .filter((f) => f.startsWith("$")) + .map((f) => `${f}:${typeof (r.rows[0] ?? {})[f]}`) + .join(","), + }; + } catch (e) { + return { ok: false, error: `${(e as Error).constructor.name}: ${(e as Error).message.slice(0, 160)}` }; + } + }), + ); + const [rest, ...gql] = outs; + const problems: string[] = []; + for (const [i, g] of gql.entries()) { + const name = SERVERS[i + 1][0]; + if (rest.ok !== g.ok) problems.push(`${name}: ${rest.ok ? "REST ok" : rest.error} vs ${g.ok ? "ok" : g.error}`); + else if (rest.ok && g.ok) { + if (rest.rows !== g.rows) problems.push(`${name}: ${rest.rows} rows vs ${g.rows}`); + else if (rest.fields !== g.fields) problems.push(`${name}: fields ${rest.fields} vs ${g.fields}`); + else if (rest.set !== g.set) problems.push(`${name}: different rows`); + else if (/near-|groupBy/.test(text) && rest.order !== g.order) problems.push(`${name}: same rows, other order`); + if (rest.metaTypes !== g.metaTypes) problems.push(`${name}: cell types ${rest.metaTypes} vs ${g.metaTypes}`); + } else if (rest.error !== g.error) problems.push(`${name}: errors differ: ${rest.error} | ${g.error}`); + } + const surprising = problems.filter((problem) => !expectedDifference(text, problem)); + unexpected += surprising.length; + if (problems.length === 0) same += 1; + else + differ.push( + `${surprising.length ? "UNEXPECTED" : "expected"} ${text.slice(0, 150)}\n ${problems.join("\n ")}`, + ); + console.log(`${problems.length ? "DIFF" : "SAME"} ${rest.ok ? `${rest.rows} rows` : "error"} ${text.slice(0, 110)}`); +} +console.log(`\n${same} of ${REQUESTS.length} requests answer the same on REST and on both GraphQL servers`); +for (const d of differ) console.log(`DIFF ${d}`); +for (const p of providers) await p.disconnect(); +console.log( + unexpected === 0 ? "path parity check passed" : `path parity check failed: ${unexpected} unexpected differences`, +); +process.exit(unexpected === 0 ? 0 : 1); diff --git a/tests/live/weaviate-scenarios.ts b/tests/live/weaviate-scenarios.ts new file mode 100644 index 0000000000..8215113876 --- /dev/null +++ b/tests/live/weaviate-scenarios.ts @@ -0,0 +1,204 @@ +/** + * The Weaviate provider's scenarios (#1566 spec 7.3): what the evidence harness drives through the provider against + * the live servers of docker/weaviate/README.md, and what the integration test replays from the captures it wrote. + * + * One list for both on purpose. A scenario is a service, a credential and the provider calls to make, in order; the + * harness records every request the provider put on the wire with the answer it got, and the outcome of every call. + * The integration test builds the same provider over a transport that answers from that record, makes the same + * calls, and holds both the requests and the outcomes to it, so a change to any module that alters a request or what + * the user sees fails by name. Pure data: importing this file opens nothing. + */ + +/** The live servers, as the compose file publishes them. */ +export const WEAVIATE_SERVICES = { + weaviate: { port: 18280, version: "1.40.2", tls: false }, + "weaviate-1-38": { port: 18285, version: "1.38.22", tls: false }, + "weaviate-1-37": { port: 18281, version: "1.37.4", tls: false }, + "weaviate-nographql": { port: 18282, version: "1.40.2", tls: false }, + "weaviate-auth": { port: 18283, version: "1.40.2", tls: false }, + "weaviate-tls": { port: 18284, version: "1.40.2", tls: true }, +} as const; + +export type WeaviateService = keyof typeof WEAVIATE_SERVICES; + +/** + * Which key a scenario sends: none, the RBAC root key, the `viewer` user's key on that server, or a key the server + * never issued. A fixture names the credential, never its value. + */ +export type WeaviateCredential = "none" | "root" | "reader" | "wrong"; + +export type WeaviateStep = + | { readonly call: "query"; readonly text: string } + | { readonly call: "listContainers" } + | { readonly call: "countObjects" } + | { readonly call: "listObjects" } + | { readonly call: "describeObject"; readonly name: string } + | { readonly call: "describeObjects"; readonly limit?: number } + | { readonly call: "readObjectSource"; readonly name: string } + | { readonly call: "getHealth" } + | { readonly call: "getOverview" } + | { readonly call: "getTableStats" } + | { readonly call: "getIndexStats" } + | { readonly call: "connectWarnings" }; + +export interface WeaviateScenario { + readonly name: string; + readonly service: WeaviateService; + readonly credential: WeaviateCredential; + /** TLS: `verify-ca` with the fixture's CA, or `disable` to send plain HTTP to the TLS port. */ + readonly ssl?: "verify-ca" | "disable"; + /** A seeded read-only connection, which the provider refuses without a key. */ + readonly readOnly?: boolean; + readonly steps: readonly WeaviateStep[]; +} + +/** The 16 seeded floats every near-vector request sends to `Article`'s unnamed vector. */ +export const ARTICLE_VECTOR: readonly number[] = [ + 0.1, -0.2, 0.3, 0.4, -0.5, 0.6, 0.7, -0.8, 0.9, 0.1, 0.2, -0.3, 0.4, 0.5, -0.6, 0.7, +]; + +/** An `Article` id the seed writes on every server (a uuid5 of its fixed namespace). */ +export const ARTICLE_ID = "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d"; + +const v = JSON.stringify(ARTICLE_VECTOR); + +/** The surface every server shows: the tree, the columns, the Source and the panels. */ +const SURFACE: readonly WeaviateStep[] = [ + { call: "connectWarnings" }, + { call: "listContainers" }, + { call: "countObjects" }, + { call: "listObjects" }, + { call: "describeObjects" }, + { call: "describeObjects", limit: 2 }, + { call: "describeObject", name: "Article" }, + { call: "describeObject", name: "Product" }, + { call: "describeObject", name: "Author" }, + { call: "describeObject", name: "TenantNotes" }, + { call: "describeObject", name: "Empty" }, + { call: "readObjectSource", name: "Article" }, + { call: "readObjectSource", name: "Product" }, + { call: "readObjectSource", name: "TenantNotes" }, + { call: "readObjectSource", name: "TenantNotesAuto" }, + { call: "readObjectSource", name: "Empty" }, + { call: "getHealth" }, + { call: "getOverview" }, + { call: "getTableStats" }, + { call: "getIndexStats" }, +]; + +/** The reads that never search: the same on every version. */ +const READS: readonly WeaviateStep[] = [ + "GET /v1/meta", + "GET /v1/schema", + "GET /v1/schema/Article", + "GET /v1/schema/Article/shards", + "GET /v1/schema/TenantNotes/tenants", + "GET /v1/schema/TenantNotes/tenants/acme", + "GET /v1/schema/TenantNotes/tenants/initech", + "GET /v1/aliases", + "GET /v1/aliases/Articles", + "GET /v1/nodes", + "GET /v1/nodes?output=verbose", + "GET /v1/nodes/Article?output=verbose", + "GET /v1/objects?class=Article&limit=3", + "GET /v1/objects?class=Article&limit=2&include=vector", + "GET /v1/objects?class=Product&limit=1&include=vector", + "GET /v1/objects?class=Author&limit=2", + "GET /v1/objects?class=Empty", + "GET /v1/objects?class=EdgeValues&limit=8", + `GET /v1/objects/Article/${ARTICLE_ID}`, + `GET /v1/objects/Article/${ARTICLE_ID}?include=vector`, + "GET /v1/objects/Article/00000000-0000-0000-0000-000000000000", + "GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", + "GET /v1/objects?class=TenantNotes&limit=2", + "GET /v1/objects?class=TenantNotes&limit=2&tenant=initech", + "GET /v1/objects?class=TenantNotesAuto&limit=2&tenant=umbrella", + "GET /v1/objects?class=Missing&limit=2", + "GET /v1/objects?class=Author&limit=2&offset=0", + "GET /v1/objects?class=Author&limit=2&offset=2", + "GET /v1/objects?class=Author&limit=2&sort=name", + "GET /v1/objects?class=Author&limit=2&after=00000000-0000-0000-0000-000000000000", + "GET /v1/schema/Missing", +].map((text) => ({ call: "query", text }) as const); + +/** The searches and aggregates, written in the REST shape on every server. */ +const SEARCHES: readonly WeaviateStep[] = [ + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 3, "returnProperties": ["title", "wordCount"], "returnMetadata": ["score"]}', + 'POST /v1/search/Article/bm25 {"query": "vector", "where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}, "limit": 2, "returnProperties": ["title", "category"]}', + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 2}', + `POST /v1/search/Article/near-vector {"vector": ${v}, "limit": 2, "returnProperties": ["title"], "returnMetadata": ["distance"]}`, + `POST /v1/search/Article/near-vector {"vector": ${v}, "limit": 1, "includeVector": true}`, + `POST /v1/search/Article/near-object {"id": "${ARTICLE_ID}", "limit": 2, "returnProperties": ["title"], "returnMetadata": ["distance"]}`, + 'POST /v1/search/Article/hybrid {"query": "vector", "alpha": 0, "limit": 2, "returnProperties": ["title"]}', + 'POST /v1/search/Product/near-vector {"vector": [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8], "targetVector": "image", "limit": 1, "returnProperties": ["name"]}', + 'POST /v1/search/TenantNotes/bm25 {"query": "note", "tenant": "acme", "limit": 2}', + 'POST /v1/search/EdgeValues/bm25 {"query": "9007199254740991", "returnProperties": ["label", "big"]}', + 'POST /v1/search/Product/bm25 {"query": "product", "limit": 2, "returnProperties": ["name"]}', + 'POST /v1/search/Missing/bm25 {"query": "x"}', + "POST /v1/aggregate/Article {}", + "POST /v1/aggregate/Article", + 'POST /v1/aggregate/Article {"groupBy": "category"}', + 'POST /v1/aggregate/TenantNotes {"tenant": "acme"}', + 'POST /v1/aggregate/TenantNotes {"tenant": "initech"}', + "POST /v1/aggregate/Empty {}", + 'POST /v1/aggregate/Article {"where": {"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}}', + 'POST /v1/aggregate/Article {"where": {"operator": "And", "operands": [{"path": ["published"], "operator": "Equal", "valueBoolean": true}, {"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}]}}', + 'POST /v1/search/Article/bm25 {"query": "vector", "where": {"path": ["tags"], "operator": "ContainsAny", "valueTextArray": ["graph", "shard"]}, "limit": 50, "returnProperties": ["title"]}', +].map((text) => ({ call: "query", text }) as const); + +/** What is refused before anything is sent: a fixture of these holds no request at all. */ +const REFUSALS: readonly WeaviateStep[] = [ + 'POST /v1/search/Article/hybrid {"query": "vector", "alpha": 0.5}', + 'POST /v1/search/Article/hybrid {"query": "vector"}', + 'POST /v1/search/Article/bm25 {"query": "x", "wher": {}}', + 'POST /v1/search/Article/near-text {"concepts": ["x"]}', + "DELETE /v1/schema/Article", + "POST /v1/objects {}", + "GET /v1/backups/filesystem", + "GET /v1/objects?class=TenantNotes&limit=2&tenant=nobody", +].map((text) => ({ call: "query", text }) as const); + +export const WEAVIATE_SCENARIOS: readonly WeaviateScenario[] = [ + { name: "surface", service: "weaviate", credential: "none", steps: SURFACE }, + { name: "reads", service: "weaviate", credential: "none", steps: READS }, + { name: "searches", service: "weaviate", credential: "none", steps: SEARCHES }, + { name: "refusals", service: "weaviate", credential: "none", steps: REFUSALS }, + { name: "surface", service: "weaviate-1-38", credential: "none", steps: SURFACE }, + { name: "searches", service: "weaviate-1-38", credential: "none", steps: SEARCHES }, + { name: "surface", service: "weaviate-1-37", credential: "none", steps: SURFACE }, + { name: "reads", service: "weaviate-1-37", credential: "none", steps: READS }, + { name: "searches", service: "weaviate-1-37", credential: "none", steps: SEARCHES }, + { name: "surface", service: "weaviate-nographql", credential: "none", steps: SURFACE }, + { name: "searches", service: "weaviate-nographql", credential: "none", steps: SEARCHES }, + { + name: "reader", + service: "weaviate-auth", + credential: "reader", + steps: [ + { call: "connectWarnings" }, + { call: "listObjects" }, + { call: "readObjectSource", name: "Article" }, + { call: "getOverview" }, + { call: "getTableStats" }, + { call: "query", text: "GET /v1/objects?class=Article&limit=2" }, + { call: "query", text: 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 2}' }, + { call: "query", text: "POST /v1/aggregate/Article {}" }, + ], + }, + { name: "root", service: "weaviate-auth", credential: "root", steps: [{ call: "listObjects" }] }, + { name: "wrong-key", service: "weaviate-auth", credential: "wrong", steps: [] }, + { name: "no-key", service: "weaviate-auth", credential: "none", steps: [] }, + { + name: "reader", + service: "weaviate-tls", + credential: "reader", + ssl: "verify-ca", + steps: [{ call: "listObjects" }, { call: "query", text: "GET /v1/objects?class=Article&limit=1" }], + }, + { name: "plain-to-tls", service: "weaviate-tls", credential: "none", ssl: "disable", steps: [] }, +]; + +/** A scenario's fixture path under tests/fixtures/weaviate/. */ +export function scenarioFile(scenario: WeaviateScenario): string { + return `${scenario.service}/${scenario.name}.json`; +} diff --git a/tests/unit/db/compatibility.test.ts b/tests/unit/db/compatibility.test.ts index e9419b413a..8bb6385076 100644 --- a/tests/unit/db/compatibility.test.ts +++ b/tests/unit/db/compatibility.test.ts @@ -512,9 +512,19 @@ describe("wire-compatibility registry", () => { // The one place these numerals live. A new provider moves them here and nowhere else, and the derived // assertions around this test say how the counts relate. expect([SHIPPED_DATABASE_TYPES.length, EXTERNAL_DATABASE_TYPES.length, WIRE_COMPATIBLE_ENGINES.length]).toEqual([ - 42, 41, 27, + 43, 42, 27, ]); - expect(connectableProductCount()).toBe(68); + expect(connectableProductCount()).toBe(69); + }); + + test("the Weaviate row of each record (#1566)", () => { + expect(SHIPPED_DATABASE_TYPES).toContain("weaviate"); + expect(EXTERNAL_DATABASE_TYPES).toContain("weaviate"); + // As Qdrant's: every console request is a read and the provider keeps the mode; no file to read. + expect(READ_ONLY_ENFORCED.weaviate).toBe(true); + expect(READS_FILE_ACCESS_POSTURE.weaviate).toBe(false); + // As Milvus's and Qdrant's: list_connections and inspect_schema; run_read_query refuses it (no queryReadOnly). + expect(MCP_EXPOSABLE.weaviate).toBe(true); }); test("the Apache Spark row of each record (#1736)", () => { diff --git a/tests/unit/db/connection-form/golden/bigquery.txt b/tests/unit/db/connection-form/golden/bigquery.txt index 782bec9df5..178add8af7 100644 --- a/tests/unit/db/connection-form/golden/bigquery.txt +++ b/tests/unit/db/connection-form/golden/bigquery.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=password] "Service-account key JSON or access token" input#password type="password" placeholder="key JSON, a ya29… token, or empty" describedby="password-hint" p#password-hint "The whole key file's JSON, or a bearer token. Empty uses the server's own credentials, where the deployment enables them." diff --git a/tests/unit/db/connection-form/golden/cassandra.txt b/tests/unit/db/connection-form/golden/cassandra.txt index d97f030380..11708d04cf 100644 --- a/tests/unit/db/connection-form/golden/cassandra.txt +++ b/tests/unit/db/connection-form/golden/cassandra.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/clickhouse.txt b/tests/unit/db/connection-form/golden/clickhouse.txt index 0a8d22a798..72207b87cd 100644 --- a/tests/unit/db/connection-form/golden/clickhouse.txt +++ b/tests/unit/db/connection-form/golden/clickhouse.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=host] "Host & Instance" @@ -132,6 +133,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=connectionString] "Connection URI" diff --git a/tests/unit/db/connection-form/golden/couchbase.txt b/tests/unit/db/connection-form/golden/couchbase.txt index d7cd12cdfa..85aa4a0f64 100644 --- a/tests/unit/db/connection-form/golden/couchbase.txt +++ b/tests/unit/db/connection-form/golden/couchbase.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=host] "Host & Instance" @@ -132,6 +133,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=connectionString] "Connection URI" diff --git a/tests/unit/db/connection-form/golden/databend.txt b/tests/unit/db/connection-form/golden/databend.txt index 09af4e8f0d..5baf8389bd 100644 --- a/tests/unit/db/connection-form/golden/databend.txt +++ b/tests/unit/db/connection-form/golden/databend.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/db2.txt b/tests/unit/db/connection-form/golden/db2.txt index 8f5161c1d9..4754ca40c4 100644 --- a/tests/unit/db/connection-form/golden/db2.txt +++ b/tests/unit/db/connection-form/golden/db2.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/druid.txt b/tests/unit/db/connection-form/golden/druid.txt index 1c0ff365e0..718a557a3d 100644 --- a/tests/unit/db/connection-form/golden/druid.txt +++ b/tests/unit/db/connection-form/golden/druid.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/duckdb.txt b/tests/unit/db/connection-form/golden/duckdb.txt index fc2b62a34c..3e896d4e9e 100644 --- a/tests/unit/db/connection-form/golden/duckdb.txt +++ b/tests/unit/db/connection-form/golden/duckdb.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=database] "Database File Path" input#database type=none placeholder="/path/to/database file" describedby=none button "Cancel" diff --git a/tests/unit/db/connection-form/golden/elasticsearch.txt b/tests/unit/db/connection-form/golden/elasticsearch.txt index 13ee97bb62..170740762a 100644 --- a/tests/unit/db/connection-form/golden/elasticsearch.txt +++ b/tests/unit/db/connection-form/golden/elasticsearch.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/etcd.txt b/tests/unit/db/connection-form/golden/etcd.txt index a6178722cc..e0c9fddf0a 100644 --- a/tests/unit/db/connection-form/golden/etcd.txt +++ b/tests/unit/db/connection-form/golden/etcd.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/firestore.txt b/tests/unit/db/connection-form/golden/firestore.txt index 4b8fe0e36f..0e4c874d45 100644 --- a/tests/unit/db/connection-form/golden/firestore.txt +++ b/tests/unit/db/connection-form/golden/firestore.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=password] "Service-account key, ADC JSON or access token" input#password type="password" placeholder="***" describedby="password-hint" p#password-hint "Studio reads as this credential's IAM identity, and Firebase Security Rules do not apply to it. Grant a dedicated service account roles/datastore.viewer and paste its key. Every read Studio sends is billed to the project; docs/providers/firestore.md lists what each action reads. A pasted access token lasts about an hour. Leave this empty on an emulator server, or for an operator-seeded connection that uses the server's own identity." diff --git a/tests/unit/db/connection-form/golden/influxdb.txt b/tests/unit/db/connection-form/golden/influxdb.txt index 93b4df37a5..18f488cf9e 100644 --- a/tests/unit/db/connection-form/golden/influxdb.txt +++ b/tests/unit/db/connection-form/golden/influxdb.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/influxdb3.txt b/tests/unit/db/connection-form/golden/influxdb3.txt index 9f14064891..4229236cf2 100644 --- a/tests/unit/db/connection-form/golden/influxdb3.txt +++ b/tests/unit/db/connection-form/golden/influxdb3.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/kafka.txt b/tests/unit/db/connection-form/golden/kafka.txt index 3d68cc59f9..60f71a5382 100644 --- a/tests/unit/db/connection-form/golden/kafka.txt +++ b/tests/unit/db/connection-form/golden/kafka.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/kubernetes.txt b/tests/unit/db/connection-form/golden/kubernetes.txt index 4510494d8f..4bdf0c3e42 100644 --- a/tests/unit/db/connection-form/golden/kubernetes.txt +++ b/tests/unit/db/connection-form/golden/kubernetes.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Import kubeconfig" label[for=host] "API server" input#host type=none placeholder="localhost" describedby="host-hint" diff --git a/tests/unit/db/connection-form/golden/libredb.txt b/tests/unit/db/connection-form/golden/libredb.txt index 04ce40f99d..49a01def1d 100644 --- a/tests/unit/db/connection-form/golden/libredb.txt +++ b/tests/unit/db/connection-form/golden/libredb.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=database] "Database File Path" input#database type=none placeholder="/path/to/database file" describedby=none button "Cancel" diff --git a/tests/unit/db/connection-form/golden/libsql.txt b/tests/unit/db/connection-form/golden/libsql.txt index 7bba94927d..5b98a13b1f 100644 --- a/tests/unit/db/connection-form/golden/libsql.txt +++ b/tests/unit/db/connection-form/golden/libsql.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=host] "Host & Instance" @@ -132,6 +133,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=connectionString] "Connection URI" diff --git a/tests/unit/db/connection-form/golden/milvus.txt b/tests/unit/db/connection-form/golden/milvus.txt index 9190ed3790..b8f20a7144 100644 --- a/tests/unit/db/connection-form/golden/milvus.txt +++ b/tests/unit/db/connection-form/golden/milvus.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/modbus.txt b/tests/unit/db/connection-form/golden/modbus.txt index 52db1a27c0..0a3f58a34f 100644 --- a/tests/unit/db/connection-form/golden/modbus.txt +++ b/tests/unit/db/connection-form/golden/modbus.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/mongodb.txt b/tests/unit/db/connection-form/golden/mongodb.txt index 66da1a04a5..9d7bbcf4f9 100644 --- a/tests/unit/db/connection-form/golden/mongodb.txt +++ b/tests/unit/db/connection-form/golden/mongodb.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=host] "Host & Instance" @@ -135,6 +136,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" button "Host / Port" button "Connection String" label[for=connectionString] "Connection URI" diff --git a/tests/unit/db/connection-form/golden/mqtt.txt b/tests/unit/db/connection-form/golden/mqtt.txt index 7d39443733..27b1c0d18d 100644 --- a/tests/unit/db/connection-form/golden/mqtt.txt +++ b/tests/unit/db/connection-form/golden/mqtt.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/mssql.txt b/tests/unit/db/connection-form/golden/mssql.txt index 9eafdb7504..4140fc4429 100644 --- a/tests/unit/db/connection-form/golden/mssql.txt +++ b/tests/unit/db/connection-form/golden/mssql.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none @@ -131,6 +132,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/mtconnect.txt b/tests/unit/db/connection-form/golden/mtconnect.txt index 917cf970f7..42319563af 100644 --- a/tests/unit/db/connection-form/golden/mtconnect.txt +++ b/tests/unit/db/connection-form/golden/mtconnect.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/mysql.txt b/tests/unit/db/connection-form/golden/mysql.txt index 329a9fd2d6..f305acf501 100644 --- a/tests/unit/db/connection-form/golden/mysql.txt +++ b/tests/unit/db/connection-form/golden/mysql.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/neo4j.txt b/tests/unit/db/connection-form/golden/neo4j.txt index 3a819ced53..ad9bf54341 100644 --- a/tests/unit/db/connection-form/golden/neo4j.txt +++ b/tests/unit/db/connection-form/golden/neo4j.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/netconf.txt b/tests/unit/db/connection-form/golden/netconf.txt index abfb1f465a..3699892987 100644 --- a/tests/unit/db/connection-form/golden/netconf.txt +++ b/tests/unit/db/connection-form/golden/netconf.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/opcua.txt b/tests/unit/db/connection-form/golden/opcua.txt index c2a0aa37ad..d0c2b5c4f5 100644 --- a/tests/unit/db/connection-form/golden/opcua.txt +++ b/tests/unit/db/connection-form/golden/opcua.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Endpoint URL" input#host type=none placeholder="opc.tcp://plc.example.net:4840/" describedby="host-hint" p#host-hint "The endpoint exactly as you type it. This is the only address dialled: a server may advertise another, and OPC PLC advertises its own container name, which resolves nowhere." diff --git a/tests/unit/db/connection-form/golden/opensearch.txt b/tests/unit/db/connection-form/golden/opensearch.txt index b44cc868ca..add1fed2be 100644 --- a/tests/unit/db/connection-form/golden/opensearch.txt +++ b/tests/unit/db/connection-form/golden/opensearch.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/oracle.txt b/tests/unit/db/connection-form/golden/oracle.txt index 98ccfa4577..d42e745899 100644 --- a/tests/unit/db/connection-form/golden/oracle.txt +++ b/tests/unit/db/connection-form/golden/oracle.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none @@ -131,6 +132,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/oxia.txt b/tests/unit/db/connection-form/golden/oxia.txt index 226d3a9cab..8c25d1417d 100644 --- a/tests/unit/db/connection-form/golden/oxia.txt +++ b/tests/unit/db/connection-form/golden/oxia.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/postgres.txt b/tests/unit/db/connection-form/golden/postgres.txt index 7bcb23b65e..b3b2bb5a24 100644 --- a/tests/unit/db/connection-form/golden/postgres.txt +++ b/tests/unit/db/connection-form/golden/postgres.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/prometheus.txt b/tests/unit/db/connection-form/golden/prometheus.txt index 26441cf403..0419fc7091 100644 --- a/tests/unit/db/connection-form/golden/prometheus.txt +++ b/tests/unit/db/connection-form/golden/prometheus.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/qdrant.txt b/tests/unit/db/connection-form/golden/qdrant.txt index 92d4c25f47..653fc7c3f5 100644 --- a/tests/unit/db/connection-form/golden/qdrant.txt +++ b/tests/unit/db/connection-form/golden/qdrant.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/rabbitmq.txt b/tests/unit/db/connection-form/golden/rabbitmq.txt index dc624c7881..a815b2112a 100644 --- a/tests/unit/db/connection-form/golden/rabbitmq.txt +++ b/tests/unit/db/connection-form/golden/rabbitmq.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host" input#host type=none placeholder="localhost" describedby="host-hint" label[for=port] "Management port" diff --git a/tests/unit/db/connection-form/golden/redis.txt b/tests/unit/db/connection-form/golden/redis.txt index 1606763235..f61df5a993 100644 --- a/tests/unit/db/connection-form/golden/redis.txt +++ b/tests/unit/db/connection-form/golden/redis.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/s3.txt b/tests/unit/db/connection-form/golden/s3.txt index 647af6c272..8fd089c083 100644 --- a/tests/unit/db/connection-form/golden/s3.txt +++ b/tests/unit/db/connection-form/golden/s3.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Endpoint host" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/snmp.txt b/tests/unit/db/connection-form/golden/snmp.txt index e0ff2e0b29..135cb276fc 100644 --- a/tests/unit/db/connection-form/golden/snmp.txt +++ b/tests/unit/db/connection-form/golden/snmp.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/snowflake.txt b/tests/unit/db/connection-form/golden/snowflake.txt index 5929337e28..0a91f130af 100644 --- a/tests/unit/db/connection-form/golden/snowflake.txt +++ b/tests/unit/db/connection-form/golden/snowflake.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Account" input#host type=none placeholder="myorg-myaccount" describedby="host-hint" p#host-hint "An account identifier such as myorg-myaccount, or its https:// URL." diff --git a/tests/unit/db/connection-form/golden/spark.txt b/tests/unit/db/connection-form/golden/spark.txt index 546c40a651..1f4e4dd4df 100644 --- a/tests/unit/db/connection-form/golden/spark.txt +++ b/tests/unit/db/connection-form/golden/spark.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host" input#host type=none placeholder="localhost" describedby="host-hint" label[for=port] "Port" diff --git a/tests/unit/db/connection-form/golden/sparkplug.txt b/tests/unit/db/connection-form/golden/sparkplug.txt index 9c70d487ae..93db976c88 100644 --- a/tests/unit/db/connection-form/golden/sparkplug.txt +++ b/tests/unit/db/connection-form/golden/sparkplug.txt @@ -60,6 +60,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby="host-hint" input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/sqlite.txt b/tests/unit/db/connection-form/golden/sqlite.txt index 09bcb29e44..784ae9d4df 100644 --- a/tests/unit/db/connection-form/golden/sqlite.txt +++ b/tests/unit/db/connection-form/golden/sqlite.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=database] "Database File Path" input#database type=none placeholder="/path/to/database file" describedby=none button "Cancel" diff --git a/tests/unit/db/connection-form/golden/trino.txt b/tests/unit/db/connection-form/golden/trino.txt index 19101bc180..f80ad6d0ac 100644 --- a/tests/unit/db/connection-form/golden/trino.txt +++ b/tests/unit/db/connection-form/golden/trino.txt @@ -57,6 +57,7 @@ button "Apache Spark" button "MTConnect" button "Modbus" button "NETCONF" +button "Weaviate" label[for=host] "Host & Instance" input#host type=none placeholder="localhost" describedby=none input#port type=none placeholder=none describedby=none diff --git a/tests/unit/db/connection-form/golden/weaviate.txt b/tests/unit/db/connection-form/golden/weaviate.txt new file mode 100644 index 0000000000..47ed3d5994 --- /dev/null +++ b/tests/unit/db/connection-form/golden/weaviate.txt @@ -0,0 +1,82 @@ +== discrete +p#none "Configure your database connection parameters securely." +button "Paste URL" +label[for=name] "Connection Name" +input#name type=none placeholder="My Database" describedby=none +label[for=queryTimeout] "Query Timeout (ms)" +input#queryTimeout type="number" placeholder="60000" describedby="queryTimeout-hint" +p#queryTimeout-hint "Leave blank to use the default of 60 seconds." +label[for=none] "Do not read the object list on connect" +input#skipObjectScan type="checkbox" placeholder=none describedby="skipObjectScan-hint" +p#skipObjectScan-hint "The editor still works. The object panel offers a load action instead." +label[for=none] "Read-only" +input#readOnly type="checkbox" placeholder=none describedby="readOnly-hint" +p#readOnly-hint "Writes, value edits and maintenance are refused on this connection. You can turn this off here, so on your own connection it is a safety rail, not a permission." +label[for=none] "Environment" +button "PROD" +button "STAGING" +button "DEV" +button "LOCAL" +button "Other" +button "PostgreSQL" +button "MySQL" +button "SQLite" +button "Oracle" +button "SQL Server" +button "MongoDB" +button "Couchbase" +button "Redis" +button "LibreDB" +button "ClickHouse" +button "Apache Druid" +button "Elasticsearch" +button "OpenSearch" +button "Trino" +button "Apache Cassandra" +button "libSQL" +button "DuckDB" +button "Prometheus" +button "Apache Kafka" +button "etcd" +button "Db2 LUW" +button "Neo4j" +button "Milvus" +button "Qdrant" +button "InfluxDB (InfluxQL)" +button "InfluxDB 3 (SQL)" +button "Oxia" +button "Databend" +button "BigQuery" +button "S3-compatible object storage" +button "Kubernetes" +button "MQTT" +button "Firestore" +button "RabbitMQ" +button "Snowflake" +button "OPC UA" +button "SNMP" +button "Sparkplug B" +button "Apache Spark" +button "MTConnect" +button "Modbus" +button "NETCONF" +button "Weaviate" +label[for=host] "Host & Instance" +input#host type=none placeholder="localhost" describedby="host-hint" +input#port type=none placeholder=none describedby=none +p#host-hint "A name or address, or a pasted http:// or https:// address such as a Weaviate Cloud endpoint, which is split into Host and Port. Studio dials this port only, never Weaviate's gRPC port 50051." +label[for=password] "API key or token" +input#password type="password" placeholder="***" describedby="password-hint" +p#password-hint "Weaviate receives the API key or OIDC access token on every request, so a key needs an SSL mode other than disable, unless the host is this machine or an SSH tunnel carries the connection. A key for a user with only the viewer role is the safest choice." +button "SSL / TLS" +button "SSH Tunnel" +button "Cancel" +button "Test Connection" +button "Establish Connection" +== build +{"color":"#6b7280","environment":"other","host":"localhost","name":"weaviate-connection","password":"","port":8080,"type":"weaviate"} +== seed foreign fields +[{"path":["securityMode"],"message":"securityMode is OPC UA only: no other engine's provider reads it, so this connection would be listed as carrying it and would not. Remove securityMode from this connection."},{"path":["serverCertificateThumbprint"],"message":"serverCertificateThumbprint is OPC UA only: no other engine's provider reads it, so this connection would be listed as carrying it and would not. Remove serverCertificateThumbprint from this connection."},{"path":["securityPolicyUri"],"message":"securityPolicyUri is OPC UA only: no other engine's provider reads it, so this connection would be listed as carrying it and would not. Remove securityPolicyUri from this connection."},{"path":["clientCertificatePath"],"message":"clientCertificatePath is OPC UA only: no other engine's provider reads it, so this connection would be listed as carrying it and would not. Remove clientCertificatePath from this connection."},{"path":["clientPrivateKeyPath"],"message":"clientPrivateKeyPath is OPC UA only: no other engine's provider reads it, so this connection would be listed as carrying it and would not. Remove clientPrivateKeyPath from this connection."},{"path":["apiKeyId"],"message":"apiKeyId and apiKeySecret are Elasticsearch-only. OpenSearch (and every other engine) refuses the pair: nothing here has measured whether OpenSearch's security plugin accepts Authorization: ApiKey, so a seed that carries it is rejected rather than listed as a connection that silently falls back to user/password."}] +[{"path":["apiKeySecret"],"message":"apiKeyId and apiKeySecret are Elasticsearch-only. OpenSearch (and every other engine) refuses the pair: nothing here has measured whether OpenSearch's security plugin accepts Authorization: ApiKey, so a seed that carries it is rejected rather than listed as a connection that silently falls back to user/password."}] +throws "Seed connection \"test-pg\" of type \"weaviate\" carries an Elasticsearch API key pair. The pair is Elasticsearch-only; OpenSearch's security plugin has not been measured to accept Authorization: ApiKey, so the seed is refused rather than projected as a connection that silently falls back to user/password." +ok diff --git a/tests/unit/db/connection-form/isolation.test.ts b/tests/unit/db/connection-form/isolation.test.ts index bfb16c1ce5..017f903ba3 100644 --- a/tests/unit/db/connection-form/isolation.test.ts +++ b/tests/unit/db/connection-form/isolation.test.ts @@ -83,7 +83,7 @@ const golden = (key: string): string => readFileSync(join(GOLDEN_DIR, `${key}.tx describe("one engine's connection fields cannot reach another engine's form", () => { test("one form per shipped type id", () => { - expect(FORM_KEYS.length).toBe(42); + expect(FORM_KEYS.length).toBe(43); }); test("the groups replace every engine while holding every other engine real", () => { diff --git a/tests/unit/db/connection-string-records.test.ts b/tests/unit/db/connection-string-records.test.ts index cf0303c0d9..0a057bc361 100644 --- a/tests/unit/db/connection-string-records.test.ts +++ b/tests/unit/db/connection-string-records.test.ts @@ -180,6 +180,7 @@ describe("CONNECTION_STRING_ACCEPTED against each provider's own declaration (Sp "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", diff --git a/tests/unit/db/connection-string/census.test.ts b/tests/unit/db/connection-string/census.test.ts index 287e9d7134..d79acb6067 100644 --- a/tests/unit/db/connection-string/census.test.ts +++ b/tests/unit/db/connection-string/census.test.ts @@ -44,7 +44,7 @@ const FAMILIES: Readonly> = { ], stream: ["kafka", "rabbitmq"], timeseries: ["prometheus"], - vector: ["milvus", "qdrant"], + vector: ["milvus", "qdrant", "weaviate"], }; function placement(id: string): string { diff --git a/tests/unit/db/connection-string/docs.test.ts b/tests/unit/db/connection-string/docs.test.ts index b7c0dadb0e..110cfbd3d1 100644 --- a/tests/unit/db/connection-string/docs.test.ts +++ b/tests/unit/db/connection-string/docs.test.ts @@ -71,7 +71,7 @@ const sectionOf = (type: DatabaseType): string => { describe("each provider document's Connection string subsection", () => { test("covers every engine the registry has a row for", () => { - expect(ENGINES).toHaveLength(42); + expect(ENGINES).toHaveLength(43); }); for (const type of ENGINES) { diff --git a/tests/unit/db/connection-string/golden/weaviate.txt b/tests/unit/db/connection-string/golden/weaviate.txt new file mode 100644 index 0000000000..0eef71c4c4 --- /dev/null +++ b/tests/unit/db/connection-string/golden/weaviate.txt @@ -0,0 +1,3 @@ +scheme => undefined +seed => [] +seed => [] diff --git a/tests/unit/db/connection-string/isolation.test.ts b/tests/unit/db/connection-string/isolation.test.ts index dd0b3a98c7..d156de711a 100644 --- a/tests/unit/db/connection-string/isolation.test.ts +++ b/tests/unit/db/connection-string/isolation.test.ts @@ -86,7 +86,7 @@ afterAll(() => { describe("one engine's connection string module cannot reach another engine's output", () => { test("one row per shipped type id", () => { - expect(IDS.length).toBe(42); + expect(IDS.length).toBe(43); }); test("the groups replace every engine while holding every other engine real", () => { diff --git a/tests/unit/db/container-path-shapes-capability.test.ts b/tests/unit/db/container-path-shapes-capability.test.ts index 246ec5882b..ee7337369a 100644 --- a/tests/unit/db/container-path-shapes-capability.test.ts +++ b/tests/unit/db/container-path-shapes-capability.test.ts @@ -91,6 +91,7 @@ const EXPECTED_CONTAINER_PATH_SHAPES: Readonly< etcd: "absent", neo4j: "absent", qdrant: "absent", + weaviate: "absent", // No container level (R16): its tables are top-level objects of the session database, the Qdrant shape. influxdb3: "absent", oxia: "absent", diff --git a/tests/unit/db/destructive-commands.test.ts b/tests/unit/db/destructive-commands.test.ts index fc3047d06d..24619f80ee 100644 --- a/tests/unit/db/destructive-commands.test.ts +++ b/tests/unit/db/destructive-commands.test.ts @@ -364,7 +364,7 @@ describe("isDestructiveNonSqlQuery", () => { describe("vocabularyDecidesAlone", () => { // The rows the gate reads without its SQL keyword test in front. MongoDB and Redis keep that // test as a backstop; a type with no row is read by the SQL half entirely. - test("is true for prometheus, kafka, etcd, neo4j, milvus, qdrant, influxdb, oxia, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect and modbus and for no other type", () => { + test("is true for prometheus, kafka, etcd, neo4j, milvus, qdrant, weaviate, influxdb, oxia, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect and modbus and for no other type", () => { expect(SHIPPED_DATABASE_TYPES.filter((type) => vocabularyDecidesAlone(type))).toEqual([ "prometheus", "kafka", @@ -372,6 +372,7 @@ describe("vocabularyDecidesAlone", () => { "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "oxia", "s3", @@ -394,7 +395,7 @@ describe("vocabularyDecidesAlone", () => { }); describe("NON_SQL_DESTRUCTIVE_VOCABULARY", () => { - test("carries a row for exactly the eighteen types whose text is not SQL", () => { + test("carries a row for exactly the nineteen types whose text is not SQL", () => { expect(Object.keys(NON_SQL_DESTRUCTIVE_VOCABULARY).sort()).toEqual([ "etcd", "firestore", @@ -417,6 +418,7 @@ describe("NON_SQL_DESTRUCTIVE_VOCABULARY", () => { "s3", "snmp", "sparkplug", + "weaviate", ]); }); @@ -522,11 +524,12 @@ describe("vocabularySendsToModel", () => { // What the dialog did for every engine before the field existed, but for etcd, whose row keeps its statements, // values included, on this deployment (#1089 E10). - test("keeps etcd's, Milvus's, Qdrant's, InfluxDB's, Oxia's, S3's, Kubernetes's, MQTT's, Firestore's, RabbitMQ's, OPC UA's, MTConnect's, Modbus's and SNMP's statements from the AI analysis, and no other shipped type's", () => { + test("keeps etcd's, Milvus's, Qdrant's, Weaviate's, InfluxDB's, Oxia's, S3's, Kubernetes's, MQTT's, Firestore's, RabbitMQ's, OPC UA's, MTConnect's, Modbus's and SNMP's statements from the AI analysis, and no other shipped type's", () => { expect(SHIPPED_DATABASE_TYPES.filter((type) => !vocabularySendsToModel(type))).toEqual([ "etcd", "milvus", "qdrant", + "weaviate", "influxdb", "oxia", "s3", @@ -632,8 +635,17 @@ describe("statementRefusal and the console text bound", () => { remove = () => {}; }); - test("only milvus's, qdrant's, influxdb's, oxia's, s3's, kubernetes's and firestore's rows declare a refusal and a bound, and redis's a refusal alone", () => { - const declaring: readonly string[] = ["milvus", "qdrant", "influxdb", "oxia", "s3", "kubernetes", "firestore"]; + test("only milvus's, qdrant's, weaviate's, influxdb's, oxia's, s3's, kubernetes's and firestore's rows declare a refusal and a bound, and redis's a refusal alone", () => { + const declaring: readonly string[] = [ + "milvus", + "qdrant", + "weaviate", + "influxdb", + "oxia", + "s3", + "kubernetes", + "firestore", + ]; for (const [type, row] of Object.entries(NON_SQL_DESTRUCTIVE_VOCABULARY)) { if (declaring.includes(type)) continue; expect(row?.maxTextBytes).toBeUndefined(); diff --git a/tests/unit/db/execution-ui/census.test.ts b/tests/unit/db/execution-ui/census.test.ts index ec32f592bc..685428cea5 100644 --- a/tests/unit/db/execution-ui/census.test.ts +++ b/tests/unit/db/execution-ui/census.test.ts @@ -43,7 +43,7 @@ const FAMILIES: Readonly> = { ], stream: ["kafka", "rabbitmq"], timeseries: ["prometheus"], - vector: ["milvus", "qdrant"], + vector: ["milvus", "qdrant", "weaviate"], }; function placement(id: string): string { diff --git a/tests/unit/db/execution-ui/docs.test.ts b/tests/unit/db/execution-ui/docs.test.ts index 125cad269c..0bff575234 100644 --- a/tests/unit/db/execution-ui/docs.test.ts +++ b/tests/unit/db/execution-ui/docs.test.ts @@ -60,7 +60,7 @@ const sectionOf = (type: DatabaseType): string => { describe("each provider document's Execution UI subsection", () => { test("covers every engine the registry has a row for", () => { - expect(ENGINES).toHaveLength(42); + expect(ENGINES).toHaveLength(43); }); for (const type of ENGINES) { diff --git a/tests/unit/db/execution-ui/golden/weaviate.txt b/tests/unit/db/execution-ui/golden/weaviate.txt new file mode 100644 index 0000000000..c32741406e --- /dev/null +++ b/tests/unit/db/execution-ui/golden/weaviate.txt @@ -0,0 +1,4 @@ +commit => none +consent ticked => {"chips":["same read-only session","500 rows","no time limit"],"sentence":null} +consent unticked => {"sentence":null} +explain => "weaviate" diff --git a/tests/unit/db/execution-ui/isolation.test.ts b/tests/unit/db/execution-ui/isolation.test.ts index 51aeec5bd6..f492cbed79 100644 --- a/tests/unit/db/execution-ui/isolation.test.ts +++ b/tests/unit/db/execution-ui/isolation.test.ts @@ -93,7 +93,7 @@ afterAll(() => { describe("one engine's execution UI module cannot reach another engine's output", () => { test("one row per shipped type id", () => { - expect(IDS.length).toBe(42); + expect(IDS.length).toBe(43); }); test("the groups replace every engine while holding every other engine real", () => { diff --git a/tests/unit/db/firestore/docs-listings.test.ts b/tests/unit/db/firestore/docs-listings.test.ts index 820552f0e0..c7d87cb670 100644 --- a/tests/unit/db/firestore/docs-listings.test.ts +++ b/tests/unit/db/firestore/docs-listings.test.ts @@ -66,7 +66,7 @@ describe("docs/ADDING_A_PROVIDER.md", () => { }); test("the driver-free ids count bigquery and firestore", () => { - expect(guide).toContain("twenty shipped ids do:"); + expect(guide).toContain("twenty-one shipped ids do:"); expect(guide).toContain("`databend`, `kubernetes`, `bigquery`, `firestore`, `rabbitmq` and `snowflake`"); }); diff --git a/tests/unit/db/influxdb/security-control.test.ts b/tests/unit/db/influxdb/security-control.test.ts index b381084209..ff44744a73 100644 --- a/tests/unit/db/influxdb/security-control.test.ts +++ b/tests/unit/db/influxdb/security-control.test.ts @@ -130,7 +130,7 @@ describe.each(Object.entries(ROWS))("row %s", (id, cited) => { describe("the notes state what the code does", () => { test("Known limits names the InfluxDB (InfluxQL) row among the rows that declare a refusal and a byte bound", () => { expect(SECURITY).toContain( - "The Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18 and 3.20); no other shipped engine declares either.", + "The Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18, 3.20 and 3.25); no other shipped engine declares either.", ); expect(SECURITY).not.toContain("Milvus's and Qdrant's rows declare both"); }); diff --git a/tests/unit/db/maintenance-surface-census.test.ts b/tests/unit/db/maintenance-surface-census.test.ts index a4661b02c7..2d5ec8fbc5 100644 --- a/tests/unit/db/maintenance-surface-census.test.ts +++ b/tests/unit/db/maintenance-surface-census.test.ts @@ -98,6 +98,7 @@ const EXPECTED: Readonly> = { milvus: { tabs: "", tree: "", outsideMaintenanceType: "load,release" }, db2: { tabs: "analyze,optimize", tree: "analyze+vacuum(optimize)", outsideMaintenanceType: "" }, qdrant: NONE, + weaviate: NONE, // Neither offers maintenance (InfluxDB spec I1): both declare `supportsMaintenance: false`. influxdb: NONE, influxdb3: NONE, @@ -138,9 +139,9 @@ describe("every shipped provider's per-row maintenance controls (R46 C3)", () => expect(surfacesOf(provider.getCapabilities(), provider.getLabels())).toEqual(EXPECTED[type]); }); - test("11 of 4041 type-ids offer per-row controls on the two tabs, 10 on the row menus, one outside MaintenanceType", () => { + test("11 of 43 type-ids offer per-row controls on the two tabs, 10 on the row menus, one outside MaintenanceType", () => { const rows = Object.values(EXPECTED); - expect(rows.length).toBe(42); + expect(rows.length).toBe(43); expect(rows.filter((row) => row.tabs !== "").length).toBe(11); expect(rows.filter((row) => row.tree !== "").length).toBe(10); expect(rows.filter((row) => row.outsideMaintenanceType !== "").length).toBe(1); diff --git a/tests/unit/db/migration-ddl/census.test.ts b/tests/unit/db/migration-ddl/census.test.ts index 3d40fb8673..6883f36ae9 100644 --- a/tests/unit/db/migration-ddl/census.test.ts +++ b/tests/unit/db/migration-ddl/census.test.ts @@ -55,6 +55,7 @@ const PLACEMENT: Record = { prometheus: "timeseries/prometheus/migration-ddl", milvus: "vector/milvus/migration-ddl", qdrant: "vector/qdrant/migration-ddl", + weaviate: "vector/weaviate/migration-ddl", }; const REFUSED: DatabaseType[] = [ @@ -71,6 +72,7 @@ const REFUSED: DatabaseType[] = [ "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", diff --git a/tests/unit/db/migration-ddl/golden/weaviate.txt b/tests/unit/db/migration-ddl/golden/weaviate.txt new file mode 100644 index 0000000000..167595a385 --- /dev/null +++ b/tests/unit/db/migration-ddl/golden/weaviate.txt @@ -0,0 +1,8 @@ +-- fixture: full +-- Migration generated at 2026-10-19T12:00:00.000Z +-- Dialect: weaviate +-- Changes: 1 added, 1 removed, 2 modified + +-- Weaviate: Cannot generate table DDL. A collection's properties and vectors are declared through Weaviate's own schema API, not SQL DDL, so there is no column definition to change. +-- fixture: none +-- No schema changes detected. diff --git a/tests/unit/db/milvus/provider-doc.test.ts b/tests/unit/db/milvus/provider-doc.test.ts index 3b0bcd3f5f..acd8bcc3fe 100644 --- a/tests/unit/db/milvus/provider-doc.test.ts +++ b/tests/unit/db/milvus/provider-doc.test.ts @@ -273,7 +273,7 @@ describe("docs/SECURITY.md states Milvus's limits and its plaintext rule", () => expect(bullet).toContain( "A Milvus password or token over no TLS is refused unless the host is a loopback address or `localhost`, or an SSH tunnel carries the connection.", ); - expect(SECURITY).toContain("etcd's, Neo4j's, Milvus's and Qdrant's providers keep the mode today"); + expect(SECURITY).toContain("etcd's, Neo4j's, Milvus's, Qdrant's and Weaviate's providers keep the mode today"); expect(SECURITY).toContain("src/lib/db/providers/vector/milvus/write-policy.ts"); }); }); diff --git a/tests/unit/db/object-edit-expectation.test.ts b/tests/unit/db/object-edit-expectation.test.ts index ae219da512..33a67faba9 100644 --- a/tests/unit/db/object-edit-expectation.test.ts +++ b/tests/unit/db/object-edit-expectation.test.ts @@ -24,8 +24,8 @@ describe("the Phase 3 census expectation", () => { // the two numerals here only say how long that list is. SNMP and Sparkplug B abstain with // the rest: an SNMP object is a value at a numbered place, and a Sparkplug metric's shape is // the birth certificate's, which no client here writes. - expect(EXPECTED_EDIT_ABSTAINERS.length).toBe(38); - expect(EDIT_CENSUS_TYPES.length).toBe(42); + expect(EXPECTED_EDIT_ABSTAINERS.length).toBe(39); + expect(EDIT_CENSUS_TYPES.length).toBe(43); }); test("no pair is written twice", () => { diff --git a/tests/unit/db/oxia/provider-doc.test.ts b/tests/unit/db/oxia/provider-doc.test.ts index ede1b0d23a..5db1e0336c 100644 --- a/tests/unit/db/oxia/provider-doc.test.ts +++ b/tests/unit/db/oxia/provider-doc.test.ts @@ -1007,7 +1007,7 @@ describe("docs/providers/oxia.md quotes what the registered type-id declares (pa "- **Oxia has no authorization.** A token that authenticates reads and writes every namespace, so Studio's read-only mode is a property of what Studio sends (it has no write call at all, row 3.15), never of the token. A standalone server has no authentication. An advertised leader decides where reads go, which row 3.14 bounds, and a Data servers entry is the operator's statement that the token may go there.", ); expect(knownLimit("**A statement the editor refuses is never sent and never written to history.**")).toContain( - "The Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18 and 3.20); no other shipped engine declares either.", + "The Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18, 3.20 and 3.25); no other shipped engine declares either.", ); }); diff --git a/tests/unit/db/qdrant/provider-doc.test.ts b/tests/unit/db/qdrant/provider-doc.test.ts index 6a31ac006c..880fc271c3 100644 --- a/tests/unit/db/qdrant/provider-doc.test.ts +++ b/tests/unit/db/qdrant/provider-doc.test.ts @@ -295,7 +295,7 @@ describe("docs/SECURITY.md states Qdrant's control, its limits and its plaintext expect(bullet).toContain( "A Qdrant API key or JWT over no TLS is refused unless the host is a loopback address or `localhost`, or an SSH tunnel carries the connection.", ); - expect(SECURITY).toContain("etcd's, Neo4j's, Milvus's and Qdrant's providers keep the mode today"); + expect(SECURITY).toContain("etcd's, Neo4j's, Milvus's, Qdrant's and Weaviate's providers keep the mode today"); }); }); diff --git a/tests/unit/db/query-dialects.test.ts b/tests/unit/db/query-dialects.test.ts index f0d40811cb..03b4939905 100644 --- a/tests/unit/db/query-dialects.test.ts +++ b/tests/unit/db/query-dialects.test.ts @@ -49,6 +49,7 @@ describe("QUERY_DIALECTS", () => { "s3", "snmp", "sparkplug", + "weaviate", ]); }); @@ -78,6 +79,13 @@ describe("QUERY_DIALECTS", () => { offersCountQuery: false, offersSqlExport: false, }, + weaviate: { + tabType: "weaviate", + offersColumnProfiling: false, + offersCodeGeneration: false, + offersCountQuery: false, + offersSqlExport: false, + }, // Oxia (SB2-4.4): records of a fixed shape, no profile, model or count statement, and no SQL export. oxia: { tabType: "oxia", @@ -188,7 +196,7 @@ describe("QUERY_DIALECTS", () => { } }); - test("a record may decline the SQL export formats, and only milvus's, qdrant's, oxia's, s3's, rabbitmq's, kubectl's and firestore's do, so every other shipped engine keeps both", () => { + test("a record may decline the SQL export formats, and only milvus's, qdrant's, weaviate's, oxia's, s3's, rabbitmq's, kubectl's and firestore's do, so every other shipped engine keeps both", () => { // `bun run typecheck` is the assertion for the field: this literal compiles only while `DialectSpec` declares // `offersSqlExport`, and bun strips types, so no runtime expect on it could fail. What a declining record does // to the menus is pinned by the export gate's own tests. @@ -204,6 +212,7 @@ describe("QUERY_DIALECTS", () => { if ( dialect === "milvus" || dialect === "qdrant" || + dialect === "weaviate" || dialect === "oxia" || dialect === "s3" || dialect === "rabbitmq" || @@ -232,6 +241,7 @@ describe("registeredDialect, dialectSpec and declaresDialect", () => { "etcd", "milvus", "qdrant", + "weaviate", "oxia", "s3", "firestore", diff --git a/tests/unit/db/rabbitmq/docs-listings.test.ts b/tests/unit/db/rabbitmq/docs-listings.test.ts index f769fd6b5d..82f70a3e96 100644 --- a/tests/unit/db/rabbitmq/docs-listings.test.ts +++ b/tests/unit/db/rabbitmq/docs-listings.test.ts @@ -31,7 +31,7 @@ describe("docs/ADDING_A_PROVIDER.md", () => { }); test("the driver-free ids count rabbitmq", () => { - expect(guide).toContain("twenty shipped ids do:"); + expect(guide).toContain("twenty-one shipped ids do:"); expect(guide).toContain("`databend`, `kubernetes`, `bigquery`, `firestore`, `rabbitmq` and `snowflake`"); }); }); diff --git a/tests/unit/db/result-pagination-capability.test.ts b/tests/unit/db/result-pagination-capability.test.ts index 815010b2cf..2d7caa3aca 100644 --- a/tests/unit/db/result-pagination-capability.test.ts +++ b/tests/unit/db/result-pagination-capability.test.ts @@ -89,6 +89,7 @@ const EXPECTED: Readonly> = Object.freeze({ neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: true, oxia: false, diff --git a/tests/unit/db/s3/provider-doc.test.ts b/tests/unit/db/s3/provider-doc.test.ts index 8dcfa27d00..6ba91c55ef 100644 --- a/tests/unit/db/s3/provider-doc.test.ts +++ b/tests/unit/db/s3/provider-doc.test.ts @@ -1320,10 +1320,10 @@ describe("docs/SECURITY.md: the S3 rows and limits", () => { test("42. the Known limits name S3 where they list the engines, and state S3's own limits", () => { expect(knownLimit("**The HTTP destination guard is opt-in and address-based.**")).toContain( - "Qdrant, InfluxDB (InfluxQL), InfluxDB 3 (SQL), S3-compatible object storage and Kubernetes HTTP requests", + "Qdrant, Weaviate, InfluxDB (InfluxQL), InfluxDB 3 (SQL), S3-compatible object storage and Kubernetes HTTP requests", ); expect(knownLimit("**A statement the editor refuses is never sent and never written to history.**")).toContain( - "The Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18 and 3.20); no other shipped engine declares either.", + "The Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3 and Kubernetes rows declare both (rows 3.11, 3.12, 3.15, 3.18, 3.20 and 3.25); no other shipped engine declares either.", ); const s3 = knownLimit("**S3-compatible object storage is reached over a REST client of Studio's own.**"); expect(s3).toContain("14 minutes of skew were accepted and 20 refused on MinIO, Silo and RustFS"); @@ -1352,7 +1352,7 @@ describe("packaging and listing copy no count gate reads", () => { "packaging/flatpak/org.libredb.Studio.desktop", "packaging/flatpark/org.libredb.Studio.desktop", ]) { - expect(read(file), file).toContain(";Qdrant;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;"); + expect(read(file), file).toContain(";Qdrant;Weaviate;Oxia;S3;ObjectStorage;MinIO;Kubernetes;IDE;"); } }); @@ -1471,7 +1471,7 @@ describe("DOCKERHUB.md", () => { expect(lines[oxia + 1]).toBe( "| **S3-compatible object storage** | none, HTTP | Read-only AWS CLI commands, bucket and folder browser, object preview |", ); - expect(hub).toContain("Qdrant, Oxia, S3-compatible object storage and Kubernetes** from your browser"); + expect(hub).toContain("Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes** from your browser"); expect(hub).toContain(`${Word(EXTERNAL_DATABASE_TYPES.length)} external engines share one interface.`); // The ordinal counts the table's rows: every external engine, then the embedded store. expect(SHIPPED_DATABASE_TYPES).toHaveLength(EXTERNAL_DATABASE_TYPES.length + 1); @@ -1542,7 +1542,7 @@ describe("FEATURES, BRAND_MESSAGING and API_DOCS", () => { expect(FEATURES_GROUP, words).toContain(words === "fd00:ec2::254" ? "AWS's IPv6 metadata address" : words); } expect(flat(features)).toContain( - "Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes have no count grammar here", + "Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes have no count grammar here", ); }); @@ -1554,7 +1554,7 @@ describe("FEATURES, BRAND_MESSAGING and API_DOCS", () => { expect(brand).toContain(`- **Proof:** ${word(engines)} providers, each with its own reference document`); expect(brand).toContain(`| ${Word(engines)} database engines | One reference document per engine:`); expect(brand).toContain( - "Qdrant, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. One more, `libredb.md`, is the embedded provider", + "Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B. One more, `libredb.md`, is the embedded provider", ); expect(brand).toContain(`against ${word(engines)} here.`); expect(brand).toContain(`"${Word(engines)} engines" beats "extensive database support".`); @@ -1570,7 +1570,7 @@ describe("FEATURES, BRAND_MESSAGING and API_DOCS", () => { const capabilities = provider.getCapabilities(); const keyScan = capabilities.keyScan; expect(api).toContain( - "Milvus, Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B.", + "Milvus, Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B.", ); expect(api).toMatch( new RegExp( @@ -1579,7 +1579,7 @@ describe("FEATURES, BRAND_MESSAGING and API_DOCS", () => { ), ); expect(capabilities.supportsResultPagination).toBe(false); - expect(api).toContain("Milvus, Qdrant, Oxia, S3-compatible object storage and Firestore ignore it."); + expect(api).toContain("Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Firestore ignore it."); expect(capabilities.containerLevels).toEqual([]); expect(api).toContain( "etcd, Oxia and S3-compatible object storage declare the walk and no container level, because one connection is one key space (one etcd cluster, one Oxia namespace, one S3 endpoint), so they refuse the field as well.", @@ -1704,7 +1704,7 @@ describe("docs/providers/README.md", () => { expect(lines[influxdb3 + 10].startsWith("| Sparkplug B | `sparkplug` |")).toBe(true); expect(lines[influxdb3 + 11].startsWith("| LibreDB | `libredb` |")).toBe(true); expect(index).toContain( - "Qdrant, InfluxDB, Oxia, Databend, S3, Kubernetes, MQTT, Firestore, RabbitMQ and OPC UA are)", + "Qdrant, Weaviate, InfluxDB, Oxia, Databend, S3, Kubernetes, MQTT, Firestore, RabbitMQ and OPC UA are)", ); // And the index holds a row for EVERY shipped type-id, which is the rule it states about itself. const indexed = new Set( @@ -1747,12 +1747,12 @@ describe("the architecture, provider, editor and guide docs", () => { `${word(EXTERNAL_DATABASE_TYPES.length)} external engines, plus the embedded LibreDB store`, ); expect(claude).toContain( - "`oxia`, `milvus`, `qdrant`, `s3`, `kubernetes`, `rabbitmq`, `libredb`) extend `BaseDatabaseProvider` directly", + "`oxia`, `milvus`, `qdrant`, `weaviate`, `s3`, `kubernetes`, `rabbitmq`, `libredb`) extend `BaseDatabaseProvider` directly", ); const architecture = read("docs/ARCHITECTURE.md"); expect(architecture).toContain(`It supports **${ids} database backends**`); expect(architecture).toContain( - "Milvus, Qdrant, Oxia, S3-compatible object storage, Kubernetes, NETCONF, SNMP, Sparkplug B, LibreDB.", + "Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, NETCONF, SNMP, Sparkplug B, LibreDB.", ); expect(architecture).toContain(" DBFactory --> ObjectStore[Object Storage Providers]"); expect(architecture).toContain(" ObjectStore --> S3[(S3-compatible object storage)]"); @@ -1772,7 +1772,9 @@ describe("the architecture, provider, editor and guide docs", () => { expect(providers).toContain( "- **S3-compatible object storage** (one AWS CLI read command, or Studio's own `preview`): [providers/s3.md](./providers/s3.md).", ); - expect(flat(providers)).toContain("Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, or LibreDB."); + expect(flat(providers)).toContain( + "Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, or LibreDB.", + ); /* * AND THE TABLE UNDER THE COUNT HOLDS EVERY SHIPPED TYPE-ID. The numeral was swept to * thirty-three while the table stayed thirty rows - BigQuery, MQTT and OPC UA missing, two of @@ -1793,18 +1795,18 @@ describe("the architecture, provider, editor and guide docs", () => { const nonSql = SHIPPED_DATABASE_TYPES.filter((type) => !readsSqlText(type)).length; const optimization = read("docs/editor/query-optimization.md"); expect(optimization).toContain( - `Qdrant, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B are the ${word(nonSql)} types whose query text is not SQL at all**`, + `Qdrant, Weaviate, Oxia, S3-compatible object storage, Kubernetes, OPC UA, MTConnect, Modbus, NETCONF, SNMP and Sparkplug B are the ${word(nonSql)} types whose query text is not SQL at all**`, ); expect(optimization).toContain(`holds exactly those ${word(nonSql)},`); expect(provider.getCapabilities().supportsResultPagination).toBe(false); - expect(optimization).toContain("Sixteen providers cannot serve page two."); - expect(optimization).toContain("Qdrant, Oxia and S3-compatible object storage answer it with page one."); + expect(optimization).toContain("Seventeen providers cannot serve page two."); + expect(optimization).toContain("Qdrant, Weaviate, Oxia and S3-compatible object storage answer it with page one."); expect(optimization).toContain("The S3 row names no operation and, like the Oxia row, is the gate's whole answer:"); expect(optimization).toContain( "a Qdrant request, an `oxia client` read command, an AWS CLI read command, a kubectl statement, a NETCONF read request, a Sparkplug read request or an SNMP walk is not judged by a SQL reader", ); expect(flat(read("docs/SCHEMA_DIFF.md"))).toContain( - "Qdrant, Oxia, S3-compatible object storage and Kubernetes receive an explanatory", + "Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes receive an explanatory", ); }); @@ -1955,7 +1957,7 @@ describe("the agent docs count the type-ids and name S3 where they list engines" const guide = flat(read("docs/AGENT_GUIDE.md")); expect(guide).toContain(`which is the other ${word(provided)} (MySQL,`); expect(guide).toContain( - "Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, Modbus, NETCONF, SNMP, Sparkplug B and the bundled LibreDB store)", + "Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, Modbus, NETCONF, SNMP, Sparkplug B and the bundled LibreDB store)", ); expect(guide).toContain(`so it reaches all ${word(ids)} engines.`); expect(guide).toContain( @@ -1969,9 +1971,9 @@ describe("the agent docs count the type-ids and name S3 where they list engines" const flow = flat(read("docs/AGENT_DATA_FLOW.md")); expect(flow).toContain(`and the other ${word(provided)} by asking the connection's own provider`); expect(flow).toContain( - "Never an etcd, Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement", + "Never an etcd, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement", ); - expect(flow).toContain("which those seven do"); + expect(flow).toContain("which those eight do"); expect(flow).toContain( "an S3 command names buckets and object keys, and a kubectl statement names namespaces and objects", ); @@ -1989,22 +1991,20 @@ describe("the agent docs count the type-ids and name S3 where they list engines" "- On S3-compatible object storage the grounding carries bucket names only, never an object key, a prefix, a size or any object content (objects are listed by the Keys panel, not by the object walk).", ); /* - * TWENTY-NINE, COUNTED FROM THE DECLARATIONS AND NOT FROM THE SENTENCE. `declaresForeignKeys: - * false` is set by every shipped type-id but the eight SQL engines that declare them, so the - * number is `SHIPPED_DATABASE_TYPES.length - 8`. It was twenty-seven at thirty-five type-ids and - * is twenty-eight at thirty-six, because Snowflake sets it false too - * (`src/lib/db/providers/sql/snowflake/index.ts`), and twenty-nine at thirty-seven, because - * Apache Spark does as well (`src/lib/db/providers/sql/spark/index.ts`). The sentence had said twenty-four and named - * twenty-four: BigQuery had been missing since its own merge, Firestore since its own, OPC UA - * since ours and Snowflake since theirs. + * COUNTED FROM THE DECLARATIONS AND NOT FROM THE SENTENCE. `declaresForeignKeys: false` is set by every shipped + * type-id but the eight SQL engines that declare them, so the list names `SHIPPED_DATABASE_TYPES.length - 8`. + * The sentence once carried that number and named fewer: it said twenty-four and named twenty-four while BigQuery, + * Firestore, OPC UA and Snowflake were missing. It names them now and counts none (#1614), so the count is held + * here, on the names between the parentheses. */ - expect(flow).toContain(`On the ${word(ids - 8)} engines that declare no foreign keys at all`); + const noKeys = flow.split("On every engine that declares no foreign keys at all (")[1]?.split(") this block")[0]; + expect(noKeys?.split(/, | and /)).toHaveLength(ids - 8); expect(flow).toContain( - "Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes, SNMP and Sparkplug B) this block carries no relations", + "Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes, SNMP and Sparkplug B) this block carries no relations", ); expect(flow).toContain(`replaces them on the other ${word(provided)}.`); expect(flow).toContain( - "nothing at all for an etcd, Milvus, Qdrant, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement", + "nothing at all for an etcd, Milvus, Qdrant, Weaviate, InfluxDB (InfluxQL), Oxia, S3-compatible object storage or Kubernetes statement", ); }); }); @@ -2040,7 +2040,9 @@ describe("the complete engine lists outside the agent docs", () => { // straight back to MQTT. The chain is a claim about ORDER, so each link is pinned at both ends: an engine added // without moving the head leaves the previous head claiming a title it no longer holds, which is exactly what // this change did to Kubernetes until the `not` assertions below were added. - expect(readme).toContain("Sparkplug B is the newest: one broker read over MQTT"); + expect(readme).toContain("Weaviate is the newest: Weaviate's own REST requests typed in the editor"); + expect(readme).toContain("Sparkplug B came before Weaviate: one broker read over MQTT"); + expect(readme).not.toContain("Sparkplug B is the newest"); expect(readme).toContain("SNMP came before Sparkplug B: one agent read over UDP"); expect(readme).not.toContain("SNMP is the newest"); expect(readme).toContain("NETCONF came before SNMP: one network device read over NETCONF on SSH"); @@ -2122,10 +2124,10 @@ describe("the complete engine lists outside the agent docs", () => { ); } expect(read("docs/BRAND_MESSAGING.md")).toContain( - "Milvus, Qdrant, Oxia, S3-compatible object storage and Kubernetes, with SSO and audit", + "Milvus, Qdrant, Weaviate, Oxia, S3-compatible object storage and Kubernetes, with SSO and audit", ); expect(read("docs/FEATURES.md")).toContain( - "Qdrant, Oxia, Databend, S3-compatible object storage, Kubernetes and LibreDB show no editing control at all", + "Qdrant, Weaviate, Oxia, Databend, S3-compatible object storage, Kubernetes and LibreDB show no editing control at all", ); expect(provider.getCapabilities().supportsInlineRowEdit).toBe(false); const guide = read("docs/ADDING_A_PROVIDER.md"); diff --git a/tests/unit/db/sql-grammar/census.test.ts b/tests/unit/db/sql-grammar/census.test.ts index de8051e263..8e5f61a4a6 100644 --- a/tests/unit/db/sql-grammar/census.test.ts +++ b/tests/unit/db/sql-grammar/census.test.ts @@ -48,7 +48,7 @@ const FAMILIES: Record = { ], stream: ["kafka", "rabbitmq"], timeseries: ["prometheus"], - vector: ["milvus", "qdrant"], + vector: ["milvus", "qdrant", "weaviate"], }; /** Where each type id's module sits, under `src/lib/db/providers/`. */ diff --git a/tests/unit/db/sql-grammar/golden/weaviate.txt b/tests/unit/db/sql-grammar/golden/weaviate.txt new file mode 100644 index 0000000000..9430fe4f3d --- /dev/null +++ b/tests/unit/db/sql-grammar/golden/weaviate.txt @@ -0,0 +1,56 @@ +resolveSqlGrammar("weaviate") => {"hash":"comment-unless-operator","bracket":"quoted-identifier","blockComment":"flat","alternateQuoting":false,"doubleSlashComment":false,"backslashAlwaysEscapes":false,"script":{"blocks":"none","separatorLine":null,"unit":"statement"},"trailingLimitClauses":[]} +readsSqlText("weaviate") => false +hashRunIsAmbiguous(resolveSqlGrammar("weaviate")) => true +readSqlSpan walk("SELECT 1 # c\nFROM t") => [["whitespace",6,7],["whitespace",8,9],["line-comment",9,13],["whitespace",17,18]] +splitStatements("SELECT 1 # c\nFROM t") => [{"sql":"SELECT 1 # c\nFROM t","startLine":0,"start":0,"end":19}] +readSqlSpan walk("SELECT a[1], [x]]y] FROM t") => [["whitespace",6,7],["quoted-identifier",8,11],["whitespace",12,13],["quoted-identifier",13,19],["whitespace",19,20],["whitespace",24,25]] +splitStatements("SELECT a[1], [x]]y] FROM t") => [{"sql":"SELECT a[1], [x]]y] FROM t","startLine":0,"start":0,"end":26}] +readSqlSpan walk("/* a /* b */ c */ SELECT 1") => [["block-comment",0,12],["whitespace",12,13],["whitespace",14,15],["whitespace",17,18],["whitespace",24,25]] +splitStatements("/* a /* b */ c */ SELECT 1") => [{"sql":"/* a /* b */ c */ SELECT 1","startLine":0,"start":0,"end":26}] +readSqlSpan walk("SELECT q'[it's]' FROM dual") => [["whitespace",6,7],["string",8,13],["string",15,26]] +splitStatements("SELECT q'[it's]' FROM dual") => [{"sql":"SELECT q'[it's]' FROM dual","startLine":0,"start":0,"end":26}] +readSqlSpan walk("SELECT 1 // c; DROP TABLE t") => [["whitespace",6,7],["whitespace",8,9],["whitespace",11,12],["whitespace",14,15],["whitespace",19,20],["whitespace",25,26]] +splitStatements("SELECT 1 // c; DROP TABLE t") => [{"sql":"SELECT 1 // c","startLine":0,"start":0,"end":13},{"sql":"DROP TABLE t","startLine":0,"start":15,"end":27}] +readSqlSpan walk("SELECT 'a\\'b'; SELECT 2") => [["whitespace",6,7],["string",7,23]] +splitStatements("SELECT 'a\\'b'; SELECT 2") => [{"sql":"SELECT 'a\\'b'; SELECT 2","startLine":0,"start":0,"end":23}] +readSqlSpan walk("SELECT $$x;$$, \"q\"\"n\", `b``t` FROM t") => [["whitespace",6,7],["dollar-string",7,13],["whitespace",14,15],["quoted-identifier",15,21],["whitespace",22,23],["quoted-identifier",23,29],["whitespace",29,30],["whitespace",34,35]] +splitStatements("SELECT $$x;$$, \"q\"\"n\", `b``t` FROM t") => [{"sql":"SELECT $$x;$$, \"q\"\"n\", `b``t` FROM t","startLine":0,"start":0,"end":36}] +readSqlSpan walk("CREATE TRIGGER tr AFTER INSERT ON t BEGIN SELECT 1; END; SELECT 2") => [["whitespace",6,7],["whitespace",14,15],["whitespace",17,18],["whitespace",23,24],["whitespace",30,31],["whitespace",33,34],["whitespace",35,36],["whitespace",41,42],["whitespace",48,49],["whitespace",51,52],["whitespace",56,57],["whitespace",63,64]] +splitStatements("CREATE TRIGGER tr AFTER INSERT ON t BEGIN SELECT 1; END; SELECT 2") => [{"sql":"CREATE TRIGGER tr AFTER INSERT ON t BEGIN SELECT 1","startLine":0,"start":0,"end":50},{"sql":"END","startLine":0,"start":52,"end":55},{"sql":"SELECT 2","startLine":0,"start":57,"end":65}] +readSqlSpan walk("SELECT 1\nGO\nSELECT 2") => [["whitespace",6,7],["whitespace",8,9],["whitespace",11,12],["whitespace",18,19]] +splitStatements("SELECT 1\nGO\nSELECT 2") => [{"sql":"SELECT 1\nGO\nSELECT 2","startLine":0,"start":0,"end":20}] +readSqlSpan walk("BEGIN NULL; END;\n/\nSELECT 1") => [["whitespace",5,6],["whitespace",11,12],["whitespace",16,17],["whitespace",18,19],["whitespace",25,26]] +splitStatements("BEGIN NULL; END;\n/\nSELECT 1") => [{"sql":"BEGIN NULL","startLine":0,"start":0,"end":10},{"sql":"END","startLine":0,"start":12,"end":15},{"sql":"/\nSELECT 1","startLine":1,"start":17,"end":27}] +readSqlSpan walk("SELECT 1 -- x\rDROP TABLE t") => [["whitespace",6,7],["whitespace",8,9],["line-comment",9,26]] +splitStatements("SELECT 1 -- x\rDROP TABLE t") => [{"sql":"SELECT 1 -- x\rDROP TABLE t","startLine":0,"start":0,"end":26}] +resolveUpdateTarget("SELECT id, note FROM products", "weaviate") => {"kind":"table","table":"products"} +resolveUpdateTarget("SELECT id FROM products --x", "weaviate") => {"kind":"table","table":"products"} +resolveUpdateTarget("SELECT id FROM products -- x", "weaviate") => {"kind":"table","table":"products"} +resolveUpdateTarget("SELECT id, (PIVOT orders ON k USING max(note)) FROM products", "weaviate") => {"kind":"table","table":"products"} +resolveUpdateTarget("SELECT id, coalesce(show, '') FROM products", "weaviate") => {"kind":"table","table":"products"} +resolveUpdateTarget("SELECT id FROM products MINUS SELECT id FROM orders", "weaviate") => {"kind":"refused","reason":"This query reads from more than one place, so the row's table cannot be told apart"} +resolveUpdateTarget("SELECT id FROM a UNION SELECT id FROM b", "weaviate") => {"kind":"refused","reason":"This result combines more than one query, so there is no single table to write to"} +resolveUpdateTarget("SELECT id FROM products WHERE qty <> 5-- zz UNION SELECT id FROM zord", "weaviate") => {"kind":"table","table":"products"} +selectsPlainColumn("SELECT id, note FROM products", "note", "weaviate") => true +redactStatement("SELECT * FROM \"Users\" WHERE name = 'bob' AND id = 42", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("SELECT * FROM \"Users\" WHERE name = 'bob' AND id = 42", "weaviate") => "SELECT * FROM \"Users\" WHERE name = 'bob' AND id = 42" +redactStatement("SELECT `a`, [b] FROM t WHERE x = 'y' -- note", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("SELECT `a`, [b] FROM t WHERE x = 'y' -- note", "weaviate") => "SELECT `a`, [b] FROM t WHERE x = 'y' -- note" +redactStatement("{\"collection\":\"users\",\"operation\":\"find\",\"filter\":{\"name\":\"bob\"}}", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("{\"collection\":\"users\",\"operation\":\"find\",\"filter\":{\"name\":\"bob\"}}", "weaviate") => "{\"collection\":\"users\",\"operation\":\"find\",\"filter\":{\"name\":\"bob\"}}" +redactStatement("GET user:1", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("GET user:1", "weaviate") => "GET user:1" +redactStatement("SET k \"v\"", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("SET k \"v\"", "weaviate") => "SET k \"v\"" +redactStatement("SELECT 'postgres://u:p@h/db' # x", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("SELECT 'postgres://u:p@h/db' # x", "weaviate") => "SELECT 'postgres://[REDACTED]@h/db' # x" +redactStatement("CREATE USER a IDENTIFIED BY secret", "weaviate") => {"statement":"?","statement_fingerprint":"8a8de823d5ed3e12746a62ef169bcf372be0ca44f0a1236abc35df05d96928e1"} +maskCredentials("CREATE USER a IDENTIFIED BY secret", "weaviate") => "CREATE USER a IDENTIFIED BY secret" +completions[plain]("SELECT * FROM ") => [["Order\"Items","Order\"Items"],["public.select","public.select"],["users","users"]] +completions[plain]("SELECT * FROM public.se") => [["public.select","public.select"]] +completions[plain]("SELECT \"Order\"\"Items\".") => [] +completions[plain]("SELECT users.") => [["email","email"],["id","id"]] +completions[quoted]("SELECT * FROM ") => [["Order\"Items","Order\"Items"],["public.select","public.select"],["t","."],["users","users"]] +completions[quoted]("SELECT * FROM public.se") => [["public.select","public.select"]] +completions[quoted]("SELECT \"Order\"\"Items\".") => [] +completions[quoted]("SELECT users.") => [["email","email"],["id","id"]] diff --git a/tests/unit/db/sql-writing/census.test.ts b/tests/unit/db/sql-writing/census.test.ts index 9f9e479ecd..05119922e4 100644 --- a/tests/unit/db/sql-writing/census.test.ts +++ b/tests/unit/db/sql-writing/census.test.ts @@ -78,6 +78,7 @@ const PLACEMENT: Readonly> = { postgres: "sql/postgres-sql-writing", prometheus: "timeseries/prometheus/sql-writing", qdrant: "vector/qdrant/sql-writing", + weaviate: "vector/weaviate/sql-writing", rabbitmq: "stream/rabbitmq/sql-writing", redis: "keyvalue/redis-sql-writing", s3: "objectstore/s3/sql-writing", diff --git a/tests/unit/db/sql-writing/golden/weaviate.txt b/tests/unit/db/sql-writing/golden/weaviate.txt new file mode 100644 index 0000000000..6cdd456afc --- /dev/null +++ b/tests/unit/db/sql-writing/golden/weaviate.txt @@ -0,0 +1,443 @@ +quoteLiteral("", "weaviate") => "''" +unquoteLiteral(quoteLiteral("", "weaviate"), "weaviate") => "" +quoteLiteral("it's", "weaviate") => "'it''s'" +unquoteLiteral(quoteLiteral("it's", "weaviate"), "weaviate") => "it's" +quoteLiteral("a\\b", "weaviate") => "'a\\b'" +unquoteLiteral(quoteLiteral("a\\b", "weaviate"), "weaviate") => "a\\b" +quoteLiteral("a\\", "weaviate") => "'a\\'" +unquoteLiteral(quoteLiteral("a\\", "weaviate"), "weaviate") => "a\\" +quoteLiteral("'", "weaviate") => "''''" +unquoteLiteral(quoteLiteral("'", "weaviate"), "weaviate") => "'" +quoteLiteral("a\\'b", "weaviate") => "'a\\''b'" +unquoteLiteral(quoteLiteral("a\\'b", "weaviate"), "weaviate") => "a\\'b" +quoteLiteral("Müşteri", "weaviate") => "'Müşteri'" +unquoteLiteral(quoteLiteral("Müşteri", "weaviate"), "weaviate") => "Müşteri" +quoteLiteral("x\u0000y", "weaviate") => "'x\u0000y'" +unquoteLiteral(quoteLiteral("x\u0000y", "weaviate"), "weaviate") => "x\u0000y" +quoteLiteral("line\nbreak", "weaviate") => "'line\nbreak'" +unquoteLiteral(quoteLiteral("line\nbreak", "weaviate"), "weaviate") => "line\nbreak" +unquoteLiteral("'a''b'", "weaviate") => "a'b" +unquoteLiteral("'a\\'b'", "weaviate") => undefined +unquoteLiteral("N'x'", "weaviate") => undefined +unquoteLiteral("'open", "weaviate") => undefined +unquoteLiteral("'a'b'", "weaviate") => undefined +quoteIdentifier("plain", "weaviate") => "\"plain\"" +quoteIdentifier("x\"y", "weaviate") => "\"x\"\"y\"" +quoteIdentifier("a`b", "weaviate") => "\"a`b\"" +quoteIdentifier("a]b", "weaviate") => "\"a]b\"" +quoteIdentifier("a\\b", "weaviate") => "\"a\\b\"" +positionalPlaceholder("weaviate", 1) => null +positionalPlaceholder("weaviate", 2) => null +positionalPlaceholder("weaviate", 10) => null +temporalLiteral("2026-01-27", "date", "weaviate") => "'2026-01-27'" +temporalLiteral("2026-01-27 14:30:00", "timestamp", "weaviate") => "'2026-01-27 14:30:00'" +temporalLiteral("2026-01-27T14:30:00Z", "timestamp", "weaviate") => "'2026-01-27T14:30:00Z'" +temporalLiteral("27-JAN-26", "date", "weaviate") => "'27-JAN-26'" +edit("DATE", "2026-10-04 12:34:56", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("DATE", "2026-10-04 12:34:56.5", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56.5' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("DATE", "-0044-03-15 12:00:00", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '-0044-03-15 12:00:00' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("date", "2026-10-04 12:34:56", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP", "2026-10-04 12:34:56", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP(6)", "2026-10-04 12:34:56.123456", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56.123456' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP", "2026-10-04T09:34:56.123Z", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04T09:34:56.123Z' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP(6) WITH TIME ZONE", "2026-10-04T09:34:56.123Z", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04T09:34:56.123Z' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP WITH LOCAL TIME ZONE", "2026-10-04T09:34:56.123Z", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04T09:34:56.123Z' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("TIMESTAMP WITH TIME ZONE", "2026-02-30T00:00:00.000Z", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-02-30T00:00:00.000Z' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("VARCHAR2(30)", "2026-10-04 12:34:56", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("datetime", "2026-10-04 12:34:57.123", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:57.123' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("DATETIME", "2026-10-04 12:34:57", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:57' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("smalldatetime", "2026-10-04 12:34:00", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:00' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("Nullable(datetime)", "2026-10-04 12:34:57", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:57' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("datetime2", "2026-10-04 12:34:57.123", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:57.123' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("datetime", "2026-10-04 12:34:57.1234", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:57.1234' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("datetime", "2026-10-04", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("timestamp with time zone", "2026-10-04 12:34:56+00", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56+00' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit(undefined, "2026-10-04 12:34:56", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = '2026-10-04 12:34:56' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("text", "it's \\ x", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'it''s \\ x' WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("text", "NULL", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = NULL WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +edit("text", "", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = NULL WHERE \"id\" = 1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("timestamp", "2026-01-01 10:00:00.123", "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("DATE", "2024-01-15", "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("datetime2", "2026-01-01 10:00:00", "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("Nullable(DateTime64(6, 'UTC'))", "2026-01-01 10:00:00.123456", "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("timestamptz", "2026-01-01T07:00:00.123Z", "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("timestamp", new Date("2026-01-01T00:00:00.000Z"), "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("daterange", "[2024-01-01,2024-02-01)", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN ('[2024-01-01,2024-02-01)') GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = '[2024-01-01,2024-02-01)'",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("double precision", 0.30000000000000004, "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (0.30000000000000004) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = 0.30000000000000004",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("BINARY_DOUBLE", 0.1, "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (0.1) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = 0.1",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("real", 0.1, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number, and nothing here says the column holds it as a 64-bit float, so the engine may read that decimal back as a different number. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("float", 0.1, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number, and nothing here says the column holds it as a 64-bit float, so the engine may read that decimal back as a different number. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("NUMBER(20,4)", 1234567890123456.8, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number the driver rounded to fit, and the column it came out of holds more digits than a 64-bit float carries, so this decimal may be a rounding of the row's own — and a rounding matches another row as readily as yours. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("NUMBER", 0.1, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number the driver rounded to fit, and the column it came out of holds more digits than a 64-bit float carries, so this decimal may be a rounding of the row's own — and a rounding matches another row as readily as yours. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("decimal(9,2)", 1.5, "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (1.5) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = 1.5",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("DECIMAL(20,4)", 1234567890123456.8, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number the driver rounded to fit, and the column it came out of holds more digits than a 64-bit float carries, so this decimal may be a rounding of the row's own — and a rounding matches another row as readily as yours. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("money", 922337203685477.6, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number the driver rounded to fit, and the column it came out of holds more digits than a 64-bit float carries, so this decimal may be a rounding of the row's own — and a rounding matches another row as readily as yours. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("integer", 9007199254740992, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a whole number past the range this editor carries exactly, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("integer", 42, "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN (42) GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = 42",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} +key("DATE", 2460324.75, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a date and time, which does not reach the table as the row holds it. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key(undefined, 0.1, "weaviate") => {"keyCheck":null,"calls":[],"toasts":[["error","Cannot Apply Changes","This editor cannot address a row by id here: in 1 row you edited it is a fractional number, and nothing here says the column holds it as a 64-bit float, so the engine may read that decimal back as a different number. Put a column that identifies a row as text or a whole number in the query and run it again, or edit the SQL by hand."]]} +key("text", "abc", "weaviate") => {"keyCheck":{"sql":"SELECT \"id\", COUNT(*) AS \"key_rows\" FROM t WHERE \"id\" IN ('abc') GROUP BY \"id\"","params":null},"calls":[["UPDATE t SET \"v\" = 'x' WHERE \"id\" = 'abc'",null],["SELECT id, v FROM t",null]],"toasts":[["success","Changes Applied","1 UPDATE statement accepted. The results are up to date."]]} + +insert(inferred) => "INSERT INTO t (\"txt\", \"int\", \"num\", \"bool\", \"ts\", \"bin\", \"empty_bin\", \"big\", \"nan\", \"inf\", \"ninf\", \"obj\", \"arr\", \"nul\", \"odd name\") VALUES ('it''s a\\', 42, 1.5, true, '2026-01-27T14:30:00.123Z', X'0102deadbeef', X'', 9007199254740993, NULL, NULL, NULL, '{\"k\":[1,{\"x\":\"y\"}]}', '[1,2,3]', NULL, 'Müşteri');\nINSERT INTO t (\"txt\", \"int\", \"num\", \"bool\", \"ts\", \"bin\", \"empty_bin\", \"big\", \"nan\", \"inf\", \"ninf\", \"obj\", \"arr\", \"nul\", \"odd name\") VALUES (NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);" +ddl(inferred) => "CREATE TABLE t (\n \"txt\" TEXT,\n \"int\" BIGINT,\n \"num\" DOUBLE PRECISION,\n \"bool\" BOOLEAN,\n \"ts\" TIMESTAMP,\n \"bin\" BLOB,\n \"empty_bin\" BLOB,\n \"big\" BIGINT,\n \"nan\" DOUBLE PRECISION,\n \"inf\" DOUBLE PRECISION,\n \"ninf\" DOUBLE PRECISION,\n \"obj\" TEXT,\n \"arr\" TEXT,\n \"nul\" TEXT,\n \"odd name\" TEXT\n);" +ddl("BIT") => "CREATE TABLE t (\n \"c\" BIT\n);" +ddl("DECIMAL(10, 2)") => "CREATE TABLE t (\n \"c\" DECIMAL(10, 2)\n);" +ddl("NUMBER(10,2)") => "CREATE TABLE t (\n \"c\" NUMBER(10,2)\n);" +ddl("Nullable(Int64)") => "CREATE TABLE t (\n \"c\" Nullable(Int64)\n);" +ddl("TIMESTAMP WITH TIME ZONE") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("__proto__") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("binary") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("binary_double") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("binary_float") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("bit") => "CREATE TABLE t (\n \"c\" bit\n);" +ddl("bit[]") => "CREATE TABLE t (\n \"c\" bit[]\n);" +ddl("blob") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("bytea") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("char") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("character") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("character varying") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("clob") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("constructor") => "CREATE TABLE t (\n \"c\" constructor\n);" +ddl("datetime") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("datetime2") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("datetimeoffset") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("decimal") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("enum") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("image") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("list>") => "CREATE TABLE t (\n \"c\" list>\n);" +ddl("longblob") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("longtext") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("map>") => "CREATE TABLE t (\n \"c\" map>\n);" +ddl("mediumblob") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("mediumtext") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("money") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("nchar") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("nclob") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("ntext") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("number") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("numeric") => "CREATE TABLE t (\n \"c\" DOUBLE PRECISION\n);" +ddl("nvarchar") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("nvarchar2") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("raw") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("rowid") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("set") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("set>>") => "CREATE TABLE t (\n \"c\" set>>\n);" +ddl("smalldatetime") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("text") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("time") => "CREATE TABLE t (\n \"c\" time\n);" +ddl("timestamp") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("timestamp with time zone") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("timestamp without time zone") => "CREATE TABLE t (\n \"c\" TIMESTAMP\n);" +ddl("tinyblob") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("tinytext") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("uniqueidentifier") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("varbinary") => "CREATE TABLE t (\n \"c\" BLOB\n);" +ddl("varchar") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("varchar2") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("vector") => "CREATE TABLE t (\n \"c\" vector\n);" +ddl("x; DROP TABLE t") => "CREATE TABLE t (\n \"c\" TEXT\n);" +ddl("year") => "CREATE TABLE t (\n \"c\" BIGINT\n);" +ddlSample("VECTOR", [1.5,2]) => "CREATE TABLE t (\n \"c\" VECTOR\n);" +ddlSample("VECTOR", "[1,2,3]") => "CREATE TABLE t (\n \"c\" VECTOR\n);" +ddlSample("VECTOR", null) => "CREATE TABLE t (\n \"c\" VECTOR\n);" +ddlSample("VECTOR", {"bad":1}) => "CREATE TABLE t (\n \"c\" VECTOR\n);" +insert("integer[]", null) => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("integer[]", undefined) => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("integer[]", [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("interval", {"days":1,"weeks":2}) => "INSERT INTO t (\"c\") VALUES ('{\"days\":1,\"weeks\":2}');" +insert("interval", {"days":"1"}) => "INSERT INTO t (\"c\") VALUES ('{\"days\":\"1\"}');" +insert("point", {"x":1,"y":"2"}) => "INSERT INTO t (\"c\") VALUES ('{\"x\":1,\"y\":\"2\"}');" +insert("circle", {"x":1,"y":2}) => "INSERT INTO t (\"c\") VALUES ('{\"x\":1,\"y\":2}');" +insert("box", {"x":1,"y":2}) => "INSERT INTO t (\"c\") VALUES ('{\"x\":1,\"y\":2}');" +insert("interval", "1 day") => "INSERT INTO t (\"c\") VALUES ('1 day');" +insert("interval[]", [{"weeks":1},1.5]) => "INSERT INTO t (\"c\") VALUES ('[{\"weeks\":1},1.5]');" +insert("jsonb[]", ["hello",1,null]) => "INSERT INTO t (\"c\") VALUES ('[\"hello\",1,null]');" +insert(" INTEGER[] ", [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert(undefined, "1") => "INSERT INTO t (\"c\") VALUES ('1');" +insert("bigint", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("varbinary", "not base64!") => "INSERT INTO t (\"c\") VALUES ('not base64!');" +insert("boolean", true) => "INSERT INTO t (\"c\") VALUES (true);" +insert("json", {"a":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("double", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("double", -Infinity) => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("real", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("array(double)", ["NaN",1.5]) => "INSERT INTO t (\"c\") VALUES ('[\"NaN\",1.5]');" +insert("varchar", "NaN") => "INSERT INTO t (\"c\") VALUES ('NaN');" +insert("row(integer, timestamp(3) with time zone)", [1,"2024-01-01 00:00:00.000 UTC"]) => "INSERT INTO t (\"c\") VALUES ('[1,\"2024-01-01 00:00:00.000 UTC\"]');" +insert("row(double precision)", [1.5]) => "INSERT INTO t (\"c\") VALUES ('[1.5]');" +insert("row(integer, varchar)", [1,"x"]) => "INSERT INTO t (\"c\") VALUES ('[1,\"x\"]');" +insert("row(\"a b\" integer, c varchar)", [1,"x"]) => "INSERT INTO t (\"c\") VALUES ('[1,\"x\"]');" +insert("row(a integer, b varchar)", [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("row(a integer)", {}) => "INSERT INTO t (\"c\") VALUES ('{}');" +insert("array(integer)", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("map(varchar, integer)", []) => "INSERT INTO t (\"c\") VALUES ('[]');" +insert(undefined, [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("INTEGER[]", "1") => "INSERT INTO t (\"c\") VALUES ('1');" +insert("BLOB", {"type":"Buffer","data":[1]}) => "INSERT INTO t (\"c\") VALUES (X'01');" +insert("JSON", {"a":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("DECIMAL(9,2)[]", ["1",2.5,"x"]) => "INSERT INTO t (\"c\") VALUES ('[\"1\",2.5,\"x\"]');" +insert("INTERVAL", {"months":0,"days":0,"micros":5}) => "INSERT INTO t (\"c\") VALUES ('{\"months\":0,\"days\":0,\"micros\":5}');" +insert("INTERVAL", {"months":1,"days":2}) => "INSERT INTO t (\"c\") VALUES ('{\"months\":1,\"days\":2}');" +insert("INTERVAL", {"months":1.5,"days":0,"micros":"0"}) => "INSERT INTO t (\"c\") VALUES ('{\"months\":1.5,\"days\":0,\"micros\":\"0\"}');" +insert("INTERVAL", {"months":1,"days":0,"micros":"1.5"}) => "INSERT INTO t (\"c\") VALUES ('{\"months\":1,\"days\":0,\"micros\":\"1.5\"}');" +insert("INTERVAL", {"months":1,"days":0,"micros":"x"}) => "INSERT INTO t (\"c\") VALUES ('{\"months\":1,\"days\":0,\"micros\":\"x\"}');" +insert("STRUCT(a INTEGER)", {"a":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("STRUCT(\"a\"\"b\" INTEGER)", {"a\"b":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\\\"b\":1}');" +insert("STRUCT(a INTEGER)", {"b":1}) => "INSERT INTO t (\"c\") VALUES ('{\"b\":1}');" +insert("STRUCT(INTEGER)", {"a":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("INTEGER[]", {"a":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("MAP(VARCHAR, INTEGER)", {"k":1}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":1}');" +insert("MAP(VARCHAR, INTEGER)", [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("list", [1,null]) => "INSERT INTO t (\"c\") VALUES ('[1,null]');" +insert("frozen>", [1.5,2]) => "INSERT INTO t (\"c\") VALUES ('[1.5,2]');" +insert("uuid", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("duration", "1 day") => "INSERT INTO t (\"c\") VALUES ('1 day');" +insert("text", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("float", Infinity) => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("list", ["-Infinity",1.5]) => "INSERT INTO t (\"c\") VALUES ('[\"-Infinity\",1.5]');" +insert("text", "NaN") => "INSERT INTO t (\"c\") VALUES ('NaN');" +insert("duration", "0s") => "INSERT INTO t (\"c\") VALUES ('0s');" +insert("list", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("map", [1]) => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("tuple", {}) => "INSERT INTO t (\"c\") VALUES ('{}');" +insert(undefined, true) => "INSERT INTO t (\"c\") VALUES (true);" +insert("bit", false) => "INSERT INTO t (\"c\") VALUES (false);" +insert("bit", 1) => "INSERT INTO t (\"c\") VALUES (1);" +insert("datetime", "2026-10-04 12:34:56.123") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:34:56.123');" +insert("smalldatetime", "2026-10-04 12:35:00") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:35:00');" +insert(" SmallDateTime ", "2026-10-04 12:35:00") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:35:00');" +insert("datetime2", "2026-10-04 12:34:56.123") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:34:56.123');" +insert(undefined, "2026-10-04 12:34:56.123") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:34:56.123');" +insert("datetime", "2026-10-04T12:34:56.123Z") => "INSERT INTO t (\"c\") VALUES ('2026-10-04T12:34:56.123Z');" +insert("datetime", "2026-10-04 12:34:56.1234567") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:34:56.1234567');" +insert("smalldatetime", "2026-10-04 12:34") => "INSERT INTO t (\"c\") VALUES ('2026-10-04 12:34');" +insert("datetime", "x 2026-10-04 12:34:56") => "INSERT INTO t (\"c\") VALUES ('x 2026-10-04 12:34:56');" +insert("datetime", Date(1970-01-01T00:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('1970-01-01T00:00:00.000Z');" +insert("Array(String)", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Array(UInt8)", {"type":"Buffer","data":[1]}) => "INSERT INTO t (\"c\") VALUES (X'01');" +insert("Nullable(Array(LowCardinality(String)))", ["a"]) => "INSERT INTO t (\"c\") VALUES ('[\"a\"]');" +insert("Array(Array(Int32))", ["x"]) => "INSERT INTO t (\"c\") VALUES ('[\"x\"]');" +insert("Map(String, Array(Int32))", {"a":"x"}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":\"x\"}');" +insert("Array(Map(String, Int32))", ["x"]) => "INSERT INTO t (\"c\") VALUES ('[\"x\"]');" +insert("Array(Tuple(Int32, Int32))", [[1,2,3]]) => "INSERT INTO t (\"c\") VALUES ('[[1,2,3]]');" +insert("Array(Tuple(a Int32, b Int32))", [{"a":1}]) => "INSERT INTO t (\"c\") VALUES ('[{\"a\":1}]');" +insert("Array(Tuple(Int32))", [{"a":1}]) => "INSERT INTO t (\"c\") VALUES ('[{\"a\":1}]');" +insert("Map(String, Tuple(Int32, DateTime64(3, 'Europe/Istanbul')))", {"k":[1,"2024-01-01 00:00:00.000"]}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":[1,\"2024-01-01 00:00:00.000\"]}');" +insert("Array(Enum8('a,b' = 1))", ["a"]) => "INSERT INTO t (\"c\") VALUES ('[\"a\"]');" +insert("Array(Float64)", ["NaN","Infinity","-Infinity","1.5"]) => "INSERT INTO t (\"c\") VALUES ('[\"NaN\",\"Infinity\",\"-Infinity\",\"1.5\"]');" +insert("Array(String)", ["NaN"]) => "INSERT INTO t (\"c\") VALUES ('[\"NaN\"]');" +insert("Array(Float32)", ["constructor"]) => "INSERT INTO t (\"c\") VALUES ('[\"constructor\"]');" +insert("Float64", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("Nullable(Float32)", "-Infinity") => "INSERT INTO t (\"c\") VALUES ('-Infinity');" +insert("LowCardinality(Nullable(Float64))", "NaN") => "INSERT INTO t (\"c\") VALUES ('NaN');" +insert("BFloat16", -Infinity) => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("Float64", 1.5) => "INSERT INTO t (\"c\") VALUES (1.5);" +insert("String", "Infinity") => "INSERT INTO t (\"c\") VALUES ('Infinity');" +insert("Float64", "inf") => "INSERT INTO t (\"c\") VALUES ('inf');" +insert("Array(Decimal(9, 2))", ["1.5","x"]) => "INSERT INTO t (\"c\") VALUES ('[\"1.5\",\"x\"]');" +insert("Array(String)", ["1"]) => "INSERT INTO t (\"c\") VALUES ('[\"1\"]');" +insert("Binary", "616263") => "INSERT INTO t (\"c\") VALUES ('616263');" +insert("Nullable(Binary)", "00FF10") => "INSERT INTO t (\"c\") VALUES ('00FF10');" +insert("Binary", "") => "INSERT INTO t (\"c\") VALUES ('');" +insert("Binary", "abc") => "INSERT INTO t (\"c\") VALUES ('abc');" +insert("Binary", "x'; DROP") => "INSERT INTO t (\"c\") VALUES ('x''; DROP');" +insert("Binary", bytes(0102)) => "INSERT INTO t (\"c\") VALUES (X'0102');" +insert("Variant", "{\"a\":1,\"b\":[1,2,\"x\"]}") => "INSERT INTO t (\"c\") VALUES ('{\"a\":1,\"b\":[1,2,\"x\"]}');" +insert("Nullable(Variant)", "\"it's\"") => "INSERT INTO t (\"c\") VALUES ('\"it''s\"');" +insert("Variant", {"k":[1,null]}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":[1,null]}');" +insert("Bitmap", "") => "INSERT INTO t (\"c\") VALUES ('');" +insert("Map(String, Int32)", "{\"k1\":1}") => "INSERT INTO t (\"c\") VALUES ('{\"k1\":1}');" +insert("Tuple(Int32, String)", "(1,\"a\")") => "INSERT INTO t (\"c\") VALUES ('(1,\"a\")');" +insert("Nullable(Array(Int32 NULL))", "[1,NULL]") => "INSERT INTO t (\"c\") VALUES ('[1,NULL]');" +insert("Interval", "1 day 2:03:00") => "INSERT INTO t (\"c\") VALUES ('1 day 2:03:00');" +insert("Map(String, Int32)", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Mystery\nSELECT 2 AS injected;\r\n--\f
…\u0000end", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Geeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Geeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Bitmap", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("Int64", "-9223372036854775808") => "INSERT INTO t (\"c\") VALUES ('-9223372036854775808');" +insert("Nullable(UInt64)", "18446744073709551615") => "INSERT INTO t (\"c\") VALUES ('18446744073709551615');" +insert("Nullable(Decimal(10, 2))", "12345678.90") => "INSERT INTO t (\"c\") VALUES ('12345678.90');" +insert("Float64", "1e+308") => "INSERT INTO t (\"c\") VALUES ('1e+308');" +insert("Int32", 7) => "INSERT INTO t (\"c\") VALUES (7);" +insert("Int32", "seven") => "INSERT INTO t (\"c\") VALUES ('seven');" +insert("Float32", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("Nullable(Float64)", "-Infinity") => "INSERT INTO t (\"c\") VALUES ('-Infinity');" +insert("Boolean", "1") => "INSERT INTO t (\"c\") VALUES ('1');" +insert("Nullable(Boolean)", "0") => "INSERT INTO t (\"c\") VALUES ('0');" +insert("Boolean", true) => "INSERT INTO t (\"c\") VALUES (true);" +insert("Boolean", "yes") => "INSERT INTO t (\"c\") VALUES ('yes');" +insert("String", "2026-10-07 12:34:56.789012") => "INSERT INTO t (\"c\") VALUES ('2026-10-07 12:34:56.789012');" +insert("Nullable(String)", "2026-10-07 12:34:56.789012") => "INSERT INTO t (\"c\") VALUES ('2026-10-07 12:34:56.789012');" +insert("Date", "2026-10-07 12:34:56.789012") => "INSERT INTO t (\"c\") VALUES ('2026-10-07 12:34:56.789012');" +insert("Timestamp", "2026-10-07 12:34:56.789012") => "INSERT INTO t (\"c\") VALUES ('2026-10-07 12:34:56.789012');" +insert("Nullable(Timestamp_Tz)", "2026-10-07 12:34:56.789012") => "INSERT INTO t (\"c\") VALUES ('2026-10-07 12:34:56.789012');" +insert(undefined, "616263") => "INSERT INTO t (\"c\") VALUES ('616263');" +insert("VARIANT", "{\"a\":1}") => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("OBJECT", {"k":[1,null]}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":[1,null]}');" +insert("array", "[1,2]") => "INSERT INTO t (\"c\") VALUES ('[1,2]');" +insert("MAP", "{\"a\":1}") => "INSERT INTO t (\"c\") VALUES ('{\"a\":1}');" +insert("VECTOR(FLOAT, 2)", "[1,2]") => "INSERT INTO t (\"c\") VALUES ('[1,2]');" +insert("ARRAY(NUMBER(38,0))", "[1,2]") => "INSERT INTO t (\"c\") VALUES ('[1,2]');" +insert("VARIANT", "\"it's\\\"") => "INSERT INTO t (\"c\") VALUES ('\"it''s\\\"');" +insert("VECTOR", "[1.500000,2.000000,-3.000000]") => "INSERT INTO t (\"c\") VALUES ('[1.500000,2.000000,-3.000000]');" +insert("VECTOR", "[1,-2]") => "INSERT INTO t (\"c\") VALUES ('[1,-2]');" +insert("vector", "[1, 2e3]") => "INSERT INTO t (\"c\") VALUES ('[1, 2e3]');" +insert("VECTOR", "[1,NaN]") => "INSERT INTO t (\"c\") VALUES ('[1,NaN]');" +insert("VECTOR", [4,5,6]) => "INSERT INTO t (\"c\") VALUES ('[4,5,6]');" +insert("VECTOR", "[]") => "INSERT INTO t (\"c\") VALUES ('[]');" +insert("VECTOR", "[\"a\"]") => "INSERT INTO t (\"c\") VALUES ('[\"a\"]');" +insert("VECTOR", "[1,,2]") => "INSERT INTO t (\"c\") VALUES ('[1,,2]');" +insert("VECTOR", "1,2") => "INSERT INTO t (\"c\") VALUES ('1,2');" +insert("ARRAY(INT)'; DROP TABLE t; --", "[1]") => "INSERT INTO t (\"c\") VALUES ('[1]');" +insert("DATE", "0001-01-01") => "INSERT INTO t (\"c\") VALUES ('0001-01-01');" +insert("TIME(0)", "13:45:30") => "INSERT INTO t (\"c\") VALUES ('13:45:30');" +insert("TIME(1)", "13:45:30.5") => "INSERT INTO t (\"c\") VALUES ('13:45:30.5');" +insert("TIMESTAMP_NTZ(0)", "2026-10-12 01:02:03") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 01:02:03');" +insert("TIMESTAMP_LTZ(6)", "2026-10-12 01:02:03.123456+00:00") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 01:02:03.123456+00:00');" +insert("TIMESTAMP_TZ(0)", "2026-10-12 01:02:03-05:30") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 01:02:03-05:30');" +insert("DATE", "10000-01-01") => "INSERT INTO t (\"c\") VALUES ('10000-01-01');" +insert("TIMESTAMP_NTZ(1)", "252026-03-04 05:06:07.5") => "INSERT INTO t (\"c\") VALUES ('252026-03-04 05:06:07.5');" +insert("TIMESTAMP_LTZ(0)", "10000-01-01 01:02:03+00:00") => "INSERT INTO t (\"c\") VALUES ('10000-01-01 01:02:03+00:00');" +insert("TIMESTAMP_TZ(0)", "10000-01-01 01:02:03-07:00") => "INSERT INTO t (\"c\") VALUES ('10000-01-01 01:02:03-07:00');" +insert("DATE", "0000-02-29") => "INSERT INTO t (\"c\") VALUES ('0000-02-29');" +insert("DATE", "-0002-06-01") => "INSERT INTO t (\"c\") VALUES ('-0002-06-01');" +insert("DATE", "-0400-02-29") => "INSERT INTO t (\"c\") VALUES ('-0400-02-29');" +insert("DATE", "-10000-12-31") => "INSERT INTO t (\"c\") VALUES ('-10000-12-31');" +insert("TIMESTAMP_NTZ(9)", "-0002-06-01 12:34:56.876543211") => "INSERT INTO t (\"c\") VALUES ('-0002-06-01 12:34:56.876543211');" +insert("TIMESTAMP_TZ(0)", "-0401-03-01 23:59:59-07:00") => "INSERT INTO t (\"c\") VALUES ('-0401-03-01 23:59:59-07:00');" +insert("TIMESTAMP_LTZ(3)", "-0002-06-01 12:34:56.123+00:00") => "INSERT INTO t (\"c\") VALUES ('-0002-06-01 12:34:56.123+00:00');" +insert("DATE", "12/10/2026") => "INSERT INTO t (\"c\") VALUES ('12/10/2026');" +insert("TIMESTAMP_NTZ(3)", Date(1970-01-01T00:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('1970-01-01T00:00:00.000Z');" +insert("TIMESTAMP_TZ(0)", "2026-10-12 01:02:03") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 01:02:03');" +insert("DATE", "999-01-01") => "INSERT INTO t (\"c\") VALUES ('999-01-01');" +insert("DATE", "--0002-06-01") => "INSERT INTO t (\"c\") VALUES ('--0002-06-01');" +insert("DECFLOAT", "1.23e40") => "INSERT INTO t (\"c\") VALUES ('1.23e40');" +insert("DECFLOAT", "-4.2e-5432") => "INSERT INTO t (\"c\") VALUES ('-4.2e-5432');" +insert("DECFLOAT", "1e16384") => "INSERT INTO t (\"c\") VALUES ('1e16384');" +insert("DECFLOAT", "0.1") => "INSERT INTO t (\"c\") VALUES ('0.1');" +insert("DECFLOAT", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("NUMBER(10,2)", "12.50") => "INSERT INTO t (\"c\") VALUES ('12.50');" +insert("NUMBER(38,0)", "123456789012345678901234567890") => "INSERT INTO t (\"c\") VALUES ('123456789012345678901234567890');" +insert("DECFLOAT", "-1.5e-300") => "INSERT INTO t (\"c\") VALUES ('-1.5e-300');" +insert("NUMBER(10,2)", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("NUMBER(38,0)", 7) => "INSERT INTO t (\"c\") VALUES (7);" +insert("FLOAT", 1.5) => "INSERT INTO t (\"c\") VALUES (1.5);" +insert("VARCHAR(10)", "a") => "INSERT INTO t (\"c\") VALUES ('a');" +insert("BOOLEAN", true) => "INSERT INTO t (\"c\") VALUES (true);" +insert("BINARY", bytes(01)) => "INSERT INTO t (\"c\") VALUES (X'01');" +insert("GEOGRAPHY", "POINT(1 2)") => "INSERT INTO t (\"c\") VALUES ('POINT(1 2)');" +insert(undefined, "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("date", "2026-10-12") => "INSERT INTO t (\"c\") VALUES ('2026-10-12');" +insert("date", "0001-01-01") => "INSERT INTO t (\"c\") VALUES ('0001-01-01');" +insert("timestamp", "2026-10-12 13:45:30.123456+00:00") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 13:45:30.123456+00:00');" +insert("timestamp_ntz", "2026-10-12 13:45:30") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 13:45:30');" +insert("time(6)", "13:45:30.5") => "INSERT INTO t (\"c\") VALUES ('13:45:30.5');" +insert("date", "12/10/2026") => "INSERT INTO t (\"c\") VALUES ('12/10/2026');" +insert("timestamp", "2026-10-12 13:45:30") => "INSERT INTO t (\"c\") VALUES ('2026-10-12 13:45:30');" +insert("timestamp_ntz", "x'; DROP TABLE t; --") => "INSERT INTO t (\"c\") VALUES ('x''; DROP TABLE t; --');" +insert("decimal(10,2)", "12345678.91") => "INSERT INTO t (\"c\") VALUES ('12345678.91');" +insert("decimal(3,2)", "-0.50") => "INSERT INTO t (\"c\") VALUES ('-0.50');" +insert("decimal(1,-10)", "10000000000") => "INSERT INTO t (\"c\") VALUES ('10000000000');" +insert("bigint", "9007199254740993") => "INSERT INTO t (\"c\") VALUES ('9007199254740993');" +insert("bigint", 42) => "INSERT INTO t (\"c\") VALUES (42);" +insert("double", 1.5) => "INSERT INTO t (\"c\") VALUES (1.5);" +insert("decimal(10,2)", "1e3") => "INSERT INTO t (\"c\") VALUES ('1e3');" +insert("bigint", "12 345") => "INSERT INTO t (\"c\") VALUES ('12 345');" +insert("interval", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("interval year to month", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("geometry(4326)", "POINT (1 2)") => "INSERT INTO t (\"c\") VALUES ('POINT (1 2)');" +insert("map", {"1":"a"}) => "INSERT INTO t (\"c\") VALUES ('{\"1\":\"a\"}');" +insert("interval year to month", "INTERVAL '3-7' YEAR TO MONTH") => "INSERT INTO t (\"c\") VALUES ('INTERVAL ''3-7'' YEAR TO MONTH');" +insert("interval day to second", "INTERVAL '-1 02:03:04.567891' DAY TO SECOND") => "INSERT INTO t (\"c\") VALUES ('INTERVAL ''-1 02:03:04.567891'' DAY TO SECOND');" +insert("interval hour", "INTERVAL '26' HOUR") => "INSERT INTO t (\"c\") VALUES ('INTERVAL ''26'' HOUR');" +insert("interval day", "INTERVAL '1' DAY; DROP") => "INSERT INTO t (\"c\") VALUES ('INTERVAL ''1'' DAY; DROP');" +insert("interval", "3 months 2 days 1 microseconds") => "INSERT INTO t (\"c\") VALUES ('3 months 2 days 1 microseconds');" +insert("variant", "{\"a\":\"it's\"}") => "INSERT INTO t (\"c\") VALUES ('{\"a\":\"it''s\"}');" +insert("array", [1,null,3]) => "INSERT INTO t (\"c\") VALUES ('[1,null,3]');" +insert("map", {"k":"v\\"}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":\"v\\\\\"}');" +insert("struct<`it's`:int>", {"it's":1}) => "INSERT INTO t (\"c\") VALUES ('{\"it''s\":1}');" +insert("array", [1,"9007199254740993"]) => "INSERT INTO t (\"c\") VALUES ('[1,\"9007199254740993\"]');" +insert("array", ["\\x0102"]) => "INSERT INTO t (\"c\") VALUES ('[\"\\\\x0102\"]');" +insert("map", {"k":"\\x01"}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":\"\\\\x01\"}');" +insert("struct", {"b":"\\x01","n":1}) => "INSERT INTO t (\"c\") VALUES ('{\"b\":\"\\\\x01\",\"n\":1}');" +insert("array", ["{\"a\":1}"]) => "INSERT INTO t (\"c\") VALUES ('[\"{\\\"a\\\":1}\"]');" +insert("ARRAY>>", [[{"v":"1"}]]) => "INSERT INTO t (\"c\") VALUES ('[[{\"v\":\"1\"}]]');" +insert("struct", {"g":"SRID=4326;POINT (1 2)"}) => "INSERT INTO t (\"c\") VALUES ('{\"g\":\"SRID=4326;POINT (1 2)\"}');" +insert("array", ["SRID=4326;POINT (1 2)"]) => "INSERT INTO t (\"c\") VALUES ('[\"SRID=4326;POINT (1 2)\"]');" +insert("struct", {"variant":1,"binary":"x"}) => "INSERT INTO t (\"c\") VALUES ('{\"variant\":1,\"binary\":\"x\"}');" +insert("struct<`a:binary`:int>", {"a:binary":1}) => "INSERT INTO t (\"c\") VALUES ('{\"a:binary\":1}');" +insert("struct,int>>", {"m":[[[1],2]]}) => "INSERT INTO t (\"c\") VALUES ('{\"m\":[[[1],2]]}');" +insert("map", {"k":1}) => "INSERT INTO t (\"c\") VALUES ('{\"k\":1}');" +insert("struct>", {"map":{"k":1}}) => "INSERT INTO t (\"c\") VALUES ('{\"map\":{\"k\":1}}');" +insert("struct", {"a":"x"}) => "INSERT INTO t (\"c\") VALUES ('{\"a\":\"x\"}');" +insert("array", ["x"]) => "INSERT INTO t (\"c\") VALUES ('[\"x\"]');" +insert("map,string>", [[[1],"v"]]) => "INSERT INTO t (\"c\") VALUES ('[[[1],\"v\"]]');" +insert("geometry(4326)", "SRID=4326;POINT (1 2)") => "INSERT INTO t (\"c\") VALUES ('SRID=4326;POINT (1 2)');" +insert("geography(4326)", "SRID=4326;POINT (1 2)") => "INSERT INTO t (\"c\") VALUES ('SRID=4326;POINT (1 2)');" +insert("variant", 1) => "INSERT INTO t (\"c\") VALUES (1);" +insert("string", "x") => "INSERT INTO t (\"c\") VALUES ('x');" +insert("char(5)", "ab ") => "INSERT INTO t (\"c\") VALUES ('ab ');" +insert("binary", bytes(0102)) => "INSERT INTO t (\"c\") VALUES (X'0102');" +insert(undefined, "2026-10-12") => "INSERT INTO t (\"c\") VALUES ('2026-10-12');" +insert("double precision", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("double precision", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("double precision", "-Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("REAL", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("REAL", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("REAL", "-Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("float8", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("float8", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("float8", "-Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("BINARY_DOUBLE", "NaN") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("BINARY_DOUBLE", "Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("BINARY_DOUBLE", "-Infinity") => "INSERT INTO t (\"c\") VALUES (NULL);" +insert("Nullable(Float64)", "NaN") => "INSERT INTO t (\"c\") VALUES ('NaN');" +insert("Nullable(Float64)", "Infinity") => "INSERT INTO t (\"c\") VALUES ('Infinity');" +insert("Nullable(Float64)", "-Infinity") => "INSERT INTO t (\"c\") VALUES ('-Infinity');" +insert("text", "NaN") => "INSERT INTO t (\"c\") VALUES ('NaN');" +insert("text", "Infinity") => "INSERT INTO t (\"c\") VALUES ('Infinity');" +insert("text", "-Infinity") => "INSERT INTO t (\"c\") VALUES ('-Infinity');" +insert("DATE", Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP(6)", Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP(6) WITH TIME ZONE", Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("VARCHAR2(20)", Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert(undefined, Date(2026-08-24T07:11:12.345Z)) => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("DATE", Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert("TIMESTAMP(6)", Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert("TIMESTAMP(6) WITH TIME ZONE", Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert("VARCHAR2(20)", Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert(undefined, Date(-000044-03-15T12:00:00.000Z)) => "INSERT INTO t (\"c\") VALUES ('-000044-03-15T12:00:00.000Z');" +insert("DATE", "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert("TIMESTAMP(6)", "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert("TIMESTAMP(6) WITH TIME ZONE", "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert("VARCHAR2(20)", "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert(undefined, "2026-08-24 10:11:12") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12');" +insert("DATE", "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert("TIMESTAMP(6)", "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert("TIMESTAMP(6) WITH TIME ZONE", "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert("VARCHAR2(20)", "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert(undefined, "2026-08-24 10:11:12.5") => "INSERT INTO t (\"c\") VALUES ('2026-08-24 10:11:12.5');" +insert("DATE", "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert("TIMESTAMP(6)", "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert("TIMESTAMP(6) WITH TIME ZONE", "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert("VARCHAR2(20)", "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert(undefined, "-0044-03-15 12:00:00") => "INSERT INTO t (\"c\") VALUES ('-0044-03-15 12:00:00');" +insert("DATE", "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP(6)", "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP(6) WITH TIME ZONE", "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("VARCHAR2(20)", "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert(undefined, "2026-08-24T07:11:12.345Z") => "INSERT INTO t (\"c\") VALUES ('2026-08-24T07:11:12.345Z');" +insert("DATE", "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +insert("TIMESTAMP(6)", "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +insert("TIMESTAMP(6) WITH TIME ZONE", "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +insert("TIMESTAMP WITH LOCAL TIME ZONE", "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +insert("VARCHAR2(20)", "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +insert(undefined, "not a date") => "INSERT INTO t (\"c\") VALUES ('not a date');" +csv(numeric) => "nf,lc,df,nm,bd,tx,none\n-Infinity,-Infinity,-Infinity,-Infinity,-Infinity,\"'-Infinity\",\"'-Infinity\"\n\"'=1+1\",\"'=1+1\",\"'=1+1\",\"'=1+1\",\"'=1+1\",\"'=1+1\",\"'=1+1\"" \ No newline at end of file diff --git a/tests/unit/db/test-data-generation-capability.test.ts b/tests/unit/db/test-data-generation-capability.test.ts index b06ec48072..fe55f21b8f 100644 --- a/tests/unit/db/test-data-generation-capability.test.ts +++ b/tests/unit/db/test-data-generation-capability.test.ts @@ -42,6 +42,7 @@ const OFFERED: Readonly> = Object.freeze({ neo4j: false, milvus: false, qdrant: false, + weaviate: false, influxdb: false, influxdb3: false, oxia: false, diff --git a/tests/unit/db/weaviate/client.test.ts b/tests/unit/db/weaviate/client.test.ts new file mode 100644 index 0000000000..656fe990f6 --- /dev/null +++ b/tests/unit/db/weaviate/client.test.ts @@ -0,0 +1,77 @@ +/** + * The Weaviate client seam (#1566 spec 3.1): the operations, the console's routes first in table order and then the + * two the provider writes itself, the error an answer is classified into, and the slice of the client a consumer is + * handed, which can send only the operations it names. + */ +import { describe, expect, test } from "bun:test"; +import { + type WeaviateAnswer, + type WeaviateClient, + WeaviateError, + type WeaviateSend, + WEAVIATE_OPS, +} from "@/lib/db/providers/vector/weaviate/client"; +import { WEAVIATE_CLIENT_ROUTES, WEAVIATE_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; + +describe("the operations", () => { + test("are the console's 17 routes in table order, then ready and graphql", () => { + expect(WEAVIATE_OPS).toEqual([...WEAVIATE_ROUTES.map((route) => route.op), "ready", "graphql"]); + }); + + test("each has one method, path and query key list in the client's table", () => { + expect(Object.keys(WEAVIATE_CLIENT_ROUTES).sort()).toEqual([...WEAVIATE_OPS].sort()); + expect(WEAVIATE_CLIENT_ROUTES.ready).toEqual({ method: "GET", path: "/v1/.well-known/ready", query: [] }); + expect(WEAVIATE_CLIENT_ROUTES.graphql).toEqual({ method: "POST", path: "/v1/graphql", query: [] }); + }); + + test("hold no write", () => { + for (const op of WEAVIATE_OPS) expect(op).not.toMatch(/batch|delete|update|create|put|patch|backup|user|role/); + }); +}); + +describe("WeaviateError", () => { + test("carries the category, the server's words and the status, and names them in its message", () => { + const error = new WeaviateError("forbidden", "permission denied: read_data", 403); + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(WeaviateError); + expect({ + name: error.name, + message: error.message, + category: error.category, + detail: error.detail, + status: error.status, + retryAfter: error.retryAfter, + }).toEqual({ + name: "WeaviateError", + message: "Weaviate answered HTTP 403 (forbidden)", + category: "forbidden", + detail: "permission denied: read_data", + status: 403, + retryAfter: null, + }); + }); + + test("a 429 keeps its Retry-After", () => { + expect(new WeaviateError("rate-limited", "slow down", 429, "5").retryAfter).toBe("5"); + }); +}); + +describe("the slice a consumer is handed", () => { + test("sends through the client, and the type admits only the operations it names", async () => { + const sent: string[] = []; + const answer: WeaviateAnswer = { status: 200, contentType: "application/json", retryAfter: null, text: "{}" }; + const client: WeaviateClient = { + send: async (request) => { + sent.push(request.op); + return answer; + }, + close: () => {}, + }; + const send: WeaviateSend<"meta" | "schema"> = (request, signal) => client.send(request, signal); + const signal = new AbortController().signal; + expect(await send({ op: "meta", params: {}, query: {} }, signal)).toBe(answer); + // @ts-expect-error a slice typed to meta and schema cannot send a search + await send({ op: "search_bm25", params: { collection: "Article" }, query: {}, body: "{}" }, signal); + expect(sent).toEqual(["meta", "search_bm25"]); + }); +}); diff --git a/tests/unit/db/weaviate/connection-options.test.ts b/tests/unit/db/weaviate/connection-options.test.ts new file mode 100644 index 0000000000..088c534c7d --- /dev/null +++ b/tests/unit/db/weaviate/connection-options.test.ts @@ -0,0 +1,346 @@ +/** + * The Weaviate connection (#1566 spec 6.1, doc section 4): the endpoint check (W1), the bearer token, the plaintext + * rule (W2), the TLS mapping, the tunnel's far end, the read-only source and the seed stage, the query timeout and + * the secret forms. Every refusal is a DatabaseConfigError raised before any client exists, and none repeats the + * value it refuses. + */ +import { afterEach, describe, expect, test } from "bun:test"; +import { DatabaseConfigError } from "@/lib/db/errors"; +import { BLOCKED_HOST } from "@/lib/db/http/egress-policy"; +import { + buildWeaviateConnectionOptions, + WEAVIATE_DEFAULT_PORT, + WEAVIATE_MAX_IN_FLIGHT, + WEAVIATE_RESPONSE_CAP_BYTES, +} from "@/lib/db/providers/vector/weaviate/connection-options"; +import { secretForms } from "@/lib/db/utils/server-text"; +import { type DatabaseConnection, TUNNEL_FAR_END } from "@/lib/types"; + +// A named placeholder, never a realistic value: a credential in a test fixture is a stand-in. +const TEST_PASSWORD = "password"; +const CONTEXT = { executionReadOnly: false, queryTimeout: 30_000 }; +const EXITS = [ + "Choose an SSL mode under SSL / TLS", + "connect through an SSH tunnel", + "if authentication is off on this server, clear the API key or token", +]; +const FLAG = "DB_HTTP_BLOCK_PRIVATE_HOSTS"; +const originalFlag = process.env[FLAG]; + +afterEach(() => { + if (originalFlag === undefined) delete process.env[FLAG]; + else process.env[FLAG] = originalFlag; +}); + +function connection(overrides: Record = {}): DatabaseConnection { + return { + id: "c1", + name: "Weaviate", + type: "weaviate", + host: "weaviate.test", + port: 8080, + createdAt: new Date(0), + ...overrides, + } as unknown as DatabaseConnection; +} + +const build = (overrides: Record = {}, context = CONTEXT) => + buildWeaviateConnectionOptions(connection(overrides), context); + +function tunnelled(overrides: Record, farEnd: { host: string; port: number }) { + return buildWeaviateConnectionOptions( + { + ...connection({ host: "127.0.0.1", port: 41_001, sshTunnel: { enabled: true }, ...overrides }), + [TUNNEL_FAR_END]: farEnd, + }, + CONTEXT, + ); +} + +function refusal(overrides: Record, context = CONTEXT): DatabaseConfigError { + try { + build(overrides, context); + } catch (error) { + expect(error).toBeInstanceOf(DatabaseConfigError); + expect(String((error as DatabaseConfigError).provider)).toBe("weaviate"); + return error as DatabaseConfigError; + } + throw new Error("buildWeaviateConnectionOptions answered, though this case must be refused"); +} + +const TLS_FULL = { ssl: { mode: "verify-full" } }; +const LOCAL = { host: "127.0.0.1" }; + +describe("W1: the endpoint is exactly what it claims", () => { + test("the origin is the validated host and port over http, 8080 by default", () => { + expect(build().origin).toEqual({ scheme: "http", host: "weaviate.test", port: 8080 }); + expect(WEAVIATE_DEFAULT_PORT).toBe(8080); + expect(build({ port: undefined }).origin.port).toBe(8080); + expect(build({ port: null }).origin.port).toBe(8080); + expect(build({ port: "8443" }).origin.port).toBe(8443); + expect(build().endpoint).toEqual({ host: "weaviate.test", port: 8080 }); + }); + + test("TLS makes the origin https on the same port", () => { + expect(build(TLS_FULL).origin).toEqual({ scheme: "https", host: "weaviate.test", port: 8080 }); + }); + + test("an IPv6 literal is bracketed in the origin and bare in the endpoint, written either way", () => { + for (const host of ["::1", "[::1]"]) { + const options = build({ host }); + expect(options.origin.host).toBe("[::1]"); + expect(options.endpoint.host).toBe("::1"); + } + }); + + test.each([ + "http://localhost:8080", + "weaviate.test:8080", + "weaviate.test/v1", + "user@weaviate.test", + "weaviate.test?x=1", + "", + 7, + null, + ])("the host %j is refused in the shared validator's words, as Weaviate's, and never repeated", (host) => { + expect(refusal({ host }).message).toBe("Invalid host: expected a hostname, an IPv4 address or an IPv6 address"); + }); + + test.each([0, 65_536, 1.5, "8080a", -1])("the port %j is refused", (port) => { + expect(refusal({ port }).message).toBe("Invalid port: expected an integer from 1 to 65535"); + }); + + test("with the egress guard on, a private literal host is refused before anything else is read", () => { + process.env[FLAG] = "true"; + expect(refusal({ host: "10.0.0.5", user: "someone" }).message).toBe(BLOCKED_HOST); + expect(build({ host: "weaviate.example.com" }).origin.host).toBe("weaviate.example.com"); + }); +}); + +describe("the SSH tunnel: the local forward is dialled, the far end is what sentences and TLS name", () => { + test("through a tunnel the origin is the local forward and the endpoint the far end", () => { + const options = tunnelled({}, { host: "weaviate.internal", port: 8080 }); + expect(options.origin).toEqual({ scheme: "http", host: "127.0.0.1", port: 41_001 }); + expect(options.endpoint).toEqual({ host: "weaviate.internal", port: 8080 }); + expect(tunnelled({}, { host: "[fd00::5]", port: 8080 }).endpoint.host).toBe("fd00::5"); + }); + + test("a far end that is no host or port is refused like the connection's own, as Weaviate's", () => { + for (const [farEnd, words] of [ + [{ host: "a/b", port: 8080 }, "Invalid host"], + [{ host: "weaviate.internal", port: 0 }, "Invalid port"], + ] as const) { + let thrown: unknown; + try { + tunnelled({}, farEnd); + } catch (error) { + thrown = error; + } + expect(thrown).toBeInstanceOf(DatabaseConfigError); + expect(String((thrown as DatabaseConfigError).provider)).toBe("weaviate"); + expect((thrown as Error).message).toStartWith(words); + } + }); + + test("a tunnel that is on but arrived with no far end is refused, so Weaviate is never dialled past it", () => { + expect(refusal({ sshTunnel: { enabled: true } }).message).toBe( + "This connection's SSH tunnel is on, but the connection arrived without its tunnel, so Weaviate was not dialled directly: the tunnel opens only when both Host and Port are set.", + ); + expect(build({ sshTunnel: { enabled: false } }).origin.host).toBe("weaviate.test"); + expect(build({ sshTunnel: { enabled: null } }).origin.host).toBe("weaviate.test"); + expect(build({ sshTunnel: null }).origin.host).toBe("weaviate.test"); + }); + + test("a tunnel field of the wrong type is refused naming the field", () => { + for (const sshTunnel of ["on", [], 1]) { + expect(refusal({ sshTunnel }).message).toBe("The connection's sshTunnel must be an object; nothing was sent."); + } + expect(refusal({ sshTunnel: { enabled: "yes" } }).message).toBe( + "The connection's sshTunnel.enabled must be true or false; nothing was sent.", + ); + }); +}); + +describe("the bearer token is validated and never echoed", () => { + test("the secret travels as one Authorization: Bearer header and nothing else", () => { + expect(build({ ...LOCAL, password: TEST_PASSWORD }).headers).toEqual({ authorization: `Bearer ${TEST_PASSWORD}` }); + }); + + test("no secret sends no header: an empty string and null are absent", () => { + expect(build().headers).toEqual({}); + expect(build({ password: "" }).headers).toEqual({}); + expect(build({ password: null, user: "" }).headers).toEqual({}); + expect(build({ user: null }).secretForms).toEqual([]); + }); + + test.each([ + ["a space", "abc def"], + ["a line feed", "abc\n"], + ["a carriage return", "a\rb"], + ["a NUL", "abc\u0000"], + ["a tab", "a\tb"], + ["a DEL", "abc\u007f"], + ["a non-breaking space", "abc "], + ["a character outside Latin-1", "abc中"], + ])("a secret holding %s is refused naming the field, never the value", (_what, password) => { + const error = refusal({ ...LOCAL, password }); + expect(error.message).toBe( + "The connection's password (the API key or token) holds a space, a line break, a NUL or another character outside printable ASCII; remove it. Nothing was sent.", + ); + expect(error.message).not.toContain(password); + }); + + test("a secret that is not a string is refused naming the field", () => { + for (const password of [12_345, true, { key: TEST_PASSWORD }, [TEST_PASSWORD]]) { + expect(refusal({ ...LOCAL, password }).message).toBe( + "The connection's password must be a string; nothing was sent.", + ); + } + }); + + test("a user is refused naming the field, because Weaviate takes none", () => { + const error = refusal({ ...LOCAL, user: "admin", password: TEST_PASSWORD }); + expect(error.message).toBe( + "Weaviate takes no user name: clear the connection's user, and put the API key or OIDC access token in the password. Nothing was sent.", + ); + expect(error.message).not.toContain("admin"); + expect(refusal({ ...LOCAL, user: 7 }).message).toBe("The connection's user must be a string; nothing was sent."); + }); + + test("the secret forms are the token's, and each segment of a JWT-shaped OIDC token", () => { + expect(build({ ...LOCAL, password: TEST_PASSWORD }).secretForms).toEqual(secretForms([TEST_PASSWORD])); + const jwt = [ + Buffer.from('{"alg":"RS256","typ":"JWT"}').toString("base64url"), + Buffer.from('{"sub":"reader"}').toString("base64url"), + Buffer.from("signature-stand-in").toString("base64url"), + ].join("."); + const options = build({ ...LOCAL, password: jwt }); + expect(options.headers).toEqual({ authorization: `Bearer ${jwt}` }); + expect(options.secretForms).toEqual(secretForms([jwt])); + for (const segment of jwt.split(".")) expect(options.secretForms).toContain(segment); + }); +}); + +describe("W2: a secret never travels in the clear outside the machine", () => { + const secret = { password: TEST_PASSWORD }; + + test.each([ + ["absent", {}], + ["null", { ssl: null }], + ["disable", { ssl: { mode: "disable" } }], + ])("a secret with the TLS panel %s to a remote host is refused with all three exits", (_name, ssl) => { + for (const host of ["weaviate.example.com", "localhost.example", "128.0.0.1"]) { + const message = refusal({ ...secret, ...ssl, host }).message; + expect(message).toStartWith( + "This connection would send its API key or token without TLS to a host that is not this machine", + ); + for (const exit of EXITS) expect(message).toContain(exit); + expect(message).not.toContain(host); + expect(message).not.toContain(TEST_PASSWORD); + } + }); + + test.each(["127.0.0.1", "::1", "localhost"])("a secret over no TLS to the loopback host %s opens", (host) => { + expect(build({ ...secret, host }).headers).toEqual({ authorization: `Bearer ${TEST_PASSWORD}` }); + }); + + test("the rule reads the far end under a tunnel, and a tunnel carries the secret inside SSH", () => { + expect(tunnelled(secret, { host: "weaviate.example.com", port: 8080 }).headers).toEqual({ + authorization: `Bearer ${TEST_PASSWORD}`, + }); + }); + + test("no secret opens anywhere, and TLS require opens a remote host", () => { + expect(build({ host: "weaviate.example.com" }).headers).toEqual({}); + expect(build({ ...secret, host: "weaviate.example.com", ssl: { mode: "require" } }).tls).toMatchObject({ + rejectUnauthorized: false, + }); + }); +}); + +describe("the SSL / TLS panel through nodeTlsMaterial", () => { + test("disable and an absent panel are plaintext; require does not verify; every verify mode verifies", () => { + expect(build().tls).toBeNull(); + expect(build({ ssl: { mode: "disable" } }).tls).toBeNull(); + expect(build({ ssl: { mode: "require" } }).tls?.rejectUnauthorized).toBe(false); + for (const mode of ["verify-system", "verify-ca", "verify-full"]) { + expect(build({ ssl: { mode } }).tls?.rejectUnauthorized).toBe(true); + } + }); + + test("the CA, the client certificate and its key are passed as bytes", () => { + const tls = build({ ssl: { mode: "verify-full", caCert: "CA", clientCert: "CERT", clientKey: "KEY" } }).tls; + expect(tls?.ca?.toString()).toBe("CA"); + expect(tls?.cert?.toString()).toBe("CERT"); + expect(tls?.key?.toString()).toBe("KEY"); + }); + + test("a panel of the wrong kind is refused in the shared words, as Weaviate's", () => { + expect(refusal({ ssl: "on" }).message).toBe("Invalid ssl: expected an object"); + expect(refusal({ ssl: { mode: "prefer" } }).message).toBe( + "Invalid ssl.mode: expected disable, require, verify-system, verify-ca or verify-full", + ); + }); + + test("the identity is the endpoint host, without brackets, and the far end under a tunnel", () => { + expect(build(TLS_FULL).tls?.identity).toBe("weaviate.test"); + expect(build({ ...TLS_FULL, host: "[::1]" }).tls?.identity).toBe("::1"); + const options = tunnelled(TLS_FULL, { host: "weaviate.internal", port: 8080 }); + expect(options.tls?.identity).toBe("weaviate.internal"); + expect(options.origin).toEqual({ scheme: "https", host: "127.0.0.1", port: 41_001 }); + }); +}); + +describe("the read-only source, the bounds and the query timeout", () => { + test("read-only comes from the connection, a seed, or the execution profile, in that order", () => { + const keyed = { ...LOCAL, password: TEST_PASSWORD }; + expect(build({ readOnly: true }).readOnly).toBe("connection"); + expect(build({ readOnly: true, seedId: "s1", ...keyed }).readOnly).toBe("seed"); + expect(build({ readOnly: true, seedId: "" }).readOnly).toBe("connection"); + expect(build({ readOnly: true, seedId: null }).readOnly).toBe("connection"); + expect(build({}, { ...CONTEXT, executionReadOnly: true }).readOnly).toBe("execution-profile"); + expect(build({ readOnly: false }, { ...CONTEXT, executionReadOnly: true }).readOnly).toBe("execution-profile"); + expect(Object.hasOwn(build(), "readOnly")).toBe(false); + expect(Object.hasOwn(build({ readOnly: false }), "readOnly")).toBe(false); + }); + + test("a readOnly that is not a boolean, and a seedId that is not text, are refused", () => { + expect(refusal({ readOnly: "yes" }).message).toBe("readOnly must be true or false."); + expect(refusal({ readOnly: null }).message).toBe("readOnly must be true or false."); + expect(refusal({ readOnly: true, seedId: 7 }).message).toBe( + "The connection's seedId must be a string; nothing was sent.", + ); + }); + + test("the socket bound is the in-flight bound, and the response cap is 16 MiB", () => { + expect(build().maxSockets).toBe(WEAVIATE_MAX_IN_FLIGHT); + expect(WEAVIATE_MAX_IN_FLIGHT).toBe(4); + expect(build().responseCapBytes).toBe(WEAVIATE_RESPONSE_CAP_BYTES); + expect(WEAVIATE_RESPONSE_CAP_BYTES).toBe(16_777_216); + }); + + test("the query timeout is the deadline cap, within the dialog's bound", () => { + expect(build({}, { ...CONTEXT, queryTimeout: 1 }).callTimeoutMs).toBe(1); + expect(build({}, { ...CONTEXT, queryTimeout: 2_147_483_647 }).callTimeoutMs).toBe(2_147_483_647); + for (const queryTimeout of [0, -1, 1.5, 2_147_483_648, Number.NaN, Number.POSITIVE_INFINITY]) { + expect(refusal({}, { ...CONTEXT, queryTimeout }).message).toBe( + "Query timeout must be a whole number between 1 and 2147483647 milliseconds.", + ); + } + }); +}); + +describe("the seed stage: a read-only seed without a key is refused, before any client exists", () => { + test("the weaviate record's no-secret entry refuses a read-only seed without a key", () => { + expect(refusal({ readOnly: true, seedId: "s1" }).message).toBe( + "Credential warning: A Weaviate server with anonymous access on, its default, answers a request that carries no key and grants it every write, so a read-only seed without a key promises a boundary the server does not keep. This read-only seed connection is refused with this credential, because the mode would promise a boundary the server does not keep; nothing was sent.", + ); + expect(refusal({ readOnly: true, seedId: "s1", password: "" }).message).toStartWith("Credential warning: "); + }); + + test("a seed holding a key, a seed that is not read-only, and a read-only connection that is no seed pass", () => { + expect(build({ readOnly: true, seedId: "s1", ...LOCAL, password: TEST_PASSWORD }).readOnly).toBe("seed"); + expect(build({ seedId: "s1" }).headers).toEqual({}); + expect(build({ readOnly: true }).readOnly).toBe("connection"); + }); +}); diff --git a/tests/unit/db/weaviate/errors.test.ts b/tests/unit/db/weaviate/errors.test.ts new file mode 100644 index 0000000000..a8137e36ce --- /dev/null +++ b/tests/unit/db/weaviate/errors.test.ts @@ -0,0 +1,566 @@ +/** + * The Weaviate error table (#1566 spec 5.6, doc section 10): the category the status and the server's words decide, + * the class and sentence each category reads as, the server's words withheld whole when they hold the secret, and a + * request that never completed. + * + * The 401, the TLS 400 and the bodyless 404 are the answers live servers gave, read from tests/fixtures/weaviate/. + * Every other server text is written in the shape errors.ts documents (`{"error":[{"message"}]}` from a handler, + * `{"code","message"}` from the router, `{"errors":[{"message"}]}` from GraphQL), with the words the phase 0 + * measurements recorded, and its test name says "in the documented shape". + */ +import { describe, expect, test } from "bun:test"; +import { + AuthenticationError, + ConnectionError, + DatabaseConfigError, + QueryCancelledError, + QueryError, + TimeoutError, +} from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import { type WeaviateAnswer, WeaviateError, type WeaviateOp } from "@/lib/db/providers/vector/weaviate/client"; +import { + answerFailure, + expectOk, + graphqlFailure, + retryAfterSeconds, + serverWords, + toProviderError, + type WeaviateErrorContext, +} from "@/lib/db/providers/vector/weaviate/errors"; +import { secretForms } from "@/lib/db/utils/server-text"; +import { capturedAnswer } from "../../../helpers/weaviate-wire"; + +// A named placeholder, never a realistic value: a credential in a test fixture is a stand-in. +const TEST_PASSWORD = "password"; +const WITHHELD = "(the server's text was withheld because it contained the configured credential)"; + +const CONTEXT: WeaviateErrorContext = { + phase: "request", + op: "objects", + endpoint: { host: "weaviate.test", port: 8080 }, + responseCapBytes: 16 * 1024 * 1024, + timeoutMs: 30_000, + secretForms: secretForms([TEST_PASSWORD]), +}; + +const NO_KEY = capturedAnswer("weaviate-auth/no-key.json", "GET /v1/meta"); +const WRONG_KEY = capturedAnswer("weaviate-auth/wrong-key.json", "GET /v1/meta"); +const PLAIN_TO_TLS = capturedAnswer("weaviate-tls/plain-to-tls.json", "GET /v1/meta"); +const NO_OBJECT = capturedAnswer( + "weaviate-1-37/reads.json", + "GET /v1/objects/Article/00000000-0000-0000-0000-000000000000", +); + +const handler = (status: number, ...messages: string[]): WeaviateAnswer => ({ + status, + contentType: "application/json", + retryAfter: null, + text: JSON.stringify({ error: messages.map((message) => ({ message })) }), +}); +const router = (status: number, message: string): WeaviateAnswer => ({ + status, + contentType: "application/json", + retryAfter: null, + text: JSON.stringify({ code: status, message }), +}); +const graphql = (...messages: string[]): WeaviateAnswer => ({ + status: 200, + contentType: "application/json", + retryAfter: null, + text: JSON.stringify({ data: { Get: { Article: null } }, errors: messages.map((message) => ({ message })) }), +}); +const plain = (status: number, text: string, retryAfter: string | null = null): WeaviateAnswer => ({ + status, + contentType: "text/plain; charset=utf-8", + retryAfter, + text, +}); + +const RBAC = + "rbac: authorization, forbidden action(s): [read_data] on resource(s) [Domain: data, Collection: Article, Tenant: *, Object: *]"; +const SCOPE = + "due to GraphQL introspection, this role must have the permission to read_collections on * (all) collections"; +const ROUTE_ABSENT = "path /v1/search/Article/bm25 was not found"; +const NO_COLLECTION = "could not find collection Nope"; +const UNKNOWN_CLASS = 'Cannot query field "Nope" on type "GetObjectsObj".'; +const UNKNOWN_AGGREGATE = 'Cannot query field "Nope" on type "AggregateObjectsObj".'; +const TENANT_COLD = 'tenant not active: "tenantA" is COLD'; +const REST_FLAG = "rest search api is experimental and not enabled"; +const GRAPHQL_OFF = "graphql api is disabled"; +const LIMIT = "query maximum results exceeded: limit 20000 > QUERY_MAXIMUM_RESULTS 10000"; + +function failureOf(answer: WeaviateAnswer): WeaviateError { + const failure = answerFailure(answer); + if (failure === undefined) throw new Error("the answer is a success"); + return failure; +} + +const worded = (answer: WeaviateAnswer, context: WeaviateErrorContext = CONTEXT): Error => + toProviderError(failureOf(answer), context); + +describe("serverWords: every message of the error body, else the body as text", () => { + test("the captured 401s give their router message", () => { + expect(serverWords(NO_KEY.text)).toBe( + "anonymous access not enabled. Please authenticate through one of the available methods: [API-keys]", + ); + expect(serverWords(WRONG_KEY.text)).toBe("unauthorized: invalid api key"); + }); + + test("a handler's and GraphQL's lists give every message, joined, skipping entries with no text message", () => { + expect(serverWords(handler(422, "first", "second").text)).toBe("first; second"); + expect( + serverWords(JSON.stringify({ errors: [{ message: "a" }, null, 7, { message: 3 }, {}, { message: "b" }] })), + ).toBe("a; b"); + expect(serverWords(JSON.stringify({ error: [{ message: "h" }], errors: [{ message: "g" }] }))).toBe("h; g"); + }); + + test("with no listed message, a string message, then a string error, is the words", () => { + expect(serverWords(JSON.stringify({ error: [], message: "routed" }))).toBe("routed"); + expect(serverWords(JSON.stringify({ error: "plain error" }))).toBe("plain error"); + }); + + test("a body that is not JSON, JSON without those fields, or too long to be a refusal, is the trimmed text", () => { + expect(serverWords(PLAIN_TO_TLS.text)).toBe("Client sent an HTTP request to an HTTPS server."); + expect(serverWords(' {"status":"down"} ')).toBe('{"status":"down"}'); + expect(serverWords('"text"')).toBe('"text"'); + expect(serverWords("null")).toBe("null"); + expect(serverWords("[1]")).toBe("[1]"); + expect(serverWords(JSON.stringify({ error: { message: "nested" } }))).toBe('{"error":{"message":"nested"}}'); + const long = JSON.stringify({ error: [{ message: "x".repeat(70_000) }] }); + expect(serverWords(long)).toBe(long); + expect(serverWords("")).toBe(""); + }); +}); + +describe("answerFailure: the status decides, the words refine", () => { + test("a 2xx is no failure", () => { + for (const status of [200, 204, 299]) expect(answerFailure(plain(status, ""))).toBeUndefined(); + }); + + test.each([ + ["the captured no-key 401", NO_KEY, "unauthenticated"], + ["the captured wrong-key 401", WRONG_KEY, "unauthenticated"], + ["a 403 RBAC refusal in the documented shape", handler(403, RBAC), "forbidden"], + ["a 403 GraphQL scope refusal in the documented shape", handler(403, SCOPE), "graphql-scope"], + ["a router 404 in the documented shape", router(404, ROUTE_ABSENT), "route-absent"], + ["a 404 missing collection in the documented shape", handler(404, NO_COLLECTION), "collection-not-found"], + ["a 404 unknown GraphQL class in the documented shape", handler(404, UNKNOWN_CLASS), "collection-not-found"], + ["the captured bodyless 404 of an object", NO_OBJECT, "not-found"], + ["a 404 with other words", handler(404, "tenant not found: tenantZ"), "not-found"], + ["a 404 naming a tenant that is not active", handler(404, TENANT_COLD), "not-found"], + ["a router 404 for another kind of path", router(404, "path /v1/a b was not found"), "not-found"], + ["a 422 cold tenant in the documented shape", handler(422, TENANT_COLD), "tenant-not-active"], + ["a 422 REST search behind its flag in the documented shape", handler(422, REST_FLAG), "rest-search-disabled"], + ["a 422 with GraphQL disabled in the documented shape", handler(422, GRAPHQL_OFF), "graphql-disabled"], + ["a 422 GraphQL scope refusal in the documented shape", handler(422, SCOPE), "graphql-scope"], + ["a 422 missing collection in the documented shape", handler(422, NO_COLLECTION), "collection-not-found"], + ["a 400 unknown aggregate class in the documented shape", handler(400, UNKNOWN_AGGREGATE), "collection-not-found"], + ["a 400 past QUERY_MAXIMUM_RESULTS in the documented shape", handler(400, LIMIT), "result-limit"], + ["the captured TLS listener's 400", PLAIN_TO_TLS, "tls-required"], + ["a 422 RBAC refusal in the documented shape", handler(422, RBAC), "forbidden"], + ["a 400 with other words", handler(400, "invalid 'limit': must be positive"), "input"], + ["a 422 with other words", handler(422, "no graphql provider present"), "input"], + ["a 429", plain(429, "too many requests", "7"), "rate-limited"], + ["a 500", handler(500, "an internal stand-in failure"), "server"], + ["a 502", plain(502, "Bad Gateway"), "server"], + ["a 503", plain(503, "not ready"), "unavailable"], + ["a 302", plain(302, ""), "unexpected-status"], + ["a 405", plain(405, "method not allowed"), "unexpected-status"], + ["a 409", handler(409, TENANT_COLD), "unexpected-status"], + ["a 199", plain(199, ""), "unexpected-status"], + ] as const)("%s is %s", (_what, answer, category) => { + const failure = failureOf(answer); + expect(failure).toBeInstanceOf(WeaviateError); + expect(failure.category).toBe(category); + expect(failure.status).toBe(answer.status); + }); + + test("the detail is the server's words, and the message never carries them", () => { + const failure = failureOf(handler(403, RBAC)); + expect(failure.detail).toBe(RBAC); + expect(failure.message).toBe("Weaviate answered HTTP 403 (forbidden)"); + expect(failure.name).toBe("WeaviateError"); + }); + + test("only a 429 keeps the Retry-After header", () => { + expect(failureOf(plain(429, "slow down", "7")).retryAfter).toBe("7"); + expect(failureOf(plain(429, "slow down")).retryAfter).toBeNull(); + expect(failureOf(plain(503, "busy", "7")).retryAfter).toBeNull(); + }); +}); + +describe("graphqlFailure: GraphQL answers its refusals under HTTP 200", () => { + test("a status that is not 2xx reads as answerFailure reads it", () => { + expect(graphqlFailure(handler(422, GRAPHQL_OFF))?.category).toBe("graphql-disabled"); + expect(graphqlFailure(NO_KEY)?.category).toBe("unauthenticated"); + }); + + test("a 200 whose body holds no errors is no failure", () => { + expect(graphqlFailure(plain(200, JSON.stringify({ data: { Get: { Article: [] } } })))).toBeUndefined(); + expect(graphqlFailure(plain(200, JSON.stringify({ data: {}, errors: [] })))).toBeUndefined(); + expect(graphqlFailure(plain(200, JSON.stringify({ errors: "one" })))).toBeUndefined(); + expect(graphqlFailure(plain(200, "null"))).toBeUndefined(); + expect(graphqlFailure(plain(200, "[]"))).toBeUndefined(); + }); + + test("a 200 that is not JSON is an unexpected status with no words", () => { + const failure = graphqlFailure(plain(200, "proxy")); + expect(failure?.category).toBe("unexpected-status"); + expect(failure?.detail).toBe(""); + expect(failure?.status).toBe(200); + }); + + test.each([ + ["a cold tenant", [TENANT_COLD], "tenant-not-active"], + ["the scope refusal", [SCOPE], "graphql-scope"], + ["an unknown class", [UNKNOWN_CLASS], "collection-not-found"], + ["an unknown aggregate class", [UNKNOWN_AGGREGATE], "collection-not-found"], + ["the result limit", [LIMIT], "result-limit"], + ["words no row reads", ['Syntax Error GraphQL request (1:3) Expected Name, found "}"'], "input"], + ["two messages, the second read", ["first problem", TENANT_COLD], "tenant-not-active"], + ] as const)("a 200 with errors in the documented shape naming %s is %s", (_what, messages, category) => { + const failure = graphqlFailure(graphql(...messages)); + expect(failure?.category).toBe(category); + expect(failure?.detail).toBe(messages.join("; ")); + expect(failure?.status).toBe(200); + expect(failure?.retryAfter).toBeNull(); + }); +}); + +describe("retryAfterSeconds: 1 to 9 digits, never echoed", () => { + test.each([ + ["7", 7], + ["0", 0], + ["999999999", 999_999_999], + ["007", 7], + ] as const)("%s is %d s", (value, seconds) => { + expect(retryAfterSeconds(value)).toBe(seconds); + }); + + test.each(["1234567890", "-5", "1.5", " 10", "10 ", "", "abc", "Sat, 03 Oct 2026 12:00:30 GMT", null])( + "%j names no wait", + (value) => { + expect(retryAfterSeconds(value)).toBeUndefined(); + }, + ); +}); + +describe("toProviderError: Studio's sentence first, the server's words after it", () => { + test("the captured 401s are authentication errors with the server's words", () => { + const noKey = worded(NO_KEY); + expect(noKey).toBeInstanceOf(AuthenticationError); + expect(noKey.message).toBe( + "Weaviate refused the API key or token. (Weaviate: anonymous access not enabled. Please authenticate through one of the available methods: [API-keys])", + ); + expect(String((noKey as AuthenticationError).provider)).toBe("weaviate"); + expect(worded(WRONG_KEY).message).toBe( + "Weaviate refused the API key or token. (Weaviate: unauthorized: invalid api key)", + ); + }); + + test("a 403 in the documented shape is an authentication error at connect and a query error after it", () => { + const connect = worded(handler(403, RBAC), { ...CONTEXT, phase: "connect", op: "meta" }); + expect(connect).toBeInstanceOf(AuthenticationError); + expect(connect.message).toBe(`The credential is not allowed to read this server's meta. (Weaviate: ${RBAC})`); + const request = worded(handler(403, RBAC)); + expect(request).toBeInstanceOf(QueryError); + expect(request).not.toBeInstanceOf(AuthenticationError); + expect(request.message).toBe(`The credential is not allowed to run this request. (Weaviate: ${RBAC})`); + }); + + test("the GraphQL scope refusal names the version where REST search serves, without the server's words", () => { + const sentence = + "This credential's role is scoped to some collections, and Weaviate allows GraphQL only to a role that may read every collection, so this server version (below 1.39.7, which serves REST search) cannot run the search for it."; + for (const answer of [handler(403, SCOPE), graphql(SCOPE)]) { + const error = toProviderError(graphqlFailure(answer) as WeaviateError, { ...CONTEXT, op: "graphql" }); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe(sentence); + } + }); + + test("a missing collection reads as missing or not visible, without the server's words", () => { + for (const answer of [handler(404, NO_COLLECTION), handler(400, UNKNOWN_CLASS)]) { + const error = worded(answer); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe("The collection does not exist or is not visible to this credential."); + } + }); + + test("a router 404 in the documented shape says the server has no such route", () => { + expect(worded(router(404, ROUTE_ABSENT)).message).toBe( + `This Weaviate server has no such route. (Weaviate: ${ROUTE_ABSENT})`, + ); + }); + + test.each([ + ["collection", "The collection does not exist or is not visible to this credential."], + ["shards", "The collection does not exist or is not visible to this credential."], + ["tenants", "The collection does not exist or is not visible to this credential."], + ["tenant", "The tenant does not exist in this collection."], + ["alias", "The alias does not exist."], + ["objects", "The collection does not exist or is not visible to this credential."], + ["object", "No object has this id in this collection."], + ["collection_nodes", "The collection does not exist or is not visible to this credential."], + ["meta", "Weaviate found nothing at the name or id the request gives."], + ["search_bm25", "Weaviate found nothing at the name or id the request gives."], + ] as const)("a bodyless 404 to %s reads %j", (op: WeaviateOp, sentence) => { + const error = worded(NO_OBJECT, { ...CONTEXT, op }); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe(sentence); + }); + + test("a 404 with words carries them after the not-found sentence, whatever the operation", () => { + expect(worded(handler(404, "tenant not found: tenantZ"), { ...CONTEXT, op: "tenant" }).message).toBe( + "Weaviate found nothing at the name or id the request gives. (Weaviate: tenant not found: tenantZ)", + ); + }); + + test.each([ + [ + "a cold tenant", + handler(422, TENANT_COLD), + `The tenant is not active, and Studio does not activate a tenant by reading it. (Weaviate: ${TENANT_COLD})`, + ], + [ + "REST search behind its flag", + handler(422, REST_FLAG), + `This Weaviate server keeps its REST search behind EXPERIMENTAL_REST_SEARCH_ENABLED, and GraphQL is not available either. (Weaviate: ${REST_FLAG})`, + ], + [ + "GraphQL disabled", + handler(422, GRAPHQL_OFF), + `This Weaviate server has GraphQL disabled. (Weaviate: ${GRAPHQL_OFF})`, + ], + [ + "the result limit", + handler(400, LIMIT), + `The request asks for more objects than the server's QUERY_MAXIMUM_RESULTS. (Weaviate: ${LIMIT})`, + ], + [ + "an input refusal", + handler(422, "invalid 'limit': must be positive"), + "Weaviate did not accept the request as written. (Weaviate: invalid 'limit': must be positive)", + ], + [ + "a 500", + handler(500, "an internal stand-in failure"), + "Weaviate failed to run the request (HTTP 500). (Weaviate: an internal stand-in failure)", + ], + [ + "a 405", + plain(405, "method not allowed"), + "Weaviate answered HTTP 405, which Studio does not read. (Weaviate: method not allowed)", + ], + ["a bodyless 302", plain(302, ""), "Weaviate answered HTTP 302, which Studio does not read."], + ] as const)("%s in the documented shape is a query error with its sentence", (_what, answer, sentence) => { + const error = worded(answer); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe(sentence); + }); + + test("the captured TLS 400 is a connection error asking for an SSL mode, naming the endpoint", () => { + const error = worded(PLAIN_TO_TLS); + expect(error).toBeInstanceOf(ConnectionError); + expect(error.message).toBe( + "Weaviate at weaviate.test:8080 speaks TLS on this port, and the connection sent plain HTTP: choose an SSL mode under SSL / TLS.", + ); + expect((error as ConnectionError).host).toBe("weaviate.test"); + expect((error as ConnectionError).port).toBe(8080); + }); + + test("an IPv6 endpoint is bracketed in a sentence", () => { + expect(worded(PLAIN_TO_TLS, { ...CONTEXT, endpoint: { host: "fd00::5", port: 8443 } }).message).toStartWith( + "Weaviate at [fd00::5]:8443 speaks TLS", + ); + }); + + test.each([ + ["7", "try again in 7 s"], + ["0", "try again in 0 s"], + ["1.5", "try again later"], + ["Sat, 03 Oct 2026 12:00:30 GMT", "try again later"], + [null, "try again later"], + ] as const)("a 429 with Retry-After %j says %s, and never echoes the header", (header, wait) => { + const error = worded(plain(429, "too many requests", header)); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe( + `Weaviate rate-limited the request; ${wait}. It was not sent again. (Weaviate: too many requests)`, + ); + }); + + test("a 503 is a connection error naming the endpoint", () => { + const error = worded(plain(503, "not ready")); + expect(error).toBeInstanceOf(ConnectionError); + expect(error.message).toBe("Weaviate is not ready to serve the request (HTTP 503). (Weaviate: not ready)"); + expect((error as ConnectionError).host).toBe("weaviate.test"); + expect((error as ConnectionError).port).toBe(8080); + }); + + test("a server text longer than 2,000 characters is cut, and says so", () => { + expect(worded(handler(500, "x".repeat(2500))).message).toBe( + `Weaviate failed to run the request (HTTP 500). (Weaviate: ${"x".repeat(2000)} (cut))`, + ); + expect(worded(handler(500, "x".repeat(2000))).message).toBe( + `Weaviate failed to run the request (HTTP 500). (Weaviate: ${"x".repeat(2000)})`, + ); + }); +}); + +describe("an echoed secret is withheld whole wherever a server's words reach a sentence", () => { + const echo = (secret: string) => + [ + plain(401, JSON.stringify({ code: 401, message: `unauthorized: invalid api key ${secret}` })), + handler(403, `${RBAC} for key ${secret}`), + router(404, `path /v1/${secret} was not found`), + handler(404, `tenant not found: ${secret}`), + handler(422, `${TENANT_COLD} ${secret}`), + handler(422, `${REST_FLAG} ${secret}`), + handler(422, `${GRAPHQL_OFF} ${secret}`), + handler(400, `${LIMIT} ${secret}`), + handler(400, `invalid ${secret}`), + plain(429, `slow down ${secret}`, "3"), + handler(500, `failure ${secret}`), + plain(503, `not ready ${secret}`), + plain(418, `teapot ${secret}`), + ] as const; + + test.each([ + ...echo(TEST_PASSWORD).map((answer) => [TEST_PASSWORD, answer] as const), + ...echo(Buffer.from(TEST_PASSWORD).toString("base64")).map((answer) => ["its base64", answer] as const), + ])("an answer echoing %s: %j", (_form, answer) => { + const message = worded(answer).message; + expect(message).toContain(`(Weaviate: ${WITHHELD})`); + for (const form of CONTEXT.secretForms) expect(message).not.toContain(form); + }); + + test("a GraphQL error echoing the secret is withheld too", () => { + const failure = graphqlFailure(graphql(`${TENANT_COLD} ${TEST_PASSWORD}`)) as WeaviateError; + expect(toProviderError(failure, CONTEXT).message).toBe( + `The tenant is not active, and Studio does not activate a tenant by reading it. (Weaviate: ${WITHHELD})`, + ); + }); + + test("with no secret configured, the words are shown", () => { + expect(worded(WRONG_KEY, { ...CONTEXT, secretForms: [] }).message).toContain( + "(Weaviate: unauthorized: invalid api key)", + ); + }); +}); + +describe("toProviderError: a request that never completed", () => { + const transport = (kind: TransportError["kind"], message: string, context = CONTEXT) => + toProviderError(new TransportError(kind, message), context); + + test("a deadline is a timeout naming the limit", () => { + const error = transport("timeout", "The request did not finish within its time limit"); + expect(error).toBeInstanceOf(TimeoutError); + expect(error.message).toBe("The request to Weaviate did not finish within 30000 ms, so Studio stopped waiting."); + expect((error as TimeoutError).timeout).toBe(30_000); + }); + + test("a connect that never completed is a connection error in the transport's words", () => { + const sentence = + "No answer from weaviate.test:8080 after 10 seconds: check the address, the port and the network path."; + const error = transport("unreachable", sentence); + expect(error).toBeInstanceOf(ConnectionError); + expect(error).not.toBeInstanceOf(TimeoutError); + expect(error.message).toBe(sentence); + expect((error as ConnectionError).host).toBe("weaviate.test"); + }); + + test("a cancel is a cancellation", () => { + const error = transport("aborted", "The request was cancelled"); + expect(error).toBeInstanceOf(QueryCancelledError); + expect(error.message).toBe("The request to Weaviate was cancelled."); + }); + + test.each([ + [16 * 1024 * 1024, "16 MiB"], + [3 * 1024, "3 KiB"], + [1500, "1,500 bytes"], + ] as const)("an answer past a %d-byte cap names the cap as %s", (responseCapBytes, cap) => { + const error = transport("too-large", "The response exceeded its byte cap", { ...CONTEXT, responseCapBytes }); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe( + `Weaviate's answer is larger than the ${cap} Studio reads for one response, so it was not read. Ask for fewer objects, fewer properties, or no vectors.`, + ); + }); + + test("a redirect and an encoding are connection errors, and the transport's words pass the secret check", () => { + const redirect = transport("redirect", "The server answered 302 to https://weaviate.test/login"); + expect(redirect).toBeInstanceOf(ConnectionError); + expect(redirect.message).toBe( + "Weaviate at weaviate.test:8080 answered with a redirect, which Studio never follows. The server answered 302 to https://weaviate.test/login", + ); + expect(transport("redirect", `Location: /login?key=${TEST_PASSWORD}`).message).toBe( + `Weaviate at weaviate.test:8080 answered with a redirect, which Studio never follows. ${WITHHELD}`, + ); + const encoding = transport("encoding", "Unsupported content-encoding br"); + expect(encoding).toBeInstanceOf(ConnectionError); + expect(encoding.message).toBe( + "Weaviate at weaviate.test:8080 answered in an encoding Studio does not read. Unsupported content-encoding br", + ); + expect(transport("encoding", `charset ${TEST_PASSWORD}`).message).toContain(WITHHELD); + }); + + test("a TLS failure and a lost answer are connection errors naming the endpoint", () => { + const tls = transport("tls", "self-signed certificate in certificate chain"); + expect(tls).toBeInstanceOf(ConnectionError); + expect(tls.message).toBe( + "The TLS connection to Weaviate at weaviate.test:8080 failed: check the SSL mode, the CA and the client certificate under SSL / TLS. self-signed certificate in certificate chain", + ); + const network = transport("network", "The request failed before a complete response arrived (ECONNRESET)"); + expect(network).toBeInstanceOf(ConnectionError); + expect(network.message).toBe( + "No complete answer arrived from Weaviate at weaviate.test:8080, and the request was not sent again. The request failed before a complete response arrived (ECONNRESET)", + ); + expect((network as ConnectionError).port).toBe(8080); + }); + + test("a repository error raised before the wire is returned as it is", () => { + const refusal = new QueryError("The request names an operation this client does not send.", "weaviate"); + expect(toProviderError(refusal, CONTEXT)).toBe(refusal); + const config = new DatabaseConfigError("Invalid host", "weaviate"); + expect(toProviderError(config, CONTEXT)).toBe(config); + }); + + test("anything else is reported without its text", () => { + for (const thrown of [new Error(`boom ${TEST_PASSWORD}`), new TypeError("x is undefined"), "a string", null]) { + const error = toProviderError(thrown, CONTEXT); + expect(error).toBeInstanceOf(QueryError); + expect(error.message).toBe("The request to Weaviate failed in a way Studio does not recognise."); + } + }); +}); + +describe("expectOk: the answer when it is a success, else its failure worded", () => { + test("a success is returned as it is", () => { + const answer = plain(200, '{"version":"1.40.2"}'); + expect(expectOk(answer, { ...CONTEXT, op: "meta" })).toBe(answer); + }); + + test("a REST operation reads the status alone, so a 200 holding an errors field is a success", () => { + const answer = graphql(TENANT_COLD); + expect(expectOk(answer, CONTEXT)).toBe(answer); + }); + + test("the graphql operation reads the errors of a 200", () => { + expect(() => expectOk(graphql(TENANT_COLD), { ...CONTEXT, op: "graphql" })).toThrow( + `The tenant is not active, and Studio does not activate a tenant by reading it. (Weaviate: ${TENANT_COLD})`, + ); + const answer = plain(200, JSON.stringify({ data: { Get: { Article: [] } } })); + expect(expectOk(answer, { ...CONTEXT, op: "graphql" })).toBe(answer); + }); + + test("a failure throws its worded error", () => { + let thrown: unknown; + try { + expectOk(NO_KEY, { ...CONTEXT, phase: "connect", op: "meta" }); + } catch (error) { + thrown = error; + } + expect(thrown).toBeInstanceOf(AuthenticationError); + expect((thrown as Error).message).toStartWith("Weaviate refused the API key or token."); + }); +}); diff --git a/tests/unit/db/weaviate/execute.test.ts b/tests/unit/db/weaviate/execute.test.ts new file mode 100644 index 0000000000..29bd56d4cd --- /dev/null +++ b/tests/unit/db/weaviate/execute.test.ts @@ -0,0 +1,601 @@ +/** + * One Weaviate console request run end to end over a recording send (#1566 spec 3.3, 3.4, 5.7, 5.8, W6): the + * collection read first, the tenant's own record before anything that names a tenant and a refusal unless it is HOT, + * the path the version decides with the one fallback when a path is switched off, the path remembered for the + * session, one permit for the whole request, one deadline fixed before the queue, and a cancel by `queryId`. + */ +import { describe, expect, test } from "bun:test"; +import { RequestRefusal } from "@/lib/db/console/dialect"; +import { ConnectionError, QueryCancelledError, QueryError, TimeoutError } from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import type { WeaviateAnswer, WeaviateRequest } from "@/lib/db/providers/vector/weaviate/client"; +import { + executeWeaviate, + type WeaviateExecution, + type WeaviateFailure, + type WeaviatePathState, + weaviateDeadlineMs, +} from "@/lib/db/providers/vector/weaviate/execute"; +import type { WeaviatePath, WeaviatePathKind } from "@/lib/db/providers/vector/weaviate/versions"; +import { + createRunRegistry, + DuplicateRunError, + engineLimiter, + LimiterFullError, + type ProviderLimiter, +} from "@/lib/db/utils/bounded-limiter"; +import { expectCalls, type LoggedCall } from "../../../helpers/call-log"; +import { + type Answering, + capturedServer, + GRAPHQL_DISABLED, + hanging, + json, + overriding, + REST_SEARCH_DISABLED, + rejection, + routeAbsent, + version, +} from "../../../helpers/weaviate-surface"; + +let keys = 0; +const freshLimiter = (perProvider = 4) => { + keys += 1; + return engineLimiter(`weaviate-execute-test-${keys}`, { perProvider, perEngine: 16, queueDepth: 64 })(); +}; + +const REST = capturedServer("weaviate/searches.json"); +const GRAPHQL = capturedServer("weaviate-1-38/searches.json"); +const READS = capturedServer("weaviate/reads.json"); + +/** A 1.40 server for REST searches and a 1.38 one for GraphQL, the two answering the same seeded data. */ +const BOTH: Answering = (request) => (request.op === "graphql" ? GRAPHQL(request) : REST(request)); + +function memory(initial: Partial> = {}): WeaviatePathState & { + readonly known: Map; +} { + const known = new Map(Object.entries(initial) as [WeaviatePathKind, WeaviatePath][]); + return { known, get: (kind) => known.get(kind), set: (kind, path) => void known.set(kind, path) }; +} + +interface Recording { + readonly calls: LoggedCall[]; + readonly failures: WeaviateFailure[]; + readonly run: WeaviateExecution; + readonly paths: ReturnType; + inFlight: number; + maxInFlight: number; +} + +function recording(answering: Answering, overrides: Partial = {}): Recording { + const paths = memory(); + const record: Recording = { + calls: [], + failures: [], + paths, + inFlight: 0, + maxInFlight: 0, + run: undefined as unknown as WeaviateExecution, + }; + const send = async (request: WeaviateRequest, signal: AbortSignal): Promise => { + record.calls.push({ method: request.op, args: [request] }); + record.inFlight += 1; + record.maxInFlight = Math.max(record.maxInFlight, record.inFlight); + try { + return await answering(request, signal); + } finally { + record.inFlight -= 1; + } + }; + (record as { run: WeaviateExecution }).run = { + send, + limiter: freshLimiter(), + runs: createRunRegistry(), + version: version("1.40.2"), + paths, + fail: (failure) => { + record.failures.push(failure); + return new QueryError( + failure.kind === "answer" ? `answer ${failure.answer.status} to ${failure.op}` : `thrown by ${failure.op}`, + ); + }, + now: () => 0, + deadline: () => new AbortController().signal, + ...overrides, + }; + return record; +} + +const sent = (record: Recording, index: number): WeaviateRequest => + record.calls.at(index)?.args?.[0] as WeaviateRequest; +const ops = (record: Recording) => record.calls.map((call) => call.method); + +const BM25 = + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 3, "returnProperties": ["title", "wordCount"], "returnMetadata": ["score"]}'; +const BM25_REST = '{"query":"vector","limit":3,"returnProperties":["title","wordCount"],"returnMetadata":["score"]}'; +const BM25_GRAPHQL = JSON.stringify({ + query: '{Get{Article(bm25:{query:"vector"},limit:3){title wordCount _additional{id score}}}}', +}); +const VECTOR = "[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7]"; +const NEAR_VECTOR = `POST /v1/search/Article/near-vector {"vector": ${VECTOR}, "limit": 2, "returnProperties": ["title"], "returnMetadata": ["distance"]}`; +const COLLECTION_READ = { op: "collection", params: { collection: "Article" }, query: {} }; + +describe("the deadline", () => { + test("10 s for a metadata route and 30 s for a read, a search or an aggregate", () => { + for (const op of [ + "meta", + "schema", + "collection", + "shards", + "tenants", + "tenant", + "aliases", + "alias", + "nodes", + ] as const) + expect(weaviateDeadlineMs(op, undefined), op).toBe(10_000); + expect(weaviateDeadlineMs("collection_nodes", undefined)).toBe(10_000); + for (const op of ["objects", "object", "search_bm25", "search_near_vector", "aggregate"] as const) + expect(weaviateDeadlineMs(op, undefined), op).toBe(30_000); + }); + + test("at most the connection's query timeout; a missing or non-positive timeout bounds nothing", () => { + expect(weaviateDeadlineMs("search_bm25", 5_000)).toBe(5_000); + expect(weaviateDeadlineMs("meta", 60_000)).toBe(10_000); + expect(weaviateDeadlineMs("search_bm25", 0)).toBe(30_000); + expect(weaviateDeadlineMs("search_bm25", -1)).toBe(30_000); + }); + + test("the deadline is asked for once, before the queue, with the route's bound", async () => { + const asked: number[] = []; + const record = recording(READS, { + queryTimeoutMs: 20_000, + deadline: (ms) => { + asked.push(ms); + return new AbortController().signal; + }, + }); + await executeWeaviate("GET /v1/objects?class=Article&limit=3", undefined, record.run); + await executeWeaviate("GET /v1/meta", undefined, record.run); + expect(asked).toEqual([20_000, 10_000]); + }); + + test("without an injected deadline the run still answers, on its own timer", async () => { + const record = recording(READS, { deadline: undefined, now: undefined }); + const result = await executeWeaviate("GET /v1/meta", undefined, record.run); + expect(result.rowCount).toBe(1); + expect(result.executionTime).toBeGreaterThanOrEqual(0); + }); +}); + +describe("the calls a request makes", () => { + test("a route that names no collection is one call, and its answer is the result", async () => { + const record = recording(READS, { + now: (() => { + let tick = 0; + return () => (tick += 7); + })(), + }); + const result = await executeWeaviate("GET /v1/meta", undefined, record.run); + expectCalls(record.calls, [{ method: "meta", args: [{ op: "meta", params: {}, query: {} }] }]); + expect(result.fields).toContain("version"); + expect(result.rows[0]?.version).toBe("1.40.2"); + expect(result.executionTime).toBe(7); + }); + + test("GET /v1/schema/{collection} is its own definition read, sent once", async () => { + const record = recording(READS); + const result = await executeWeaviate("GET /v1/schema/Article", undefined, record.run); + expectCalls(record.calls, [{ method: "collection", args: [COLLECTION_READ] }]); + expect(result.rows[0]?.class).toBe("Article"); + expect(result.warnings).toBeUndefined(); + }); + + test("a route that reads a collection reads its definition first, then itself", async () => { + const record = recording(READS); + const result = await executeWeaviate("GET /v1/schema/Article/shards", undefined, record.run); + expectCalls(record.calls, [ + { method: "collection", args: [COLLECTION_READ] }, + { method: "shards", args: [{ op: "shards", params: { collection: "Article" }, query: {} }] }, + ]); + expect(result.rows[0]?.status).toBe("READY"); + }); + + test("an object list sends its query with no path parameter, the defaults written in", async () => { + const record = recording(READS); + await executeWeaviate("GET /v1/objects?class=Empty", undefined, record.run); + expect(sent(record, 1)).toEqual({ op: "objects", params: {}, query: { class: "Empty", limit: "25" } }); + }); + + test("a failed definition read is the request's failure, and nothing more is sent", async () => { + const record = recording(READS); + const error = await rejection(executeWeaviate("GET /v1/objects?class=Missing&limit=2", undefined, record.run)); + expect((error as Error).message).toBe("answer 404 to collection"); + expect(record.failures).toEqual([ + { kind: "answer", op: "collection", answer: expect.objectContaining({ status: 404 }) }, + ]); + expectCalls(record.calls, ["collection"]); + }); + + test("a phase 0 refusal makes no call", async () => { + const record = recording(READS); + const error = await rejection( + executeWeaviate('POST /v1/search/Article/hybrid {"query": "x", "alpha": 0.5}', undefined, record.run), + ); + expect(error).toBeInstanceOf(RequestRefusal); + expect((error as RequestRefusal).phase).toBe(0); + expectCalls(record.calls, []); + }); + + test("a phase 1 refusal holds exactly the definition read", async () => { + const record = recording(READS); + const error = await rejection(executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2", undefined, record.run)); + expect(error).toBeInstanceOf(RequestRefusal); + expect((error as RequestRefusal).phase).toBe(1); + expectCalls(record.calls, ["collection"]); + }); +}); + +describe("the tenant guard", () => { + const TENANT_READ = (tenant: string) => ({ + op: "tenant", + params: { collection: "TenantNotes", tenant }, + query: {}, + }); + + test("a HOT tenant is looked up by its own record, then read", async () => { + const record = recording(READS); + const result = await executeWeaviate( + "GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", + undefined, + record.run, + ); + expectCalls(record.calls, [ + "collection", + { method: "tenant", args: [TENANT_READ("acme")] }, + { + method: "objects", + args: [{ op: "objects", params: {}, query: { class: "TenantNotes", limit: "2", tenant: "acme" } }], + }, + ]); + expect(result.rowCount).toBe(2); + }); + + test("ACTIVE, HOT's older name, is read too", async () => { + const record = recording(overriding(READS, { tenant: () => json({ name: "acme", activityStatus: "ACTIVE" }) })); + await executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", undefined, record.run); + expect(ops(record)).toEqual(["collection", "tenant", "objects"]); + }); + + test("a COLD tenant is refused after its record, naming its status, and nothing names it again", async () => { + const record = recording(READS); + const error = await rejection( + executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2&tenant=initech", undefined, record.run), + ); + expect(error).toBeInstanceOf(RequestRefusal); + expect((error as RequestRefusal).phase).toBe(1); + expect((error as RequestRefusal).key).toBe("tenant"); + expect((error as Error).message).toBe( + 'The tenant "initech" is COLD. Studio does not activate a tenant by reading it, so nothing was read: set the tenant HOT on the server first.', + ); + expectCalls(record.calls, ["collection", { method: "tenant", args: [TENANT_READ("initech")] }]); + }); + + test("a tenant named in a search body is guarded the same way", async () => { + const record = recording(overriding(BOTH, { tenant: () => json({ name: "acme", activityStatus: "FROZEN" }) })); + const error = await rejection( + executeWeaviate('POST /v1/search/TenantNotes/bm25 {"query": "note", "tenant": "acme"}', undefined, record.run), + ); + expect((error as Error).message).toStartWith('The tenant "acme" is FROZEN.'); + expect(ops(record)).toEqual(["collection", "tenant"]); + }); + + test("a record that is not JSON, or names no status, reads as UNKNOWN and is refused", async () => { + for (const text of ["not json", '{"name":"acme"}', "null"]) { + const record = recording(overriding(READS, { tenant: () => ({ ...json({}), text }) })); + // oxlint-disable-next-line no-await-in-loop -- each case has its own log. + const error = await rejection( + executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2&tenant=acme", undefined, record.run), + ); + expect((error as Error).message, text).toStartWith('The tenant "acme" is UNKNOWN.'); + expect(ops(record)).toEqual(["collection", "tenant"]); + } + }); + + test("the tenant route reads its record once, as the answer, with no guard read before it", async () => { + const record = recording(READS); + const result = await executeWeaviate("GET /v1/schema/TenantNotes/tenants/initech", undefined, record.run); + expectCalls(record.calls, ["collection", { method: "tenant", args: [TENANT_READ("initech")] }]); + expect(result.rows[0]?.activityStatus).toBe("COLD"); + }); + + test("an unknown tenant's 404 is the request's failure", async () => { + const record = recording(overriding(READS, { tenant: () => json("", 404) })); + const error = await rejection( + executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2&tenant=nobody", undefined, record.run), + ); + expect((error as Error).message).toBe("answer 404 to tenant"); + expect(ops(record)).toEqual(["collection", "tenant"]); + }); +}); + +describe("the path the version decides", () => { + const pathOf = async (serverVersion: string, text: string) => { + const record = recording(BOTH, { version: version(serverVersion) }); + const result = await executeWeaviate(text, undefined, record.run); + return { record, result, op: sent(record, 1).op }; + }; + + test("1.40.2 sends bm25 and near-vector over REST", async () => { + const bm25 = await pathOf("1.40.2", BM25); + expect(sent(bm25.record, 1)).toEqual({ + op: "search_bm25", + params: { collection: "Article" }, + query: {}, + body: BM25_REST, + }); + expect(bm25.result.warnings).toEqual([{ message: "Answered via REST search." }]); + expect((await pathOf("1.40.2", NEAR_VECTOR)).op).toBe("search_near_vector"); + }); + + test("1.39.7 sends bm25 over REST and near-vector over GraphQL; 1.39.8 sends both over REST", async () => { + expect((await pathOf("1.39.7", BM25)).op).toBe("search_bm25"); + expect((await pathOf("1.39.7", NEAR_VECTOR)).op).toBe("graphql"); + expect((await pathOf("1.39.8", NEAR_VECTOR)).op).toBe("search_near_vector"); + }); + + test("below 1.39.7, and on a version that cannot be read, a search goes over GraphQL", async () => { + for (const serverVersion of ["1.39.6", "1.38.22", "1.37.4", "1.41.0-rc.1", "weaviate"]) { + // oxlint-disable-next-line no-await-in-loop -- each version has its own log. + const { record, result } = await pathOf(serverVersion, BM25); + expect(sent(record, 1), serverVersion).toEqual({ op: "graphql", params: {}, query: {}, body: BM25_GRAPHQL }); + expect(result.warnings).toEqual([{ message: "Answered via GraphQL." }]); + } + }); + + test("both paths answer the same rows", async () => { + const rest = await pathOf("1.40.2", NEAR_VECTOR); + const graphql = await pathOf("1.38.22", NEAR_VECTOR); + expect(graphql.result.fields).toEqual(rest.result.fields); + expect(graphql.result.rows.map((row) => row.$id)).toEqual(rest.result.rows.map((row) => row.$id)); + }); + + test("the path that answered is remembered per kind, and the next search goes straight to it", async () => { + const record = recording(BOTH, { version: version("1.39.7") }); + await executeWeaviate(BM25, undefined, record.run); + await executeWeaviate(NEAR_VECTOR, undefined, record.run); + expect([...record.paths.known]).toEqual([ + ["other", "rest"], + ["near-vector", "graphql"], + ]); + const remembered = recording(BOTH, { version: version("1.40.2"), paths: memory({ other: "graphql" }) }); + await executeWeaviate(BM25, undefined, remembered.run); + expect(ops(remembered)).toEqual(["collection", "graphql"]); + }); +}); + +describe("the one fallback", () => { + test("GraphQL disabled on 1.39.0 to 1.39.6: the search is sent once more over REST, and REST is remembered", async () => { + const record = recording(overriding(BOTH, { graphql: () => GRAPHQL_DISABLED }), { version: version("1.39.6") }); + const result = await executeWeaviate(BM25, undefined, record.run); + expect(ops(record)).toEqual(["collection", "graphql", "search_bm25"]); + expect(result.warnings).toEqual([{ message: "Answered via REST search." }]); + expect(record.paths.get("other")).toBe("rest"); + const next = recording(BOTH, { version: version("1.39.6"), paths: record.paths }); + await executeWeaviate(BM25, undefined, next.run); + expect(ops(next)).toEqual(["collection", "search_bm25"]); + }); + + test("a server that has neither path is refused with one sentence naming its version", async () => { + const cases: [string, WeaviateAnswer][] = [ + ["1.39.0", routeAbsent("/v1/search/Article/bm25")], + ["1.39.6", REST_SEARCH_DISABLED], + ]; + for (const [serverVersion, restAnswer] of cases) { + const record = recording(overriding(BOTH, { graphql: () => GRAPHQL_DISABLED, search_bm25: () => restAnswer }), { + version: version(serverVersion), + }); + // oxlint-disable-next-line no-await-in-loop -- each server has its own log. + const error = await rejection(executeWeaviate(BM25, undefined, record.run)); + expect(error).toBeInstanceOf(RequestRefusal); + expect((error as RequestRefusal).phase).toBe(1); + expect((error as Error).message).toBe( + `This Weaviate server (${serverVersion}) serves this search neither over REST search, which it lacks or keeps behind EXPERIMENTAL_REST_SEARCH_ENABLED, nor over GraphQL, which it has disabled. Browsing the collections still works.`, + ); + expect(ops(record)).toEqual(["collection", "graphql", "search_bm25"]); + expect(record.paths.known.size).toBe(0); + } + }); + + test("a REST route the server lacks falls back to GraphQL", async () => { + const record = recording(overriding(BOTH, { search_bm25: () => routeAbsent("/v1/search/Article/bm25") }), { + version: version("1.40.2"), + }); + const result = await executeWeaviate(BM25, undefined, record.run); + expect(ops(record)).toEqual(["collection", "search_bm25", "graphql"]); + expect(result.warnings).toEqual([{ message: "Answered via GraphQL." }]); + expect(record.paths.get("other")).toBe("graphql"); + }); + + test("a fallback that fails otherwise is that path's failure", async () => { + const record = recording( + overriding(BOTH, { + graphql: () => GRAPHQL_DISABLED, + search_bm25: () => json({ error: [{ message: "bad" }] }, 500), + }), + { version: version("1.38.22") }, + ); + expect(((await rejection(executeWeaviate(BM25, undefined, record.run))) as Error).message).toBe( + "answer 500 to search_bm25", + ); + }); + + test("any other failure is not a fallback: one call, worded by its path", async () => { + const rest = recording(overriding(BOTH, { search_bm25: () => json({ error: [{ message: "bad" }] }, 422) })); + expect(((await rejection(executeWeaviate(BM25, undefined, rest.run))) as Error).message).toBe( + "answer 422 to search_bm25", + ); + expect(ops(rest)).toEqual(["collection", "search_bm25"]); + const graphqlErrors = json({ errors: [{ message: "Cannot query field" }] }); + const graphql = recording(overriding(BOTH, { graphql: () => graphqlErrors }), { version: version("1.38.22") }); + expect(((await rejection(executeWeaviate(BM25, undefined, graphql.run))) as Error).message).toBe( + "answer 200 to graphql", + ); + expect(graphql.failures).toEqual([{ kind: "answer", op: "graphql", answer: graphqlErrors }]); + expect(ops(graphql)).toEqual(["collection", "graphql"]); + expect(graphql.paths.known.size).toBe(0); + }); +}); + +describe("one permit, one deadline, one cancel", () => { + test("a request holds one permit for all its calls: a second request waits for the first to end", async () => { + const limiter = freshLimiter(1); + const order: string[] = []; + const answering: Answering = async (request) => { + order.push(`start ${request.op}`); + await Bun.sleep(1); + order.push(`end ${request.op}`); + return REST(request); + }; + const first = recording(answering, { limiter }); + const second = recording(answering, { limiter }); + await Promise.all([ + executeWeaviate(BM25, undefined, first.run), + executeWeaviate("GET /v1/schema/Article", undefined, second.run), + ]); + expect(order).toEqual([ + "start collection", + "end collection", + "start search_bm25", + "end search_bm25", + "start collection", + "end collection", + ]); + }); + + test("a cancel by queryId aborts the running call with QueryCancelledError and frees the run", async () => { + const record = recording(overriding(BOTH, { search_bm25: hanging })); + const running = executeWeaviate(BM25, "q-1", record.run); + await Bun.sleep(1); + expect(record.run.runs.cancel("q-1")).toBe(true); + const error = await rejection(running); + expect(error).toBeInstanceOf(QueryCancelledError); + expect(record.failures).toEqual([]); + expect(record.run.runs.runsInFlight()).toBe(0); + expect(record.run.runs.cancel("q-1")).toBe(false); + }); + + test("a queryId already running is refused before anything is sent", async () => { + const record = recording(overriding(BOTH, { search_bm25: hanging })); + const running = executeWeaviate(BM25, "q-2", record.run); + expect(await rejection(executeWeaviate("GET /v1/meta", "q-2", record.run))).toBeInstanceOf(DuplicateRunError); + record.run.runs.cancel("q-2"); + await rejection(running); + expect(ops(record)).toEqual(["collection", "search_bm25"]); + }); + + test("the deadline aborts the running call as a TimeoutError naming its seconds", async () => { + const deadline = new AbortController(); + const record = recording(overriding(READS, { objects: hanging }), { deadline: () => deadline.signal }); + const running = executeWeaviate("GET /v1/objects?class=Article&limit=3", undefined, record.run); + await Bun.sleep(1); + deadline.abort(new DOMException("timed out", "TimeoutError")); + const error = await rejection(running); + expect(error).toBeInstanceOf(TimeoutError); + expect((error as Error).message).toBe("The request did not finish within its 30 s deadline."); + expect(record.failures).toEqual([]); + }); + + test("the deadline also bounds the queue: a request that never got its permit times out", async () => { + const deadline = new AbortController(); + const queued: ProviderLimiter = { + acquire: (signal) => + new Promise((_resolve, reject) => { + signal.addEventListener("abort", () => reject(signal.reason), { once: true }); + }), + }; + const record = recording(READS, { limiter: queued, deadline: () => deadline.signal, queryTimeoutMs: 4_000 }); + const running = executeWeaviate("GET /v1/meta", undefined, record.run); + deadline.abort(new DOMException("timed out", "TimeoutError")); + const error = await rejection(running); + expect((error as Error).message).toBe("The request did not finish within its 4 s deadline."); + expectCalls(record.calls, []); + }); + + test("a cancel while queued is a QueryCancelledError, and nothing is sent", async () => { + const queued: ProviderLimiter = { + acquire: (signal) => + new Promise((_resolve, reject) => { + signal.addEventListener("abort", () => reject(signal.reason), { once: true }); + }), + }; + const record = recording(READS, { limiter: queued }); + const running = executeWeaviate("GET /v1/meta", "q-3", record.run); + record.run.runs.cancel("q-3"); + expect(await rejection(running)).toBeInstanceOf(QueryCancelledError); + expectCalls(record.calls, []); + }); + + test("a full queue is refused as the limiter words it, and nothing is sent", async () => { + const full = new LimiterFullError("The queue is full."); + const record = recording(READS, { limiter: { acquire: () => Promise.reject(full) } }); + expect(await rejection(executeWeaviate("GET /v1/meta", undefined, record.run))).toBe(full); + expectCalls(record.calls, []); + expect(record.run.runs.runsInFlight()).toBe(0); + }); + + test("a transport failure is handed to errors.ts as thrown, with the operation that met it", async () => { + const refused = new TransportError("network", "socket hang up"); + const record = recording(overriding(READS, { meta: () => Promise.reject(refused) })); + expect(((await rejection(executeWeaviate("GET /v1/meta", undefined, record.run))) as Error).message).toBe( + "thrown by meta", + ); + expect(record.failures).toEqual([{ kind: "thrown", op: "meta", error: refused }]); + }); + + test("an unreachable endpoint is worded as such even when the deadline has passed", async () => { + const deadline = new AbortController(); + const unreachable = new TransportError("unreachable", "Weaviate at 127.0.0.1:8080 did not answer within 10 s."); + const record = recording( + overriding(READS, { + meta: () => { + deadline.abort(); + return Promise.reject(unreachable); + }, + }), + { + deadline: () => deadline.signal, + fail: (failure) => new ConnectionError((failure as { error: Error }).error.message, "weaviate"), + }, + ); + const error = await rejection(executeWeaviate("GET /v1/meta", undefined, record.run)); + expect(error).toBeInstanceOf(ConnectionError); + expect((error as Error).message).toBe("Weaviate at 127.0.0.1:8080 did not answer within 10 s."); + }); + + test("the permit is released and the run ended on every outcome", async () => { + const limiter = freshLimiter(1); + const failing = recording(overriding(READS, { meta: () => json({}, 500) }), { limiter }); + await rejection(executeWeaviate("GET /v1/meta", undefined, failing.run)); + const refused = recording(READS, { limiter, runs: failing.run.runs }); + await rejection( + executeWeaviate("GET /v1/objects?class=TenantNotes&limit=2&tenant=initech", undefined, refused.run), + ); + const after = recording(READS, { limiter, runs: failing.run.runs }); + expect((await executeWeaviate("GET /v1/meta", undefined, after.run)).rowCount).toBe(1); + expect(failing.run.runs.runsInFlight()).toBe(0); + }); +}); + +describe("the aggregate", () => { + test("a body-less aggregate is sent as {} over REST and as a meta count over GraphQL", async () => { + const rest = recording(BOTH); + const restResult = await executeWeaviate("POST /v1/aggregate/Article", undefined, rest.run); + expect(sent(rest, 1)).toEqual({ op: "aggregate", params: { collection: "Article" }, query: {}, body: "{}" }); + expect(restResult.rows).toEqual([Object.assign(Object.create(null), { count: 500 })]); + const graphql = recording(BOTH, { version: version("1.37.4") }); + const graphqlResult = await executeWeaviate("POST /v1/aggregate/Article", undefined, graphql.run); + expect(sent(graphql, 1).body).toBe(JSON.stringify({ query: "{Aggregate{Article{meta{count}}}}" })); + expect(graphqlResult.rows).toEqual(restResult.rows); + }); +}); diff --git a/tests/unit/db/weaviate/generators.test.ts b/tests/unit/db/weaviate/generators.test.ts new file mode 100644 index 0000000000..2295822ae4 --- /dev/null +++ b/tests/unit/db/weaviate/generators.test.ts @@ -0,0 +1,127 @@ +/** + * The tree click and Generate Request for a Weaviate collection (#1566 spec 6.4): each text round-tripped through + * phase 0, the probe vector accepted by the shared dense check for its dimension, and a collection name kept in its + * place through the request line's percent-encoding. + */ +import { describe, expect, test } from "bun:test"; +import { toJsonText } from "@/lib/db/console/tagged-json"; +import { weaviateSelectQuery, weaviateTableQuery } from "@/lib/db/providers/vector/weaviate/generators"; +import { readWeaviateClass, weaviateColumns } from "@/lib/db/providers/vector/weaviate/schema"; +import { checkDenseElements, vectorNumbers } from "@/lib/db/vector/dense"; +import type { ColumnSchema } from "@/lib/types"; +import { plan } from "../../../helpers/weaviate-request-fixtures"; + +const vectorColumn = (name: string, type: string): ColumnSchema => ({ name, type, nullable: true, isPrimary: false }); +const TITLE: ColumnSchema = { name: "title", type: "text", nullable: true, isPrimary: false }; + +/** Product's columns as the provider builds them: two named vectors, each dimension read from one object. */ +const PRODUCT_COLUMNS = weaviateColumns( + readWeaviateClass( + { + class: "Product", + properties: [{ name: "name", dataType: ["text"] }], + vectorConfig: { + image: { vectorIndexType: "hnsw", vectorIndexConfig: { distance: "cosine" } }, + text: { vectorIndexType: "flat", vectorIndexConfig: { distance: "dot", bq: { enabled: true } } }, + }, + }, + "Product", + ), + new Map([ + ["image", 8], + ["text", 4], + ]), +); + +describe("weaviateTableQuery", () => { + test("reads the collection's first 50 objects", () => { + expect(weaviateTableQuery(["Article"])).toBe("GET /v1/objects?class=Article&limit=50"); + expect(plan(weaviateTableQuery(["Article"])).query).toEqual({ class: "Article", limit: "50" }); + }); + + test("names the last segment of the path", () => { + expect(plan(weaviateTableQuery(["weaviate", "Product"])).collection).toBe("Product"); + }); + + test("a name with a character a query string carries is percent-encoded", () => { + expect(weaviateTableQuery(["a&b"])).toBe("GET /v1/objects?class=a%26b&limit=50"); + }); +}); + +describe("weaviateSelectQuery", () => { + test("a collection with named vectors searches the first, with the probe vector of its dimension", () => { + const text = weaviateSelectQuery(["Product"], PRODUCT_COLUMNS); + const lines = text.split("\n"); + expect(lines.slice(0, 5)).toEqual([ + "// Replace vector with your query vector: Vector(8, cosine, hnsw)", + '// Also in this collection: vector "text", Vector(4, dot, flat, bq)', + '// A keyword search: POST /v1/search/Product/bm25 {"query": "your words", "limit": 10}', + "// A count: POST /v1/aggregate/Product {}", + "POST /v1/search/Product/near-vector", + ]); + const search = plan(text).search; + expect(search?.targetVector).toBe("image"); + expect(toJsonText(search?.limit ?? null)).toBe("10"); + expect(search?.returnMetadata).toEqual(["distance"]); + const numbers = vectorNumbers( + { name: "image", kind: "dense", dtype: "float32", dimension: 8 }, + search?.vector ?? [], + ) as number[]; + expect(numbers).toHaveLength(8); + expect(checkDenseElements({ name: "image", kind: "dense", dtype: "float32", dimension: 8 }, numbers)).toBeNull(); + }); + + test("the unnamed vector is searched without targetVector", () => { + const text = weaviateSelectQuery(["Article"], [TITLE, vectorColumn("$vector", "Vector(2, cosine, hnsw)")]); + expect(text.split("\n").at(-1)).toMatch( + /^\{"vector": \[[^\]]+\], "limit": 10, "returnMetadata": \["distance"\]\}$/, + ); + expect(plan(text).search?.targetVector).toBeNull(); + }); + + test("a vector of length 0 reads as a dimension not yet shown, never as a probe of no numbers", () => { + const text = weaviateSelectQuery(["Article"], [vectorColumn("$vector.v", "Vector(0, cosine, hnsw)")]); + expect(text).toContain("no object has shown its length yet"); + expect(plan(text).route.op).toBe("search_bm25"); + }); + + test("with no dimension shown, the keyword search is the request and the vector search waits in a comment", () => { + // A guessed length is a server error ("vector lengths don't match", measured on 1.40.2), so it is never sent. + const text = weaviateSelectQuery(["Article"], [vectorColumn("$vector", "Vector(?, cosine, hnsw)")]); + expect(text).toBe( + [ + "// A vector search needs a query vector of Vector(?, cosine, hnsw); no object has shown its length yet, so a keyword search runs instead:", + '// POST /v1/search/Article/near-vector {"vector": [your numbers], "limit": 10, "returnMetadata": ["distance"]}', + "// A count: POST /v1/aggregate/Article {}", + "POST /v1/search/Article/bm25", + '{"query": "your words", "limit": 10}', + ].join("\n"), + ); + expect(plan(text).route.op).toBe("search_bm25"); + }); + + test("a vector type the generator cannot read is treated as an unknown dimension", () => { + const text = weaviateSelectQuery(["Article"], [vectorColumn("$vector.v", "vector")]); + expect(text).toContain( + '// POST /v1/search/Article/near-vector {"vector": [your numbers], "targetVector": "v", "limit": 10', + ); + expect(plan(text).route.op).toBe("search_bm25"); + }); + + test("a collection that declares no vector opens a bm25 search", () => { + const text = weaviateSelectQuery(["Author"], [TITLE]); + expect(text).toBe( + [ + '// Collection "Author" declares no vector to search.', + "POST /v1/search/Author/bm25", + '{"query": "your words", "limit": 10}', + ].join("\n"), + ); + expect(plan(text).route.op).toBe("search_bm25"); + }); + + test("a vector name reaches the body through JSON.stringify", () => { + const text = weaviateSelectQuery(["Doc"], [vectorColumn("$vector.with_name", "Vector(2, cosine, hnsw)")]); + expect(plan(text).search?.targetVector).toBe("with_name"); + }); +}); diff --git a/tests/unit/db/weaviate/graphql.test.ts b/tests/unit/db/weaviate/graphql.test.ts new file mode 100644 index 0000000000..bf51347b7b --- /dev/null +++ b/tests/unit/db/weaviate/graphql.test.ts @@ -0,0 +1,289 @@ +/** + * The two encoders of one Weaviate search model (#1566 spec 3.1, 5.5, W5): `encodeGraphql` writes the one `Get` or + * `Aggregate` document a server below 1.39.7 is sent, and `encodeRest` the REST body. Each GraphQL document is + * compared with the body the 1.37.4 server answered, and every identifier, string and number goes through the + * builder's checks, never through a user's text as typed. + */ +import { describe, expect, test } from "bun:test"; +import { taggedNumber, type TaggedObject } from "@/lib/db/console/tagged-json"; +import { QueryError } from "@/lib/db/errors"; +import { + encodeGraphql, + encodeRest, + GRAPHQL_METADATA, + graphqlName, + graphqlString, + graphqlWhere, + selectedProperties, +} from "@/lib/db/providers/vector/weaviate/graphql"; +import { type WeaviateSearchModel, weaviatePhase1 } from "@/lib/db/providers/vector/weaviate/request"; +import type { WeaviateCollectionFacts } from "@/lib/db/providers/vector/weaviate/schema"; +import { handFacts, plan, recordedFacts, recordedGraphqlBodies } from "../../../helpers/weaviate-request-fixtures"; + +const FACTS: Readonly> = Object.fromEntries( + ["Article", "Product", "TenantNotes", "EdgeValues", "Empty", "Author"].map((name) => [name, recordedFacts(name)]), +); + +/** The model phase 1 answers for a text, and the facts of its collection. */ +function modelOf(text: string): { model: WeaviateSearchModel; facts: WeaviateCollectionFacts } { + const read = plan(text); + const facts = FACTS[read.collection as string]; + return { model: weaviatePhase1(read, facts).search as WeaviateSearchModel, facts }; +} + +const graphql = (text: string): string => { + const { model, facts } = modelOf(text); + return encodeGraphql(model, facts); +}; +const documentOf = (text: string): string => (JSON.parse(graphql(text)) as { query: string }).query; +const rest = (text: string): string => { + const read = plan(text); + const { model } = modelOf(text); + return encodeRest(read.body as TaggedObject, model); +}; + +const UUID = "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d"; +const VECTOR16 = "[0.1,-0.2,0.3,0.4,-0.5,0.6,0.7,-0.8,0.9,0.1,0.2,-0.3,0.4,0.5,-0.6,0.7]"; + +/** The console texts whose GraphQL documents the 1.37.4 server answered, in the order of the record. */ +const RECORDED: readonly string[] = [ + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 3, "returnProperties": ["title", "wordCount"], "returnMetadata": ["score"]}', + 'POST /v1/search/Article/bm25 {"query": "vector", "where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}, "limit": 2, "returnProperties": ["title", "category"]}', + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 2}', + `POST /v1/search/Article/near-vector {"vector": ${VECTOR16}, "limit": 2, "returnProperties": ["title"], "returnMetadata": ["distance"]}`, + `POST /v1/search/Article/near-object {"id": "${UUID}", "limit": 2, "returnProperties": ["title"], "returnMetadata": ["distance"]}`, + 'POST /v1/search/Article/hybrid {"query": "vector", "alpha": 0, "limit": 2, "returnProperties": ["title"]}', + 'POST /v1/search/Product/near-vector {"vector": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], "targetVector": "image", "limit": 1, "returnProperties": ["name"]}', + 'POST /v1/search/TenantNotes/bm25 {"query": "note", "tenant": "acme", "limit": 2}', + 'POST /v1/search/EdgeValues/bm25 {"query": "9007199254740991", "returnProperties": ["label", "big"]}', + 'POST /v1/search/Product/bm25 {"query": "product", "limit": 2, "returnProperties": ["name"]}', + "POST /v1/aggregate/Article", + 'POST /v1/aggregate/Article {"groupBy": "category"}', + 'POST /v1/aggregate/TenantNotes {"tenant": "acme"}', + "POST /v1/aggregate/Empty", + 'POST /v1/aggregate/Article {"where": {"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}}', + 'POST /v1/aggregate/Article {"where": {"operator": "And", "operands": [{"path": ["published"], "operator": "Equal", "valueBoolean": true}, {"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": 41, "longitude": 29}, "distance": {"max": 3000000}}}]}}', + 'POST /v1/search/Article/bm25 {"query": "vector", "where": {"path": ["tags"], "operator": "ContainsAny", "valueTextArray": ["graph", "shard"]}, "limit": 50, "returnProperties": ["title"]}', + "POST /v1/aggregate/Product", + "POST /v1/aggregate/Author", + "POST /v1/aggregate/EdgeValues", +]; + +describe("encodeGraphql against the record", () => { + test("every recorded document is written byte for byte from its REST search text", () => { + expect(RECORDED.map(graphql)).toEqual([...recordedGraphqlBodies()]); + }); +}); + +describe("encodeGraphql", () => { + test("a hybrid search writes alpha 0, its properties, fusion, distance and target as GraphQL spells them", () => { + const product = + 'POST /v1/search/Product/hybrid {"query": "lamp", "alpha": 0, "queryProperties": ["name^2"], "fusionType": "relativeScore", "maxVectorDistance": 0.25, "targetVector": "text", "limit": 4}'; + expect(documentOf(product)).toBe( + '{Get{Product(hybrid:{query:"lamp",alpha:0,properties:["name^2"],fusionType:relativeScoreFusion,maxVectorDistance:0.25,targetVectors:["text"]},limit:4){name price sku _additional{id}}}}', + ); + expect( + documentOf( + 'POST /v1/search/Product/hybrid {"query": "lamp", "alpha": 0, "fusionType": "ranked", "targetVector": "text"}', + ), + ).toContain("fusionType:rankedFusion"); + }); + + test("bm25 properties, offset, autocut and consistency level are written as arguments", () => { + expect( + documentOf( + 'POST /v1/search/Article/bm25 {"query": "vector", "queryProperties": ["title^2", "body"], "limit": 5, "offset": 3, "autoLimit": 1, "consistencyLevel": "ONE", "returnProperties": ["title"]}', + ), + ).toBe( + '{Get{Article(bm25:{query:"vector",properties:["title^2","body"]},limit:5,offset:3,autocut:1,consistencyLevel:ONE){title _additional{id}}}}', + ); + }); + + test("near-vector and near-object write distance or certainty as typed", () => { + expect(documentOf('POST /v1/search/Article/near-vector {"vector": [1e-3, 2], "certainty": 0.75}')).toBe( + "{Get{Article(nearVector:{vector:[1e-3,2],certainty:0.75},limit:10){title body category tags wordCount rating published publishedAt location{latitude longitude} meta{source revision} _additional{id}}}}", + ); + expect( + documentOf( + `POST /v1/search/Article/near-object {"id": "${UUID}", "distance": 0.5, "returnProperties": ["title"]}`, + ), + ).toBe(`{Get{Article(nearObject:{id:"${UUID}",distance:0.5},limit:10){title _additional{id}}}}`); + }); + + test("every metadata word is written as _additional spells it", () => { + const words = Object.keys(GRAPHQL_METADATA); + expect( + documentOf( + `POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["title"], "returnMetadata": ${JSON.stringify(words)}}`, + ), + ).toBe( + '{Get{Article(bm25:{query:"x"},limit:10){title _additional{id distance certainty score explainScore creationTimeUnix lastUpdateTimeUnix}}}}', + ); + }); + + test("a collection with no selectable property selects _additional alone", () => { + const facts = handFacts({ name: "Linked", properties: [], references: ["owner"] }); + const read = plan('POST /v1/search/Linked/bm25 {"query": "x"}'); + const model = weaviatePhase1(read, facts).search as WeaviateSearchModel; + expect(JSON.parse(encodeGraphql(model, facts)).query).toBe( + '{Get{Linked(bm25:{query:"x"},limit:10){_additional{id}}}}', + ); + }); + + test("an aggregate with a where filter and a group limit", () => { + expect( + documentOf( + 'POST /v1/aggregate/Article {"where": {"path": ["published"], "operator": "Equal", "valueBoolean": true}, "groupBy": "category", "limit": 2}', + ), + ).toBe( + '{Aggregate{Article(where:{path:["published"],operator:Equal,valueBoolean:true},groupBy:["category"],limit:2){meta{count} groupedBy{value path}}}}', + ); + }); + + test("a string is escaped by JSON's rules, so a quote or a brace stays inside it", () => { + expect(documentOf('POST /v1/search/Article/bm25 {"query": "a\\"}){x}\\n", "returnProperties": ["title"]}')).toBe( + '{Get{Article(bm25:{query:"a\\"}){x}\\n"},limit:10){title _additional{id}}}}', + ); + }); + + test("a text that is not well-formed Unicode is refused before anything is sent", () => { + const { model, facts } = modelOf('POST /v1/search/Article/bm25 {"query": "x"}'); + expect(() => encodeGraphql({ ...model, query: "\uD800" }, facts)).toThrow( + new QueryError("A text in the request is not well-formed Unicode, so it cannot be sent over GraphQL."), + ); + }); + + test("an identifier that is no GraphQL name is refused, whatever reached the encoder", () => { + const { model, facts } = modelOf('POST /v1/search/Article/bm25 {"query": "x"}'); + expect(() => encodeGraphql({ ...model, collection: "Article){x" }, facts)).toThrow( + '"Article){x" cannot be written as a GraphQL name, so nothing was sent.', + ); + expect(() => encodeGraphql({ ...model, consistencyLevel: "TWO" }, facts)).toThrow( + '"TWO" is not a word this encoder writes, so nothing was sent.', + ); + }); + + test("a number Studio produced is written as JSON writes it, and anything else that is no number is refused", () => { + const { model, facts } = modelOf('POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["title"]}'); + expect(JSON.parse(encodeGraphql({ ...model, limit: 5 }, facts)).query).toBe( + '{Get{Article(bm25:{query:"x"},limit:5.0){title _additional{id}}}}', + ); + expect(() => encodeGraphql({ ...model, limit: "5" }, facts)).toThrow( + "A number in the request cannot be written as a GraphQL number, so nothing was sent.", + ); + expect(() => encodeGraphql({ ...model, limit: Number.NaN }, facts)).toThrow( + "A number in the request cannot be written as a GraphQL number, so nothing was sent.", + ); + }); +}); + +describe("graphqlWhere", () => { + const whereOf = (where: string): string => + graphqlWhere(plan(`POST /v1/search/Article/bm25 {"query": "x", "where": ${where}}`).search?.where as TaggedObject); + + test("nested operands and a number keep their spelling, and a value list goes under the scalar key", () => { + expect( + whereOf( + '{"operator": "Or", "operands": [{"path": ["tags"], "operator": "ContainsAny", "valueTextArray": ["a", "b"]}, {"path": ["rating"], "operator": "GreaterThan", "valueNumber": 4.50}]}', + ), + ).toBe( + '{operator:Or,operands:[{path:["tags"],operator:ContainsAny,valueText:["a","b"]},{path:["rating"],operator:GreaterThan,valueNumber:4.50}]}', + ); + }); + + test("every valueArray key is written as its scalar key, which is the only spelling GraphQL accepts", () => { + // Measured on 1.37.4, 1.38.22 and 1.40.2: valueTextArray is an "Unknown field", valueText with a list answers + // the count REST answers for valueTextArray. + for (const [key, value, written] of [ + ["valueTextArray", '["a"]', 'valueText:["a"]'], + ["valueStringArray", '["a"]', 'valueString:["a"]'], + ["valueIntArray", "[1, 2]", "valueInt:[1,2]"], + ["valueNumberArray", "[1.5]", "valueNumber:[1.5]"], + ["valueBooleanArray", "[true]", "valueBoolean:[true]"], + ["valueDateArray", '["2026-01-01T00:00:00Z"]', 'valueDate:["2026-01-01T00:00:00Z"]'], + ]) { + expect(whereOf(`{"path": ["tags"], "operator": "ContainsAny", "${key}": ${value}}`)).toBe( + `{path:["tags"],operator:ContainsAny,${written}}`, + ); + } + }); + + test("a geo range is written in a fixed order, whatever order it was typed in", () => { + expect( + whereOf( + '{"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"distance": {"max": 2000}, "geoCoordinates": {"longitude": 2.35, "latitude": 48.85}}}', + ), + ).toBe( + '{path:["location"],operator:WithinGeoRange,valueGeoRange:{geoCoordinates:{latitude:48.85,longitude:2.35},distance:{max:2000}}}', + ); + }); + + test("a null key is left out", () => { + const filter = Object.assign(Object.create(null), { + path: ["title"], + operator: "IsNull", + valueBoolean: false, + valueText: null, + }) as TaggedObject; + expect(graphqlWhere(filter)).toBe('{path:["title"],operator:IsNull,valueBoolean:false}'); + }); + + test("an operator outside Weaviate's words is refused", () => { + const filter = Object.assign(Object.create(null), { + operator: "Equal}){x", + path: ["a"], + valueInt: taggedNumber("1"), + }); + expect(() => graphqlWhere(filter as TaggedObject)).toThrow( + '"Equal}){x" is not a word this encoder writes, so nothing was sent.', + ); + }); +}); + +describe("the builder's pieces", () => { + test("graphqlName takes a GraphQL name only", () => { + expect(graphqlName("_a1")).toBe("_a1"); + expect(() => graphqlName("1a")).toThrow(QueryError); + }); + + test("graphqlString is JSON's escaping", () => { + expect(graphqlString('say "hi"\t')).toBe('"say \\"hi\\"\\t"'); + }); + + test("selectedProperties keeps the properties named that have a selection, in the order named", () => { + const { model, facts } = modelOf( + 'POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["location", "title"]}', + ); + expect(selectedProperties(model, facts)).toEqual([ + { name: "location", fields: [{ name: "latitude" }, { name: "longitude" }] }, + { name: "title" }, + ]); + expect(selectedProperties({ ...model, returnProperties: ["writtenBy"] }, facts)).toEqual([]); + }); +}); + +describe("encodeRest", () => { + test("writes the checked body back, the default limit in it", () => { + expect(rest('POST /v1/search/Article/bm25 {"query": "vector", "limit": 2}')).toBe('{"query":"vector","limit":2}'); + expect(rest('POST /v1/search/Article/bm25 {"query": "vector"}')).toBe('{"query":"vector","limit":10}'); + }); + + test("adds the target vector phase 1 found when the body names none", () => { + const facts = handFacts({ name: "Doc", vectors: ["text"] }); + const read = plan('POST /v1/search/Doc/near-vector {"vector": [0.5], "limit": 1}'); + const model = weaviatePhase1(read, facts).search as WeaviateSearchModel; + expect(encodeRest(read.body as TaggedObject, model)).toBe('{"vector":[0.5],"limit":1,"targetVector":"text"}'); + }); + + test("keeps a target vector the body names, and adds none for the unnamed vector", () => { + expect(rest('POST /v1/search/Product/near-vector {"vector": [0.1], "targetVector": "image", "limit": 1}')).toBe( + '{"vector":[0.1],"targetVector":"image","limit":1}', + ); + expect(rest('POST /v1/search/Article/near-vector {"vector": [0.1]}')).toBe('{"vector":[0.1],"limit":10}'); + }); + + test("an aggregate body is sent as checked", () => { + expect(rest('POST /v1/aggregate/TenantNotes {"tenant": "acme"}')).toBe('{"tenant":"acme"}'); + expect(rest("POST /v1/aggregate/Article")).toBe("{}"); + }); +}); diff --git a/tests/unit/db/weaviate/guard.test.ts b/tests/unit/db/weaviate/guard.test.ts new file mode 100644 index 0000000000..9698dde811 --- /dev/null +++ b/tests/unit/db/weaviate/guard.test.ts @@ -0,0 +1,72 @@ +/** + * The browser's verdict on a Weaviate console text (#1566 spec 5.8): `weaviateRefusal` is the grammar and every phase + * 0 rule, the same two functions the provider runs first, so a text it refuses is never sent and never stored; + * `readWeaviateOperations` is the confirmation gate's reading, the class of the route, and there is no destructive + * operation to confirm. + */ +import { describe, expect, test } from "bun:test"; +import { + readWeaviateOperations, + WEAVIATE_DESTRUCTIVE_OPERATIONS, + weaviateRefusal, +} from "@/lib/db/providers/vector/weaviate/guard"; +import { WEAVIATE_STATEMENT_EXAMPLE } from "@/lib/db/providers/vector/weaviate/labels"; +import { WEAVIATE_RUNS } from "@/lib/db/providers/vector/weaviate/routes"; + +/** The examples of spec 5.4, as a user types them. */ +const EXAMPLES: readonly string[] = [ + "GET /v1/objects?class=Article&limit=50", + 'POST /v1/search/Article/bm25 {"query": "vector search", "where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}, "limit": 5, "returnMetadata": ["score"]}', + 'POST /v1/search/Product/near-vector {"vector": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8], "targetVector": "image", "limit": 3, "returnMetadata": ["distance"]}', + 'POST /v1/aggregate/TenantNotes {"tenant": "acme"}', + "// the first page\n# of articles\nGET objects?class=Article", + WEAVIATE_STATEMENT_EXAMPLE, +]; + +describe("weaviateRefusal", () => { + test.each(EXAMPLES)("accepts %j", (text) => { + expect(weaviateRefusal(text)).toBeUndefined(); + }); + + test("refuses a grammar error with the grammar's sentence", () => { + expect(weaviateRefusal("DELETE /v1/schema/Article")).toBe( + `DELETE /v1/schema/Article is a schema, tenant, index or alias change, which this console does not run. ${WEAVIATE_RUNS} (line 1, column 1)`, + ); + }); + + test("refuses a phase 0 rule with its sentence", () => { + expect(weaviateRefusal('POST /v1/search/Article/hybrid {"query": "x", "alpha": 0.7}')).toBe( + 'alpha must be 0 in this console: any other value makes Weaviate embed the query text with the collection\'s vectorizer, which sends it to a model provider. Write "alpha": 0 for a keyword-only hybrid search.', + ); + expect(weaviateRefusal('POST /v1/search/Article/bm25 {"query": "x", "singlePrompt": "summarise"}')).toBe( + 'The body takes no key "singlePrompt" in this console: generative search sends the results to a model provider.', + ); + }); + + test("leaves the rules that read the collection to the server", () => { + expect(weaviateRefusal("GET /v1/objects?class=TenantNotes")).toBeUndefined(); + expect( + weaviateRefusal('POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["nope"]}'), + ).toBeUndefined(); + }); +}); + +describe("readWeaviateOperations", () => { + test("a text the console runs reads as one read", () => { + for (const text of EXAMPLES) expect(readWeaviateOperations(text)).toEqual(["read"]); + }); + + test("a text the console refuses reads as nothing", () => { + expect(readWeaviateOperations("DELETE /v1/objects/Article")).toBeUndefined(); + expect(readWeaviateOperations('POST /v1/search/Article/bm25 {"query": ""}')).toBeUndefined(); + }); + + test("an error that is no refusal is thrown, never read as a verdict", () => { + expect(() => weaviateRefusal(undefined as unknown as string)).toThrow(TypeError); + expect(() => readWeaviateOperations(undefined as unknown as string)).toThrow(TypeError); + }); + + test("no operation asks for a confirmation", () => { + expect(WEAVIATE_DESTRUCTIVE_OPERATIONS.size).toBe(0); + }); +}); diff --git a/tests/unit/db/weaviate/labels.test.ts b/tests/unit/db/weaviate/labels.test.ts new file mode 100644 index 0000000000..273aea84dc --- /dev/null +++ b/tests/unit/db/weaviate/labels.test.ts @@ -0,0 +1,93 @@ +/** + * The Weaviate labels (#1566 spec 9): the statement-language sentence plan mode states, generated from the route + * table and the dialect so the two cannot drift, and the words the panels show for this engine. + */ +import { describe, expect, test } from "bun:test"; +import type { RouteSpec } from "@/lib/db/console/dialect"; +import { + WEAVIATE_LABELS, + WEAVIATE_REFUSED_CLASSES, + WEAVIATE_STATEMENT_EXAMPLE, + weaviateReadRoutes, + weaviateStatementLanguage, +} from "@/lib/db/providers/vector/weaviate/labels"; +import { refusedRouteSentence, WEAVIATE_CONSOLE, WEAVIATE_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; +import { plan } from "../../../helpers/weaviate-request-fixtures"; + +const ROUTES = + "GET /v1/meta, GET /v1/schema, GET /v1/schema/{collection}, GET /v1/schema/{collection}/shards, GET /v1/schema/{collection}/tenants, GET /v1/schema/{collection}/tenants/{tenant}, GET /v1/aliases, GET /v1/aliases/{alias}, GET /v1/nodes, GET /v1/nodes/{collection}, GET /v1/objects, GET /v1/objects/{collection}/{id}, POST /v1/search/{collection}/bm25, POST /v1/search/{collection}/hybrid, POST /v1/search/{collection}/near-vector, POST /v1/search/{collection}/near-object and POST /v1/aggregate/{collection}"; + +const GOLDEN = [ + `A Weaviate REST request, one per run: optional comment lines starting with // or #, then a line METHOD /path naming one of ${ROUTES}, with every brace-enclosed segment replaced by a real name or id.`, + `GET routes take no body; POST routes take one JSON object with that route's Weaviate REST body, for example ${WEAVIATE_STATEMENT_EXAMPLE}.`, + "Filters are Weaviate where objects with operator, path and one value key such as valueText or valueInt; And, Or and Not take operands.", + 'A multi-tenant collection needs its tenant: ?tenant= on a GET, "tenant" in a body.', + "Not requests: object, schema, tenant and alias writes, batch, backups, users and roles, near-text and the other searches that send text or media to a model, generative search and rerank, hybrid with an alpha other than 0 and GraphQL written by hand.", +].join(" "); + +describe("statementLanguage", () => { + test("the generated sentence, word for word", () => { + expect(WEAVIATE_LABELS.statementLanguage).toBe(GOLDEN); + }); + + test("names the 17 routes of the table, in table order", () => { + const routes = weaviateReadRoutes(WEAVIATE_CONSOLE, WEAVIATE_ROUTES); + expect(routes).toHaveLength(17); + expect(routes.join(", ").replace(/, (?=[^,]*$)/, " and ")).toBe(ROUTES); + }); + + test("a route of another class is never listed", () => { + const write: RouteSpec = { ...WEAVIATE_ROUTES[0], method: "DELETE", template: "objects/{id}", class: "write" }; + expect(weaviateReadRoutes(WEAVIATE_CONSOLE, [...WEAVIATE_ROUTES, write])).not.toContain("DELETE /v1/objects/{id}"); + }); + + test("a one-route table and a one-class refusal list are written without a conjunction", () => { + const sentence = weaviateStatementLanguage(WEAVIATE_CONSOLE, [WEAVIATE_ROUTES[0]], ["batch"]); + expect(sentence).toContain("naming one of GET /v1/meta, with every brace-enclosed segment"); + expect(sentence).toEndWith("Not requests: batch."); + }); + + test("the example is accepted by phase 0 as a bm25 search", () => { + expect(plan(WEAVIATE_STATEMENT_EXAMPLE).route.op).toBe("search_bm25"); + }); + + test.each([ + ["DELETE", "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d"], + ["POST", "/v1/batch/objects"], + ["POST", "/v1/backups/filesystem"], + ["GET", "/v1/users/own-info"], + ["POST", "/v1/search/Article/near-text"], + ["POST", "/v1/graphql"], + ])("%s %s, a class the sentence names, is refused by what it is", (method, path) => { + expect(refusedRouteSentence(method, path)).toContain("which this console does not run"); + }); + + test("the refusal clause holds eight classes", () => { + expect(WEAVIATE_REFUSED_CLASSES).toHaveLength(8); + }); +}); + +describe("the other labels", () => { + test("the entity words, the actions and the captions", () => { + expect(WEAVIATE_LABELS).toMatchObject({ + entityName: "Collection", + entityNamePlural: "Collections", + rowName: "Object", + rowNamePlural: "Objects", + selectAction: "Read Objects", + generateAction: "Generate Request", + searchPlaceholder: "Search collections...", + tableStatsCaption: + "The first 200 single-tenant collections, each with its exact object count (aggregate meta.count). A multi-tenant collection is counted per tenant: POST /v1/aggregate/{collection} with a tenant.", + }); + expect(WEAVIATE_LABELS.slowQueriesEmptyState).toBe( + "Weaviate reports no slow-query log over the routes Studio reads.", + ); + expect(WEAVIATE_LABELS.sessionsEmptyState).toContain("Prometheus server that scrapes Weaviate's metrics"); + }); + + test("the maintenance words say nothing runs", () => { + expect(WEAVIATE_LABELS.analyzeGlobalTitle).toBe("Not available"); + expect(WEAVIATE_LABELS.vacuumGlobalTitle).toBe("Not available"); + }); +}); diff --git a/tests/unit/db/weaviate/monitoring-reads.test.ts b/tests/unit/db/weaviate/monitoring-reads.test.ts new file mode 100644 index 0000000000..b89ef00afc --- /dev/null +++ b/tests/unit/db/weaviate/monitoring-reads.test.ts @@ -0,0 +1,139 @@ +/** + * The Weaviate monitoring reads (#1566 spec 7) over a recording `send`: health is one readiness probe, the overview + * `GET /v1/meta` and `GET /v1/schema`, the Tables panel one schema read then one exact count per single-tenant + * collection of the first 200 by name, one after another, and the Indexes panel the schema read alone. + */ +import { describe, expect, test } from "bun:test"; +import { + readWeaviateHealth, + readWeaviateIndexStats, + readWeaviateOverview, + readWeaviateTableStats, +} from "@/lib/db/providers/vector/weaviate/monitoring-reads"; +import { toWeaviateIndexStats } from "@/lib/db/providers/vector/weaviate/monitoring"; +import { VISIBLE_TO_CREDENTIAL } from "@/lib/db/providers/vector/weaviate/objects"; +import { readWeaviateSchema } from "@/lib/db/providers/vector/weaviate/schema"; +import { expectCalls } from "../../../helpers/call-log"; +import { + type Answering, + capturedServer, + capturedText, + json, + overriding, + surfaceContext, +} from "../../../helpers/weaviate-surface"; + +const SURFACE = capturedServer("weaviate/surface.json"); +const SURFACE_1_37 = capturedServer("weaviate-1-37/surface.json"); + +describe("health", () => { + test("one readiness probe, which carries no credential evidence", async () => { + const { context, calls } = surfaceContext(SURFACE); + expect(await readWeaviateHealth(context)).toEqual({ + databaseSize: "N/A", + cacheHitRatio: "N/A", + slowQueries: [], + activeSessions: [], + }); + expectCalls(calls, [{ method: "ready", args: [{ op: "ready", params: {}, query: {} }] }]); + }); +}); + +describe("the overview", () => { + test("meta for the version, the schema for the collections and their indexes", async () => { + const { context, calls } = surfaceContext(SURFACE); + expect(await readWeaviateOverview(context)).toEqual({ + version: "1.40.2", + uptime: "N/A", + maxConnections: 0, + databaseSize: "N/A", + tableCount: 7, + indexCount: 8, + }); + expectCalls(calls, ["meta", "schema"]); + }); + + test("a version that is not a short token reads N/A; a credential scopes the count", async () => { + const { context } = surfaceContext( + overriding(SURFACE, { meta: () => json({ version: "a sentence, not a version" }) }), + { + scoped: true, + }, + ); + const overview = await readWeaviateOverview(context); + expect(overview.version).toBe("N/A"); + expect(overview.tableCountSampledFrom).toBe(VISIBLE_TO_CREDENTIAL); + }); +}); + +describe("the Tables panel", () => { + test("one exact count per single-tenant collection, by name, one after another; multi-tenant ones left out", async () => { + let inFlight = 0; + let maxInFlight = 0; + const counting: Answering = async (request) => { + inFlight += 1; + maxInFlight = Math.max(maxInFlight, inFlight); + await Bun.sleep(1); + inFlight -= 1; + return SURFACE(request); + }; + const { context, calls } = surfaceContext(counting); + expect(await readWeaviateTableStats(context)).toEqual( + ( + [ + ["Article", 500], + ["Author", 12], + ["EdgeValues", 8], + ["Empty", 0], + ["Product", 200], + ] as const + ).map(([tableName, rowCount]) => ({ schemaName: "", tableName, rowCount, totalSize: "N/A", totalSizeBytes: 0 })), + ); + expect(calls.map((call) => call.method)).toEqual(["schema", ...Array(5).fill("aggregate")]); + expect( + calls.slice(1).map((call) => (call.args as [{ params: { collection: string } }])[0].params.collection), + ).toEqual(["Article", "Author", "EdgeValues", "Empty", "Product"]); + expect(maxInFlight).toBe(1); + }); + + test("on 1.37 each count goes over GraphQL", async () => { + const { context, calls } = surfaceContext(SURFACE_1_37, { version: "1.37.4" }); + const stats = await readWeaviateTableStats(context); + expect(stats.map((row) => row.rowCount)).toEqual([500, 12, 8, 0, 200]); + expect(calls.slice(1).every((call) => call.method === "graphql")).toBe(true); + }); + + test("a count that fails leaves its collection out, and the rest are still read", async () => { + const { context, calls } = surfaceContext( + overriding(SURFACE, { + aggregate: (request) => + request.params.collection === "Author" ? json({ error: [{ message: "boom" }] }, 500) : SURFACE(request), + }), + ); + const stats = await readWeaviateTableStats(context); + expect(stats.map((row) => row.tableName)).toEqual(["Article", "EdgeValues", "Empty", "Product"]); + expect(calls).toHaveLength(6); + }); + + test("only the first 200 collections by name are counted", async () => { + const classes = Array.from({ length: 205 }, (_, index) => ({ class: `C${String(204 - index).padStart(3, "0")}` })); + const { context, calls } = surfaceContext((request) => + request.op === "schema" ? json({ classes }) : json({ count: 1 }), + ); + const stats = await readWeaviateTableStats(context); + expect(stats).toHaveLength(200); + expect(stats[0].tableName).toBe("C000"); + expect(stats.at(-1)?.tableName).toBe("C199"); + expect(calls).toHaveLength(201); + }); +}); + +describe("the Indexes panel", () => { + test("the schema read alone, one row per vector", async () => { + const { context, calls } = surfaceContext(SURFACE); + const schema = readWeaviateSchema(JSON.parse(capturedText("weaviate/surface.json", "GET", "/v1/schema"))); + const sorted = [...schema].sort((a, b) => (a.name < b.name ? -1 : 1)); + expect(await readWeaviateIndexStats(context)).toEqual(toWeaviateIndexStats(sorted)); + expectCalls(calls, ["schema"]); + }); +}); diff --git a/tests/unit/db/weaviate/monitoring.test.ts b/tests/unit/db/weaviate/monitoring.test.ts new file mode 100644 index 0000000000..946ab05f78 --- /dev/null +++ b/tests/unit/db/weaviate/monitoring.test.ts @@ -0,0 +1,118 @@ +/** + * The Weaviate monitoring shapes (#1566 spec 7): a figure Weaviate's read routes do not report reads "N/A" or is + * left out, never zero; the overview counts the collections and one vector index per vector; the Tables panel holds + * exact counts only, a collection whose count was not read left out; the Indexes panel names each vector's index + * type, distance and compression. + */ +import { describe, expect, test } from "bun:test"; +import { + toWeaviateHealth, + toWeaviateIndexStats, + toWeaviateOverview, + toWeaviateTableStats, + WEAVIATE_TABLE_STATS_LIMIT, + weaviateIndexCount, +} from "@/lib/db/providers/vector/weaviate/monitoring"; +import { VISIBLE_TO_CREDENTIAL } from "@/lib/db/providers/vector/weaviate/objects"; +import { readWeaviateSchema } from "@/lib/db/providers/vector/weaviate/schema"; +import { capturedText } from "../../../helpers/weaviate-surface"; + +const COLLECTIONS = readWeaviateSchema(JSON.parse(capturedText("weaviate/surface.json", "GET", "/v1/schema"))); +const byName = (name: string) => COLLECTIONS.filter((collection) => collection.name === name); + +describe("health", () => { + test("readiness only: no size, no cache ratio, no slow query, no session", () => { + expect(toWeaviateHealth()).toEqual({ + databaseSize: "N/A", + cacheHitRatio: "N/A", + slowQueries: [], + activeSessions: [], + }); + }); +}); + +describe("the overview", () => { + test("the version, the collection count, one index per vector; uptime and size not reported", () => { + expect(weaviateIndexCount(COLLECTIONS)).toBe(8); + expect(toWeaviateOverview({ version: "1.40.2", collections: COLLECTIONS, scoped: false })).toEqual({ + version: "1.40.2", + uptime: "N/A", + maxConnections: 0, + databaseSize: "N/A", + tableCount: 7, + indexCount: 8, + }); + }); + + test("a version not reported reads N/A; a credential says what the count was taken from", () => { + expect(toWeaviateOverview({ version: null, collections: [], scoped: true })).toEqual({ + version: "N/A", + uptime: "N/A", + maxConnections: 0, + databaseSize: "N/A", + tableCount: 0, + tableCountSampledFrom: VISIBLE_TO_CREDENTIAL, + indexCount: 0, + }); + }); +}); + +describe("the Tables panel", () => { + test("one row per counted collection with its exact count, in the order given", () => { + expect( + toWeaviateTableStats([ + { name: "Article", count: 500 }, + { name: "Broken", count: null }, + { name: "Empty", count: 0 }, + ]), + ).toEqual([ + { schemaName: "", tableName: "Article", rowCount: 500, totalSize: "N/A", totalSizeBytes: 0 }, + { schemaName: "", tableName: "Empty", rowCount: 0, totalSize: "N/A", totalSizeBytes: 0 }, + ]); + expect(WEAVIATE_TABLE_STATS_LIMIT).toBe(200); + }); +}); + +describe("the Indexes panel", () => { + test("one row per vector: the unnamed one as $vector, a named one as $vector.", () => { + expect(toWeaviateIndexStats(byName("Product"))).toEqual([ + { + schemaName: "", + tableName: "Product", + indexName: "$vector.image", + indexType: "hnsw, cosine", + columns: ["$vector.image"], + isUnique: false, + isPrimary: false, + indexSize: "N/A", + scans: 0, + }, + { + schemaName: "", + tableName: "Product", + indexName: "$vector.text", + indexType: "flat, dot", + columns: ["$vector.text"], + isUnique: false, + isPrimary: false, + indexSize: "N/A", + scans: 0, + }, + ]); + expect(toWeaviateIndexStats(byName("Article")).map((row) => row.indexName)).toEqual(["$vector"]); + }); + + test("the compression joins the type; a distance not declared is left out", () => { + const [compressed] = readWeaviateSchema({ + classes: [ + { class: "C", vectorIndexType: "hnsw", vectorIndexConfig: { distance: "cosine", pq: { enabled: true } } }, + ], + }); + const [bare] = readWeaviateSchema({ classes: [{ class: "D", vectorIndexType: "flat" }] }); + expect(toWeaviateIndexStats([compressed, bare]).map((row) => row.indexType)).toEqual(["hnsw, cosine, pq", "flat"]); + }); + + test("a collection with no vector has no index row", () => { + expect(toWeaviateIndexStats(readWeaviateSchema({ classes: [{ class: "Plain" }] }))).toEqual([]); + }); +}); diff --git a/tests/unit/db/weaviate/objects.test.ts b/tests/unit/db/weaviate/objects.test.ts new file mode 100644 index 0000000000..12a3125884 --- /dev/null +++ b/tests/unit/db/weaviate/objects.test.ts @@ -0,0 +1,376 @@ +/** + * The Weaviate object surface (#1566 spec 4, 6.1, 6.2) over a recording `send` that answers from the captures of the + * seeded servers: the one kind, a listing sorted by name from one schema read, its count scoped to a credential, + * `describeObject` with its one sampled object for the dimensions and none for a multi-tenant collection (W6), + * `describeObjects` in one round trip with the caller's bound, the exact count over the path the version decides, + * and the Source's reads. + */ +import { describe, expect, test } from "bun:test"; +import { AuthenticationError, QueryError } from "@/lib/db/errors"; +import { callerBoundTruncationReason } from "@/lib/db/object-kinds"; +import { + countWeaviateCollection, + countWeaviateObjects, + describeWeaviateObject, + describeWeaviateObjects, + listWeaviateObjects, + NO_COLLECTIONS_VISIBLE, + parseAnswer, + readWeaviateClasses, + readWeaviateCollection, + readWeaviateObjectSource, + VISIBLE_TO_CREDENTIAL, + WEAVIATE_OBJECT_KINDS, + WEAVIATE_SURFACE_TIMEOUT_MS, +} from "@/lib/db/providers/vector/weaviate/objects"; +import { readWeaviateClass, weaviateColumns } from "@/lib/db/providers/vector/weaviate/schema"; +import { weaviateSourceParts } from "@/lib/db/providers/vector/weaviate/source"; +import { expectCalls } from "../../../helpers/call-log"; +import { + answer, + capturedServer, + capturedText, + json, + overriding, + pathMemory, + rejection, + renderedPart, + surfaceContext, +} from "../../../helpers/weaviate-surface"; + +const SURFACE = capturedServer("weaviate/surface.json"); +const SURFACE_1_37 = capturedServer("weaviate-1-37/surface.json"); +const definitionOf = (name: string) => + readWeaviateClass(JSON.parse(capturedText("weaviate/surface.json", "GET", `/v1/schema/${name}`)), name); + +const SORTED = ["Article", "Author", "EdgeValues", "Empty", "Product", "TenantNotes", "TenantNotesAuto"]; + +describe("the kind", () => { + test("one kind, the collection, with columns and a JSON Source, its count the listing", () => { + expect(WEAVIATE_OBJECT_KINDS).toEqual([ + { + id: "collection", + role: "relation", + label: "Collection", + labelPlural: "Collections", + hasColumns: true, + hasSource: true, + sourceLanguage: "json", + countIsListing: true, + }, + ]); + expect(Object.isFrozen(WEAVIATE_OBJECT_KINDS)).toBe(true); + expect(WEAVIATE_SURFACE_TIMEOUT_MS).toBe(10_000); + }); + + test("another kind, or a path that is not [name], is refused before anything is sent", async () => { + const { context, calls } = surfaceContext(SURFACE); + await expect(listWeaviateObjects(context, "view")).rejects.toThrow('Weaviate declares no object kind "view"'); + await expect(describeWeaviateObjects(context, "tenant")).rejects.toThrow(QueryError); + await expect(describeWeaviateObject(context, ["Article", "acme"], "collection")).rejects.toThrow( + 'A Weaviate "collection" path is [name], received ["Article","acme"]', + ); + await expect(readWeaviateObjectSource(context, [], "collection")).rejects.toThrow("is [name], received []"); + expectCalls(calls, []); + }); +}); + +describe("the listing", () => { + test("one schema read, the collections sorted by name, names only", async () => { + const { context, calls } = surfaceContext(SURFACE); + expect(await listWeaviateObjects(context, "collection")).toEqual( + SORTED.map((name) => ({ path: [name], name, kind: "collection" })), + ); + expectCalls(calls, [{ method: "schema", args: [{ op: "schema", params: {}, query: {} }] }]); + }); + + test("whatever order the server lists them in", async () => { + const { context } = surfaceContext(() => json({ classes: ["b", "C", "a", "B"].map((name) => ({ class: name })) })); + expect((await readWeaviateClasses(context)).map((entry) => entry.name)).toEqual(["B", "C", "a", "b"]); + }); + + test("the count: exact with no credential, what the credential may see with one, unavailable when empty", async () => { + expect(await countWeaviateObjects(surfaceContext(SURFACE).context)).toEqual({ collection: { count: 7 } }); + expect(await countWeaviateObjects(surfaceContext(SURFACE, { scoped: true }).context)).toEqual({ + collection: { count: 7, sampledFrom: VISIBLE_TO_CREDENTIAL }, + }); + for (const empty of [{ classes: [] }, { classes: null }, {}]) { + // oxlint-disable-next-line no-await-in-loop -- each answer has its own context. + expect(await countWeaviateObjects(surfaceContext(() => json(empty), { scoped: true }).context)).toEqual({ + collection: { unavailable: NO_COLLECTIONS_VISIBLE }, + }); + } + }); + + test("a schema answer that is not JSON is refused by name", async () => { + const { context } = surfaceContext(() => answer(200, "proxy", "text/html")); + await expect(listWeaviateObjects(context, "collection")).rejects.toThrow( + new QueryError("Weaviate's answer to the schema is not JSON Studio can read.", "weaviate"), + ); + expect(() => parseAnswer(answer(200, ""), "the alias list")).toThrow( + "Weaviate's answer to the alias list is not JSON Studio can read.", + ); + }); +}); + +describe("describeObject", () => { + test("the definition, then one object with its vector for the dimension", async () => { + const { context, calls } = surfaceContext(SURFACE); + const detail = await describeWeaviateObject(context, ["Article"], "collection"); + expectCalls(calls, [ + { method: "collection", args: [{ op: "collection", params: { collection: "Article" }, query: {} }] }, + { + method: "objects", + args: [{ op: "objects", params: {}, query: { class: "Article", limit: "1", include: "vector" } }], + }, + ]); + expect(detail.columns.at(-1)).toEqual({ + name: "$vector", + type: "Vector(16, cosine, hnsw)", + nullable: true, + isPrimary: false, + }); + expect(detail.indexes).toEqual([{ name: "$vector", columns: ["$vector"], unique: false }]); + expect(detail.foreignKeys).toEqual([]); + }); + + test("named vectors take their dimensions from the object's vectors", async () => { + const detail = await describeWeaviateObject(surfaceContext(SURFACE).context, ["Product"], "collection"); + expect(detail.columns.filter((column) => column.name.startsWith("$vector"))).toEqual([ + { name: "$vector.image", type: "Vector(8, cosine, hnsw)", nullable: true, isPrimary: false }, + { name: "$vector.text", type: "Vector(16, dot, flat)", nullable: true, isPrimary: false }, + ]); + }); + + test("a multi-tenant collection is never read past its schema, so no tenant is touched", async () => { + const { context, calls } = surfaceContext(SURFACE); + const detail = await describeWeaviateObject(context, ["TenantNotes"], "collection"); + expectCalls(calls, ["collection"]); + expect(detail.columns.at(-1)?.type).toBe("Vector(?, cosine, hnsw)"); + }); + + test("a collection with no vector config reads no object", async () => { + const plain = { class: "Plain", properties: [{ name: "label", dataType: ["text"] }] }; + const { context, calls } = surfaceContext(() => json(plain)); + const detail = await describeWeaviateObject(context, ["Plain"], "collection"); + expectCalls(calls, ["collection"]); + expect(detail.columns.map((column) => column.name)).toEqual(["$id", "label"]); + expect(detail.indexes).toEqual([]); + }); + + test("an empty collection, or an object without vectors, leaves the dimension unknown", async () => { + const empty = await describeWeaviateObject(surfaceContext(SURFACE).context, ["Empty"], "collection"); + expect(empty.columns.at(-1)?.type).toBe("Vector(?, cosine, hnsw)"); + for (const objects of [ + { objects: [{ id: "x", vector: [], vectors: { image: "not a list" } }] }, + { objects: "none" }, + [], + ]) { + const { context } = surfaceContext(overriding(SURFACE, { objects: () => json(objects) })); + // oxlint-disable-next-line no-await-in-loop -- each answer has its own context. + const detail = await describeWeaviateObject(context, ["Product"], "collection"); + expect( + detail.columns.filter((column) => column.type.startsWith("Vector(?")), + JSON.stringify(objects), + ).toHaveLength(2); + } + }); + + test("a sampled object that is not JSON is refused, naming the collection", async () => { + const { context } = surfaceContext(overriding(SURFACE, { objects: () => answer(200, "{") })); + await expect(describeWeaviateObject(context, ["Article"], "collection")).rejects.toThrow( + `Weaviate's answer to an object of "Article" is not JSON Studio can read.`, + ); + }); +}); + +describe("the definition read", () => { + test("a refusal that does not name the collection is prefixed with it", async () => { + const missing = new QueryError("The collection does not exist or is not visible to this credential.", "weaviate"); + const prefixed = await rejection( + readWeaviateCollection(surfaceContext(() => Promise.reject(missing)).context, "Gone"), + ); + expect(prefixed).toBeInstanceOf(QueryError); + expect((prefixed as Error).message).toBe( + 'Collection "Gone": The collection does not exist or is not visible to this credential.', + ); + const { context } = surfaceContext(() => answer(200, "not json")); + await expect(readWeaviateCollection(context, "Gone")).rejects.toThrow( + new QueryError( + `Weaviate's answer to the definition of collection "Gone" is not JSON Studio can read.`, + "weaviate", + ), + ); + const nameless = surfaceContext(() => json({ description: "no class" })).context; + const error = await rejection(readWeaviateCollection(nameless, "Nameless")); + expect((error as Error).message).toBe(`Weaviate's definition of "Nameless" holds no class name.`); + }); + + test("a QueryError that already names it, or any other error, passes as it is", async () => { + const named = new QueryError('No collection "Gone" here', "weaviate"); + expect(await rejection(readWeaviateCollection(surfaceContext(() => Promise.reject(named)).context, "Gone"))).toBe( + named, + ); + const auth = new AuthenticationError("Weaviate refused the API key or token.", "weaviate"); + expect(await rejection(readWeaviateCollection(surfaceContext(() => Promise.reject(auth)).context, "Gone"))).toBe( + auth, + ); + const plain = new Error("boom"); + expect(await rejection(readWeaviateCollection(surfaceContext(() => Promise.reject(plain)).context, "X"))).toBe( + plain, + ); + }); +}); + +describe("describeObjects", () => { + test("every collection's columns from the one schema read, with no object read", async () => { + const { context, calls } = surfaceContext(SURFACE); + const batch = await describeWeaviateObjects(context, "collection"); + expectCalls(calls, ["schema"]); + expect(batch.details.map((detail) => detail.path[0])).toEqual(SORTED); + expect(batch.truncated).toBeUndefined(); + expect(batch.details[0].columns).toEqual([...weaviateColumns(definitionOf("Article"))]); + }); + + test("the caller's bound cuts after the sort and says so; a bound not reached cuts nothing", async () => { + const cut = await describeWeaviateObjects(surfaceContext(SURFACE).context, "collection", 2); + expect(cut.details.map((detail) => detail.path[0])).toEqual(["Article", "Author"]); + expect(cut.truncated).toEqual({ limit: 2, reason: callerBoundTruncationReason(2) }); + const whole = await describeWeaviateObjects(surfaceContext(SURFACE).context, "collection", 7); + expect(whole.details).toHaveLength(7); + expect(whole.truncated).toBeUndefined(); + }); +}); + +describe("the exact count", () => { + test("over REST on 1.40: one aggregate with an empty body", async () => { + const { context, calls } = surfaceContext(SURFACE); + expect(await countWeaviateCollection(context, definitionOf("Article"))).toBe(500); + expectCalls(calls, [ + { method: "aggregate", args: [{ op: "aggregate", params: { collection: "Article" }, query: {}, body: "{}" }] }, + ]); + }); + + test("over GraphQL on 1.37: one meta count", async () => { + const { context, calls } = surfaceContext(SURFACE_1_37, { version: "1.37.4" }); + expect(await countWeaviateCollection(context, definitionOf("Article"))).toBe(500); + expectCalls(calls, [ + { + method: "graphql", + args: [ + { + op: "graphql", + params: {}, + query: {}, + body: JSON.stringify({ query: "{Aggregate{Article{meta{count}}}}" }), + }, + ], + }, + ]); + }); + + test("the path the session remembered wins over the version's", async () => { + const { context, calls } = surfaceContext(SURFACE_1_37, { paths: pathMemory({ other: "graphql" }) }); + expect(await countWeaviateCollection(context, definitionOf("Empty"))).toBe(0); + expectCalls(calls, ["graphql"]); + }); + + test("a multi-tenant collection is not counted, and nothing is sent", async () => { + const { context, calls } = surfaceContext(SURFACE); + expect(await countWeaviateCollection(context, definitionOf("TenantNotes"))).toBeNull(); + expectCalls(calls, []); + }); + + test("a failed or unreadable count answers null, with no second attempt", async () => { + const cases = [ + () => Promise.reject(new QueryError("rate-limited", "weaviate")), + () => answer(200, "not json"), + () => json(null), + () => json({ count: "500" }), + ]; + for (const answering of cases) { + const { context, calls } = surfaceContext(answering); + // oxlint-disable-next-line no-await-in-loop -- each answer has its own context. + expect(await countWeaviateCollection(context, definitionOf("Article"))).toBeNull(); + expect(calls).toHaveLength(1); + } + for (const body of [{ data: { Aggregate: { Article: [] } } }, { data: { Aggregate: { Article: "x" } } }, {}]) { + const { context } = surfaceContext(() => json(body), { version: "1.37.4" }); + // oxlint-disable-next-line no-await-in-loop -- each answer has its own context. + expect(await countWeaviateCollection(context, definitionOf("Article"))).toBeNull(); + } + }); +}); + +describe("the Source", () => { + test("a single-tenant collection: definition, aliases, shards, then the count", async () => { + const { context, calls } = surfaceContext(SURFACE); + const source = await readWeaviateObjectSource(context, ["Article"], "collection"); + expectCalls(calls, [ + "collection", + { method: "aliases", args: [{ op: "aliases", params: {}, query: {} }] }, + { method: "shards", args: [{ op: "shards", params: { collection: "Article" }, query: {} }] }, + "aggregate", + ]); + expect(source.path).toEqual(["Article"]); + expect(source.kind).toBe("collection"); + const state = JSON.parse(renderedPart(source.parts[1]).text); + expect(state).toMatchObject({ + multiTenant: false, + aliases: ["Articles"], + objectCount: 500, + objectCountKind: "exact, aggregate meta.count", + }); + expect(state.shards).toHaveLength(1); + }); + + test("a multi-tenant collection: its tenants, and no shard read and no count", async () => { + const { context, calls } = surfaceContext(SURFACE); + const source = await readWeaviateObjectSource(context, ["TenantNotes"], "collection"); + expectCalls(calls, [ + "collection", + "aliases", + { method: "tenants", args: [{ op: "tenants", params: { collection: "TenantNotes" }, query: {} }] }, + ]); + const tenants = JSON.parse(capturedText("weaviate/surface.json", "GET", "/v1/schema/TenantNotes/tenants")); + expect(source.parts).toEqual( + weaviateSourceParts({ + definition: definitionOf("TenantNotes"), + aliases: JSON.parse(capturedText("weaviate/surface.json", "GET", "/v1/aliases")), + shards: null, + tenants, + count: null, + }), + ); + expect(JSON.parse(renderedPart(source.parts[1]).text).tenantCount).toBe(tenants.length); + }); + + test("the caller's bound reaches both parts", async () => { + const source = await readWeaviateObjectSource(surfaceContext(SURFACE).context, ["Article"], "collection", 64); + expect(source.parts.every((part) => renderedPart(part).truncated !== undefined)).toBe(true); + }); + + test("an alias, shard or tenant answer that is not JSON is refused by what it is", async () => { + const cases: [string, Parameters[1], string][] = [ + ["Article", { aliases: () => answer(200, "<") }, "the alias list"], + ["Article", { shards: () => answer(200, "<") }, 'the shards of "Article"'], + ["TenantNotes", { tenants: () => answer(200, "<") }, 'the tenants of "TenantNotes"'], + ]; + for (const [name, answers, what] of cases) { + const { context } = surfaceContext(overriding(SURFACE, answers)); + // oxlint-disable-next-line no-await-in-loop -- each answer has its own context. + await expect(readWeaviateObjectSource(context, [name], "collection")).rejects.toThrow( + `Weaviate's answer to ${what} is not JSON Studio can read.`, + ); + } + }); + + test("a failed count leaves the Source standing, saying the count was not read", async () => { + const { context } = surfaceContext(overriding(SURFACE, { aggregate: () => json({}, 500) })); + const state = JSON.parse( + renderedPart((await readWeaviateObjectSource(context, ["Article"], "collection")).parts[1]).text, + ); + expect(state.objectCount).toBe("not read: the aggregate count failed or this server answered none"); + expect(state.objectCountKind).toBeUndefined(); + }); +}); diff --git a/tests/unit/db/weaviate/provider.test.ts b/tests/unit/db/weaviate/provider.test.ts new file mode 100644 index 0000000000..b544056ea0 --- /dev/null +++ b/tests/unit/db/weaviate/provider.test.ts @@ -0,0 +1,460 @@ +/** + * WeaviateProvider at its own seam (#1566 spec 2.3, 3.1, 6.2, 7, 9): the declarations with no client; the connect + * sequence of exactly one `GET /v1/meta`, closing what it built on a failure; the warning below the floor; a console + * request's failures worded by errors.ts with the request's deadline; a cancel by `queryId`; one limiter permit per + * call; the container guard; and that every surface answers what the module that owns it answers over the same + * answers, so the provider composes and never reshapes. + * + * Every client comes from `fakeClients` (tests/helpers/weaviate-surface.ts), answering from the captures of the + * seeded servers or from answers written here in the shape the captures show. + */ +import { describe, expect, test } from "bun:test"; +import { RequestRefusal } from "@/lib/db/console/dialect"; +import { + AuthenticationError, + ConnectionError, + DatabaseConfigError, + QueryCancelledError, + QueryError, + TimeoutError, +} from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import { + WEAVIATE_LIMITER_OPTIONS, + WEAVIATE_ROUTE_TEMPLATES, + WeaviateProvider, +} from "@/lib/db/providers/vector/weaviate/index"; +import { WEAVIATE_LABELS } from "@/lib/db/providers/vector/weaviate/labels"; +import { + readWeaviateHealth, + readWeaviateIndexStats, + readWeaviateOverview, + readWeaviateTableStats, +} from "@/lib/db/providers/vector/weaviate/monitoring-reads"; +import { + countWeaviateObjects, + describeWeaviateObject, + describeWeaviateObjects, + listWeaviateObjects, + readWeaviateObjectSource, + VISIBLE_TO_CREDENTIAL, + WEAVIATE_OBJECT_KINDS, + type WeaviateSurfaceContext, +} from "@/lib/db/providers/vector/weaviate/objects"; +import { WEAVIATE_CLIENT_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; +import type { DatabaseConnection, ProviderExecutionContext, ProviderOptions } from "@/lib/db/types"; +import { DEFAULT_QUERY_LIMIT } from "@/lib/db/utils/query-limiter"; +import { expectCalls } from "../../../helpers/call-log"; +import { + type Answering, + answer, + capturedServer, + fakeClients, + hanging, + json, + overriding, + rejection, + version, + WEAVIATE_TEST_CONNECTION, +} from "../../../helpers/weaviate-surface"; + +const TEST_KEY = "replay-reader-key"; + +const SURFACE = capturedServer("weaviate/surface.json"); +const SURFACE_1_37 = capturedServer("weaviate-1-37/surface.json"); +const READS = capturedServer("weaviate/reads.json"); +const SEARCHES_1_38 = capturedServer("weaviate-1-38/searches.json"); + +function providerOf( + answering: Answering = SURFACE, + connection: Partial = {}, + options: ProviderOptions = {}, + execution: ProviderExecutionContext = {}, +) { + const clients = fakeClients(answering); + const provider = new WeaviateProvider( + { ...WEAVIATE_TEST_CONNECTION, ...connection } as DatabaseConnection, + options, + execution, + clients.factory, + ); + return { provider, clients }; +} + +async function connected(...args: Parameters) { + const built = providerOf(...args); + await built.provider.connect(); + built.clients.calls.length = 0; + return built; +} + +/** The context a module function is handed, over the same answers and the same version as the provider's. */ +function contextOf( + answering: Answering, + serverVersion = "1.40.2", + scoped = false, +): WeaviateSurfaceContext< + "schema" | "collection" | "objects" | "aliases" | "shards" | "tenants" | "aggregate" | "graphql" | "meta" | "ready" +> { + const known = new Map(); + return { + send: async (request, signal) => answering(request, signal), + signal: new AbortController().signal, + version: version(serverVersion), + paths: { get: (kind) => known.get(kind), set: (kind, path) => void known.set(kind, path) }, + scoped, + }; +} + +describe("declarations", () => { + test("the constructor validates nothing and builds no client", () => { + const { provider, clients } = providerOf(SURFACE, { user: "refused-at-connect" }); + expect(provider.isConnected()).toBe(false); + expect(clients.built).toEqual([]); + }); + + test("every capability is written out", () => { + const capabilities: object = providerOf().provider.getCapabilities(); + expect(capabilities).toEqual({ + queryLanguage: "json", + queryDialect: "weaviate", + supportsExplain: false, + supportsTransactions: false, + supportsInlineRowEdit: false, + supportsTestDataGeneration: false, + supportsResultPagination: false, + supportsExternalQueryLimiting: false, + supportsConnectionString: false, + declaresForeignKeys: false, + supportsMaintenance: false, + maintenanceOperations: [], + statementTerminator: "none", + defaultPort: 8080, + containerLevels: [], + objectKinds: WEAVIATE_OBJECT_KINDS, + enforcesReadOnly: true, + schemaRefreshPattern: "(?!)", + }); + }); + + test("no request refreshes the schema: the refresh pattern matches nothing", () => { + const pattern = new RegExp(providerOf().provider.getCapabilities().schemaRefreshPattern as string); + for (const text of ["", "GET /v1/schema", "POST /v1/schema", "DELETE /v1/schema/Article"]) { + expect(pattern.test(text), text).toBe(false); + } + }); + + test("the labels are labels.ts's, as a copy", () => { + const { provider } = providerOf(); + expect(provider.getLabels()).toEqual(WEAVIATE_LABELS); + expect(provider.getLabels()).not.toBe(WEAVIATE_LABELS); + }); + + test("a request is run as written: no limit is added and there is no page two", () => { + expect(providerOf().provider.prepareQuery("GET /v1/objects?class=Article")).toEqual({ + query: "GET /v1/objects?class=Article", + wasLimited: false, + limit: DEFAULT_QUERY_LIMIT, + offset: 0, + }); + }); + + test("the limiter's bounds and the client's route table", () => { + expect(WEAVIATE_LIMITER_OPTIONS).toEqual({ perProvider: 4, perEngine: 16, queueDepth: 64 }); + expect(WEAVIATE_ROUTE_TEMPLATES).toBe(WEAVIATE_CLIENT_ROUTES); + expect(Object.keys(WEAVIATE_ROUTE_TEMPLATES)).toHaveLength(19); + }); + + test("there is no read-only query method and no transaction method", () => { + const provider = providerOf().provider as unknown as Record; + expect(provider.queryReadOnly).toBeUndefined(); + expect(provider.beginTransaction).toBeUndefined(); + }); +}); + +describe("connect", () => { + test("exactly one request, GET /v1/meta, with the route table and the connection's options", async () => { + const { provider, clients } = providerOf(); + await provider.connect(); + expect(provider.isConnected()).toBe(true); + expectCalls(clients, [{ method: "meta", args: [{ op: "meta", params: {}, query: {} }] }]); + expect(clients.built).toHaveLength(1); + expect(clients.built[0].origin).toEqual({ scheme: "http", host: "127.0.0.1", port: 8080 }); + expect(clients.built[0].headers).toEqual({}); + }); + + test("the key travels in the options as one bearer header; the execution profile's read-only mode too", async () => { + const { provider, clients } = providerOf(SURFACE, { password: TEST_KEY }, {}, { readOnly: true }); + await provider.connect(); + expect(clients.built[0].headers).toEqual({ authorization: `Bearer ${TEST_KEY}` }); + expect(clients.built[0].readOnly).toBe("execution-profile"); + }); + + test("a refused connection builds no client and sends nothing", async () => { + const { provider, clients } = providerOf(SURFACE, { user: "admin" }); + await expect(provider.connect()).rejects.toThrow(DatabaseConfigError); + expect(clients.built).toEqual([]); + expect(provider.isConnected()).toBe(false); + }); + + test("a 401 on meta is the key's refusal, and the client built is closed", async () => { + const refused = json({ code: 401, message: "anonymous access not enabled" }, 401); + const { provider, clients } = providerOf(() => refused); + const error = await rejection(provider.connect()); + expect(error).toBeInstanceOf(AuthenticationError); + expect((error as Error).message).toBe( + "Weaviate refused the API key or token. (Weaviate: anonymous access not enabled)", + ); + expect(clients.closed).toBe(1); + expect(provider.isConnected()).toBe(false); + }); + + test("a 403 on meta says the credential may not read the server's meta", async () => { + const forbidden = json({ error: [{ message: "rbac: authorization, forbidden action(s)" }] }, 403); + const { provider } = providerOf(() => forbidden); + const error = await rejection(provider.connect()); + expect(error).toBeInstanceOf(AuthenticationError); + expect((error as Error).message).toStartWith("The credential is not allowed to read this server's meta."); + }); + + test("a transport failure at connect is worded with the surface's deadline", async () => { + const { provider, clients } = providerOf( + () => Promise.reject(new TransportError("timeout", "timed out")), + {}, + { queryTimeout: 4_000 }, + ); + const error = await rejection(provider.connect()); + expect(error).toBeInstanceOf(TimeoutError); + expect((error as Error).message).toBe( + "The request to Weaviate did not finish within 4000 ms, so Studio stopped waiting.", + ); + expect(clients.closed).toBe(1); + }); + + test("a server older than 1.37 connects with one warning; a supported or unread version with none", async () => { + const old = providerOf(overriding(SURFACE, { meta: () => json({ version: "1.36.9" }) })).provider; + expect(old.connectWarnings()).toEqual([]); + await old.connect(); + expect(old.connectWarnings()).toEqual([ + { + message: + "This Weaviate server is 1.36.9, older than 1.37, the oldest line Studio supports; nothing below it is tested.", + }, + ]); + const current = (await connected()).provider; + expect(current.connectWarnings()).toEqual([]); + const unread = (await connected(overriding(SURFACE, { meta: () => json({}) }))).provider; + expect(unread.connectWarnings()).toEqual([]); + }); + + test("disconnect closes the one client, and a second disconnect closes nothing", async () => { + const { provider, clients } = await connected(); + await provider.disconnect(); + expect(clients.closed).toBe(1); + expect(provider.isConnected()).toBe(false); + expect(provider.connectWarnings()).toEqual([]); + await provider.disconnect(); + expect(clients.closed).toBe(1); + }); +}); + +describe("a console request", () => { + test("is refused before connect", async () => { + const { provider, clients } = providerOf(); + await expect(provider.query("GET /v1/meta")).rejects.toThrow("Provider is not connected"); + expectCalls(clients, []); + }); + + test("bound params are refused before anything is sent; an empty list is no params", async () => { + const { provider, clients } = await connected(READS); + const error = await rejection(provider.query("GET /v1/meta", ["x"])); + expect(error).toBeInstanceOf(DatabaseConfigError); + expect((error as Error).message).toBe("Bound params are not supported: a Weaviate request has no placeholders"); + expectCalls(clients, []); + expect((await provider.query("GET /v1/meta", [])).rowCount).toBe(1); + }); + + test("runs over the version connect read: GraphQL on 1.38, with the path named on the result", async () => { + const { provider, clients } = await connected(SEARCHES_1_38); + const result = await provider.query( + 'POST /v1/search/Article/bm25 {"query": "vector", "limit": 3, "returnProperties": ["title", "wordCount"], "returnMetadata": ["score"]}', + ); + expectCalls(clients, ["collection", "graphql"]); + expect(result.warnings).toEqual([{ message: "Answered via GraphQL." }]); + expect(result.fields).toEqual(["$id", "title", "wordCount", "$score"]); + }); + + test("a failed answer is worded by errors.ts: a missing collection, a GraphQL error under 200", async () => { + const { provider } = await connected(READS); + await expect(provider.query("GET /v1/schema/Missing")).rejects.toThrow( + new QueryError("The collection does not exist or is not visible to this credential.", "weaviate"), + ); + const graphql = await connected( + overriding(SEARCHES_1_38, { graphql: () => json({ errors: [{ message: "unexpected token" }] }) }), + ); + const error = await rejection(graphql.provider.query('POST /v1/search/Article/bm25 {"query": "vector"}')); + expect(error).toBeInstanceOf(QueryError); + expect((error as Error).message).toBe( + "Weaviate did not accept the request as written. (Weaviate: unexpected token)", + ); + }); + + test("a transport failure is worded with the search's deadline, at most the query timeout", async () => { + const timedOut = () => Promise.reject(new TransportError("timeout", "timed out")); + const { provider } = await connected(overriding(READS, { objects: timedOut }), {}, { queryTimeout: 12_000 }); + await expect(provider.query("GET /v1/objects?class=Article&limit=3")).rejects.toThrow( + "The request to Weaviate did not finish within 12000 ms, so Studio stopped waiting.", + ); + const long = await connected(overriding(READS, { objects: timedOut }), {}, { queryTimeout: 120_000 }); + await expect(long.provider.query("GET /v1/objects?class=Article&limit=3")).rejects.toThrow( + "did not finish within 30000 ms", + ); + }); + + test("a COLD tenant is refused by the guard after its record", async () => { + const { provider, clients } = await connected(READS); + const error = await rejection(provider.query("GET /v1/objects?class=TenantNotes&limit=2&tenant=initech")); + expect(error).toBeInstanceOf(RequestRefusal); + expectCalls(clients, ["collection", "tenant"]); + }); + + test("a running request is cancelled by its queryId; an unknown id answers false", async () => { + const { provider } = await connected(overriding(READS, { objects: hanging })); + const running = provider.query("GET /v1/objects?class=Article&limit=3", undefined, "q-cancel"); + await Bun.sleep(1); + expect(await provider.cancelQuery("q-cancel")).toBe(true); + expect(await rejection(running)).toBeInstanceOf(QueryCancelledError); + expect(await provider.cancelQuery("q-cancel")).toBe(false); + expect(await provider.cancelQuery("q-never")).toBe(false); + }); +}); + +describe("the surface", () => { + test("every call is refused before connect", async () => { + const { provider, clients } = providerOf(); + for (const call of [ + () => provider.listContainers(), + () => provider.countObjects([]), + () => provider.getHealth(), + () => provider.getOverview(), + () => provider.getPerformanceMetrics(), + () => provider.getSlowQueries(), + () => provider.getActiveSessions(), + () => provider.getStorageStats(), + ]) { + // oxlint-disable-next-line no-await-in-loop -- one call at a time, each refused alone. + expect(await rejection(call())).toBeInstanceOf(DatabaseConfigError); + } + expectCalls(clients, []); + }); + + test("there is no container level: the list is empty and any container is refused", async () => { + const { provider, clients } = await connected(); + expect(await provider.listContainers()).toEqual([]); + for (const call of [ + () => provider.countObjects(["db"]), + () => provider.listObjects(["db"], "collection"), + () => provider.describeObjects(["db"], "collection"), + ]) { + // oxlint-disable-next-line no-await-in-loop -- one call at a time, each refused alone. + const error = await rejection(call()); + expect(error).toBeInstanceOf(QueryError); + expect((error as Error).message).toBe('A Weaviate connection has no container level; received ["db"]'); + } + expectCalls(clients, []); + }); + + test("the tree, the columns and the Source are objects.ts's over the same answers", async () => { + const { provider } = await connected(); + const context = contextOf(SURFACE); + expect(await provider.countObjects([])).toEqual(await countWeaviateObjects(context)); + expect(await provider.countObjects([])).toEqual({ collection: { count: 7 } }); + expect(await provider.listObjects([], "collection")).toEqual(await listWeaviateObjects(context, "collection")); + expect(await provider.describeObject(["Article"], "collection")).toEqual( + await describeWeaviateObject(context, ["Article"], "collection"), + ); + expect(await provider.describeObjects([], "collection", 2)).toEqual( + await describeWeaviateObjects(context, "collection", 2), + ); + expect(await provider.readObjectSource(["TenantNotes"], "collection")).toEqual( + await readWeaviateObjectSource(context, ["TenantNotes"], "collection"), + ); + }); + + test("the panels are monitoring-reads.ts's over the same answers", async () => { + const { provider, clients } = await connected(); + const context = contextOf(SURFACE); + expect(await provider.getHealth()).toEqual(await readWeaviateHealth(context)); + expect(await provider.getOverview()).toEqual(await readWeaviateOverview(context)); + expect(await provider.getTableStats()).toEqual(await readWeaviateTableStats(context)); + expect(await provider.getIndexStats()).toEqual(await readWeaviateIndexStats(context)); + expect(clients.calls.map((call) => call.method).slice(0, 3)).toEqual(["ready", "meta", "schema"]); + }); + + test("a count on 1.37 goes over GraphQL, the version connect read deciding", async () => { + const { provider, clients } = await connected(SURFACE_1_37); + const stats = await provider.getTableStats(); + expect(stats).toEqual(await readWeaviateTableStats(contextOf(SURFACE_1_37, "1.37.4"))); + expect(clients.calls.filter((call) => call.method === "graphql")).toHaveLength(stats.length); + }); + + test("a credential scopes the counts: the listing says what it may see", async () => { + const { provider } = await connected(SURFACE, { password: TEST_KEY }); + expect(await provider.countObjects([])).toEqual({ + collection: { count: 7, sampledFrom: VISIBLE_TO_CREDENTIAL }, + }); + expect((await provider.getOverview()).tableCountSampledFrom).toBe(VISIBLE_TO_CREDENTIAL); + }); + + test("a surface failure is worded by errors.ts in the request phase", async () => { + const forbidden = json({ error: [{ message: "rbac: authorization, forbidden action(s) read_schema" }] }, 403); + const { provider } = await connected(overriding(SURFACE, { schema: () => forbidden })); + const error = await rejection(provider.listObjects([], "collection")); + expect(error).toBeInstanceOf(QueryError); + expect((error as Error).message).toBe( + "The credential is not allowed to run this request. (Weaviate: rbac: authorization, forbidden action(s) read_schema)", + ); + const missing = await connected(overriding(SURFACE, { collection: () => answer(404, "", null) })); + await expect(missing.provider.describeObject(["Missing"], "collection")).rejects.toThrow( + 'Collection "Missing": The collection does not exist or is not visible to this credential.', + ); + const unready = await connected(overriding(SURFACE, { ready: () => json("", 503) })); + expect(await rejection(unready.provider.getHealth())).toBeInstanceOf(ConnectionError); + }); + + test("each surface call takes its own permit: at most four in flight", async () => { + const slow: Answering = async (request) => { + await Bun.sleep(2); + return SURFACE(request); + }; + const { provider, clients } = await connected(slow); + await Promise.all(Array.from({ length: 10 }, () => provider.getHealth())); + expect(clients.calls).toHaveLength(10); + expect(clients.maxInFlight).toBe(4); + }); + + test("each surface call runs under a live deadline signal", async () => { + const { provider, clients } = await connected(); + await provider.getHealth(); + expect(clients.signals.at(-1)?.aborted).toBe(false); + }); + + test("Weaviate reports no performance, slow queries, sessions or storage: each is empty", async () => { + const { provider, clients } = await connected(); + expect(await provider.getPerformanceMetrics()).toEqual({}); + expect(await provider.getSlowQueries()).toEqual([]); + expect(await provider.getActiveSessions()).toEqual([]); + expect(await provider.getStorageStats()).toEqual([]); + expectCalls(clients, []); + }); + + test("maintenance is refused, and nothing is sent", async () => { + const { provider, clients } = await connected(); + const error = await rejection(provider.runMaintenance()); + expect(error).toBeInstanceOf(QueryError); + expect((error as Error).message).toBe( + "Weaviate has no maintenance operation in this version of Studio, so nothing was sent.", + ); + expectCalls(clients, []); + }); +}); diff --git a/tests/unit/db/weaviate/registry-rows.test.ts b/tests/unit/db/weaviate/registry-rows.test.ts new file mode 100644 index 0000000000..83e4bc3287 --- /dev/null +++ b/tests/unit/db/weaviate/registry-rows.test.ts @@ -0,0 +1,67 @@ +/** + * The `weaviate` rows of the five contract registries (#1566 spec 4, 5.9, 9, Migration DDL): each declared beside the + * provider and registered as its row, and each saying what the design says, since a Weaviate console request is not + * SQL text and nothing it runs writes. + */ +import { describe, expect, test } from "bun:test"; +import { CONNECTION_STRING } from "@/lib/db/connection-string"; +import { EXECUTION_UI } from "@/lib/db/execution-ui"; +import { SQL_COMMIT_KEYWORD } from "@/lib/db/execution-ui/shared"; +import { MIGRATION_DDL } from "@/lib/db/migration-ddl"; +import { WEAVIATE_CONNECTION_STRING } from "@/lib/db/providers/vector/weaviate/connection-string"; +import { WEAVIATE_EXECUTION_UI } from "@/lib/db/providers/vector/weaviate/execution-ui"; +import { WEAVIATE_MIGRATION_DDL } from "@/lib/db/providers/vector/weaviate/migration-ddl"; +import { WEAVIATE_SQL_GRAMMAR } from "@/lib/db/providers/vector/weaviate/sql-grammar"; +import { WEAVIATE_SQL_WRITING } from "@/lib/db/providers/vector/weaviate/sql-writing"; +import { SQL_GRAMMAR } from "@/lib/db/sql-grammar"; +import { DEFAULT_SQL_GRAMMAR } from "@/lib/db/sql-grammar/shared"; +import { SQL_WRITING } from "@/lib/db/sql-writing"; +import { identifierDoubleQuoted, literalStandard } from "@/lib/db/sql-writing/shared"; + +describe("each row is the registry's weaviate row", () => { + test.each([ + ["SQL_GRAMMAR", SQL_GRAMMAR.weaviate, WEAVIATE_SQL_GRAMMAR], + ["SQL_WRITING", SQL_WRITING.weaviate, WEAVIATE_SQL_WRITING], + ["MIGRATION_DDL", MIGRATION_DDL.weaviate, WEAVIATE_MIGRATION_DDL], + ["CONNECTION_STRING", CONNECTION_STRING.weaviate, WEAVIATE_CONNECTION_STRING], + ["EXECUTION_UI", EXECUTION_UI.weaviate, WEAVIATE_EXECUTION_UI], + ] as const)("%s", (_name, registered, declared) => { + expect(registered).toBe(declared as never); + }); +}); + +describe("the rows", () => { + test("the SQL grammar reads no SQL text and redacts a statement whole", () => { + expect(WEAVIATE_SQL_GRAMMAR.readsSqlText).toBe(false); + expect(WEAVIATE_SQL_GRAMMAR.grammar).toBe(DEFAULT_SQL_GRAMMAR); + expect(WEAVIATE_SQL_GRAMMAR.redaction).toEqual({ kind: "none" }); + expect(WEAVIATE_SQL_GRAMMAR.completion).toEqual({ formatSegment: null, readQuotedQualifier: null }); + }); + + test("SQL writing is the standard form, with no placeholder and no temporal literal", () => { + expect(WEAVIATE_SQL_WRITING.escapeLiteral).toBe(literalStandard); + expect(WEAVIATE_SQL_WRITING.quoteIdentifier).toBe(identifierDoubleQuoted); + expect(WEAVIATE_SQL_WRITING.placeholder).toBeNull(); + expect(WEAVIATE_SQL_WRITING.temporalLiteral).toBeNull(); + expect(WEAVIATE_SQL_WRITING.export.insertForm).toBe("values"); + }); + + test("migration DDL is refused with the one sentence, and no transaction wrapper", () => { + const reason = + "A collection's properties and vectors are declared through Weaviate's own schema API, not SQL DDL, so there is no column definition to change."; + expect(WEAVIATE_MIGRATION_DDL).toEqual({ + tableDdl: "refused", + refusal: `-- Weaviate: Cannot generate table DDL. ${reason}`, + transactionWrapper: null, + reasons: [reason], + }); + }); + + test("there is no connection string scheme", () => { + expect(WEAVIATE_CONNECTION_STRING).toEqual({ scheme: null, readTls: null, validateSeed: null }); + }); + + test("the execution UI names COMMIT and has no consent deadline", () => { + expect(WEAVIATE_EXECUTION_UI).toEqual({ commitKeyword: SQL_COMMIT_KEYWORD, consentDeadline: null }); + }); +}); diff --git a/tests/unit/db/weaviate/request-filter.test.ts b/tests/unit/db/weaviate/request-filter.test.ts new file mode 100644 index 0000000000..6c792433ab --- /dev/null +++ b/tests/unit/db/weaviate/request-filter.test.ts @@ -0,0 +1,251 @@ +/** + * The where filter of a Weaviate search or aggregate (#1566 spec 5.3, W4): every level is closed, And and Or take + * operands and Not exactly one, every other operator a path and exactly one value key of the right kind, and the + * whole filter is bounded at 256 conditions, 8 levels and 64 KiB. Each rule is read in phase 0 with no call. + */ +import { describe, expect, test } from "bun:test"; +import { toJsonText } from "@/lib/db/console/tagged-json"; +import { refused, searchOf } from "../../../helpers/weaviate-request-fixtures"; + +const search = (where: string) => `POST /v1/search/Article/bm25 {"query": "x", "where": ${where}}`; +const refusedWhere = (where: string) => refused(search(where)); +const condition = (extra: string) => `{"path": ["category"], "operator": "Equal", ${extra}}`; +const nested = (depth: number): string => + depth === 1 ? condition('"valueText": "a"') : `{"operator": "And", "operands": [${nested(depth - 1)}]}`; + +describe("an accepted filter", () => { + test("is handed on exactly as written", () => { + const where = + '{"operator": "And", "operands": [{"path": ["category"], "operator": "Equal", "valueText": "alpha"}, {"operator": "Not", "operands": [{"path": ["wordCount"], "operator": "GreaterThan", "valueInt": 100}]}]}'; + expect(toJsonText(searchOf(search(where)).where as never)).toBe( + '{"operator":"And","operands":[{"path":["category"],"operator":"Equal","valueText":"alpha"},{"operator":"Not","operands":[{"path":["wordCount"],"operator":"GreaterThan","valueInt":100}]}]}', + ); + }); + + test.each([ + ['"valueNumber": 1.5'], + ['"valueNumber": 2'], + ['"valueBoolean": true'], + ['"valueString": "a"'], + ['"valueDate": "2026-01-01T00:00:00Z"'], + ['"valueTextArray": ["a", "b"]'], + ['"valueIntArray": [1, 2]'], + ['"valueNumberArray": [1.5]'], + ['"valueBooleanArray": [false]'], + ['"valueStringArray": ["a"]'], + ['"valueDateArray": ["2026-01-01T00:00:00Z"]'], + ])("takes %s", (value) => { + expect(searchOf(search(condition(value))).where).not.toBeNull(); + }); + + test("a path through a cross-reference names the property, the class, then its property", () => { + expect( + searchOf(search('{"path": ["writtenBy", "Author", "name"], "operator": "Like", "valueText": "A*"}')).where, + ).not.toBeNull(); + }); + + test("IsNull takes valueBoolean", () => { + expect(searchOf(search('{"path": ["category"], "operator": "IsNull", "valueBoolean": true}')).where).not.toBeNull(); + }); + + test("a geo range at the edges of the globe opens", () => { + const where = + '{"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": {"geoCoordinates": {"latitude": -90, "longitude": 180}, "distance": {"max": 0}}}'; + expect(searchOf(search(where)).where).not.toBeNull(); + }); + + test("8 levels and 256 conditions open", () => { + expect(searchOf(search(nested(8))).where).not.toBeNull(); + const operands = new Array(255).fill(condition('"valueText": "a"')).join(","); + expect(searchOf(search(`{"operator": "Or", "operands": [${operands}]}`)).where).not.toBeNull(); + }); +}); + +describe("a refused filter", () => { + test("must be an object", () => { + expect(refusedWhere("[]")).toEqual({ phase: 0, key: "where", message: "where must be an object, found a list." }); + }); + + test("takes only the where filter's keys", () => { + expect(refusedWhere('{"operator": "Equal", "path": ["a"], "valueText": "a", "value": 1}')).toEqual({ + phase: 0, + key: "value", + message: + 'where takes no key "value": Weaviate reads operator, operands, path, valueInt, valueNumber, valueBoolean, valueString, valueText, valueDate, valueIntArray, valueNumberArray, valueBooleanArray, valueStringArray, valueTextArray, valueDateArray, valueGeoRange there and nothing else.', + }); + }); + + test("needs an operator, one of Weaviate's words", () => { + expect(refusedWhere('{"path": ["a"], "valueText": "a"}').message).toBe("where needs the key operator."); + expect(refusedWhere('{"path": ["a"], "operator": "Equals", "valueText": "a"}')).toEqual({ + phase: 0, + key: "where.operator", + message: + 'where.operator takes one of And, Or, Not, Equal, NotEqual, Like, GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, WithinGeoRange, IsNull, ContainsAny, ContainsAll, ContainsNone, not "Equals".', + }); + }); + + test("And, Or and Not take operands only, at least one, and Not exactly one", () => { + expect(refusedWhere('{"operator": "And", "path": ["a"], "operands": []}')).toEqual({ + phase: 0, + key: "where", + message: "where: And takes operands only, never a path or a value.", + }); + expect(refusedWhere('{"operator": "Or", "valueText": "a", "operands": []}').message).toBe( + "where: Or takes operands only, never a path or a value.", + ); + expect(refusedWhere('{"operator": "And"}').message).toBe("where.operands must be a list, found nothing."); + expect(refusedWhere('{"operator": "And", "operands": []}').message).toBe( + "where.operands: And needs at least one operand.", + ); + const two = `${condition('"valueText": "a"')}, ${condition('"valueText": "b"')}`; + expect(refusedWhere(`{"operator": "Not", "operands": [${two}]}`).message).toBe( + "where.operands: Not takes exactly one operand.", + ); + }); + + test("an operand is read at its own place in the filter", () => { + expect( + refusedWhere('{"operator": "And", "operands": [{"operator": "Equal", "path": [], "valueText": "a"}]}'), + ).toEqual({ phase: 0, key: "where.operands[0]", message: "where.operands[0].path names no property." }); + }); + + test("a comparison takes a path and a value, never operands", () => { + expect(refusedWhere('{"operator": "Equal", "path": ["a"], "valueText": "a", "operands": []}').message).toBe( + "where: Equal takes a path and a value, never operands.", + ); + expect(refusedWhere('{"operator": "Equal", "valueText": "a"}').message).toBe( + "where.path must be a list, found nothing.", + ); + expect(refusedWhere('{"operator": "Equal", "path": [1], "valueText": "a"}').message).toBe( + "where.path[0] must be a string, found a number.", + ); + expect(refusedWhere('{"operator": "Equal", "path": ["a b"], "valueText": "a"}').message).toBe( + 'where.path[0] is "a b", which is not a property or class name.', + ); + }); + + test("a comparison takes exactly one value key", () => { + expect(refusedWhere('{"operator": "Equal", "path": ["a"]}').message).toBe( + "where: Equal takes exactly one value key (valueText, valueInt and the rest), found 0.", + ); + expect(refusedWhere(condition('"valueText": "a", "valueInt": 1')).message).toBe( + "where: Equal takes exactly one value key (valueText, valueInt and the rest), found 2.", + ); + }); + + test("a value key written as null is absent, as it is at the top level", () => { + expect(searchOf(search(condition('"valueText": "alpha", "valueGeoRange": null'))).where).not.toBeNull(); + }); + + test("WithinGeoRange and valueGeoRange go only together", () => { + const sentence = "where: WithinGeoRange takes valueGeoRange, and valueGeoRange takes WithinGeoRange."; + expect(refusedWhere('{"operator": "WithinGeoRange", "path": ["location"], "valueText": "a"}').message).toBe( + sentence, + ); + expect(refusedWhere(condition('"valueGeoRange": {}')).message).toBe(sentence); + }); + + test("IsNull takes valueBoolean only", () => { + expect(refusedWhere('{"operator": "IsNull", "path": ["a"], "valueText": "a"}').message).toBe( + "where: IsNull takes valueBoolean.", + ); + }); + + test.each([ + ['"valueInt": 1.5', "where.valueInt must be an integer, found a number."], + [ + '"valueInt": 9007199254740992', + "where.valueInt is 9007199254740992; it takes an integer from -9007199254740991 to 9007199254740991.", + ], + ['"valueNumber": "1"', "where.valueNumber must be a number, found a string."], + ['"valueBoolean": "true"', "where.valueBoolean must be true or false, found a string."], + ['"valueText": 1', "where.valueText must be a string, found a number."], + ['"valueDate": false', "where.valueDate must be a string, found a boolean."], + ['"valueTextArray": "a"', "where.valueTextArray must be a list, found a string."], + ['"valueIntArray": [1, "2"]', "where.valueIntArray[1] must be an integer, found a string."], + ])("a value of the wrong kind, %s, is refused", (value, message) => { + expect(refusedWhere(condition(value)).message).toBe(message); + }); + + test("a value list holds at most 10,000 entries", () => { + const entries = new Array(10_001).fill("1").join(","); + expect(refusedWhere(condition(`"valueIntArray": [${entries}]`)).message).toBe( + "where.valueIntArray holds 10001 entries, above 10000.", + ); + }); + + describe("a geo range", () => { + const geo = (range: string) => `{"path": ["location"], "operator": "WithinGeoRange", "valueGeoRange": ${range}}`; + + test.each([ + ['"x"', "where.valueGeoRange must be an object, found a string."], + ['{"geoCoordinates": {"latitude": 1, "longitude": 1}}', "where.valueGeoRange needs the key distance."], + [ + '{"geoCoordinates": {"latitude": 1, "longitude": 1}, "distance": {"max": 1}, "radius": 1}', + 'where.valueGeoRange takes no key "radius": Weaviate reads geoCoordinates, distance there and nothing else.', + ], + [ + '{"geoCoordinates": [1, 1], "distance": {"max": 1}}', + "where.valueGeoRange.geoCoordinates must be an object, found a list.", + ], + [ + '{"geoCoordinates": {"latitude": 1}, "distance": {"max": 1}}', + "where.valueGeoRange.geoCoordinates needs the key longitude.", + ], + [ + '{"geoCoordinates": {"latitude": "1", "longitude": 1}, "distance": {"max": 1}}', + "where.valueGeoRange.geoCoordinates.latitude must be a number, found a string.", + ], + [ + '{"geoCoordinates": {"latitude": 90.5, "longitude": 1}, "distance": {"max": 1}}', + "where.valueGeoRange.geoCoordinates.latitude is outside -90 to 90.", + ], + [ + '{"geoCoordinates": {"latitude": 1, "longitude": -180.5}, "distance": {"max": 1}}', + "where.valueGeoRange.geoCoordinates.longitude is outside -180 to 180.", + ], + [ + '{"geoCoordinates": {"latitude": 1, "longitude": 1}, "distance": 5}', + "where.valueGeoRange.distance must be an object, found a number.", + ], + [ + '{"geoCoordinates": {"latitude": 1, "longitude": 1}, "distance": {"min": 1}}', + 'where.valueGeoRange.distance takes no key "min": Weaviate reads max there and nothing else.', + ], + [ + '{"geoCoordinates": {"latitude": 1, "longitude": 1}, "distance": {"max": -1}}', + "where.valueGeoRange.distance.max cannot be negative.", + ], + ])("%s is refused", (range, message) => { + expect(refusedWhere(geo(range)).message).toBe(message); + }); + }); + + test("deeper than 8 levels is refused", () => { + expect(refusedWhere(nested(9))).toEqual({ + phase: 0, + key: "where", + message: + "where.operands[0].operands[0].operands[0].operands[0].operands[0].operands[0].operands[0].operands[0] nests filters deeper than 8 levels.", + }); + }); + + test("more than 256 conditions is refused", () => { + const operands = new Array(256).fill(condition('"valueText": "a"')).join(","); + expect(refusedWhere(`{"operator": "Or", "operands": [${operands}]}`)).toEqual({ + phase: 0, + key: "where", + message: "The filter holds more than 256 conditions.", + }); + }); + + test("a filter above 64 KiB is refused before it is walked", () => { + const where = condition(`"valueText": "${"a".repeat(65_536)}"`); + expect(refusedWhere(where)).toEqual({ + phase: 0, + key: "where", + message: "The filter is 65591 bytes, above the bound of 65536.", + }); + }); +}); diff --git a/tests/unit/db/weaviate/request-phase0.test.ts b/tests/unit/db/weaviate/request-phase0.test.ts new file mode 100644 index 0000000000..5d0f51e8d8 --- /dev/null +++ b/tests/unit/db/weaviate/request-phase0.test.ts @@ -0,0 +1,356 @@ +/** + * Phase 0 of the Weaviate console (#1566 spec 5.1 to 5.3, W1): the grammar's sentences for a route it does not run, + * the collection, alias, tenant and id rules, the object list's query keys with their defaults, and the aggregate + * body, each read from the text alone. A refusal is a `RequestRefusal` of phase 0 naming its key. + */ +import { describe, expect, test } from "bun:test"; +import { ConsoleRefusal } from "@/lib/db/console/parser"; +import { type TaggedJson, toJsonText } from "@/lib/db/console/tagged-json"; +import { + parseWeaviateRequest, + serverClassName, + weaviateClassNameRefusal, + weaviateTenantNameRefusal, +} from "@/lib/db/providers/vector/weaviate/request"; +import { WEAVIATE_RUNS } from "@/lib/db/providers/vector/weaviate/routes"; +import { bodyText, plan, refused, refusalOf, searchOf } from "../../../helpers/weaviate-request-fixtures"; + +describe("the grammar", () => { + test("a write route is refused by what it is, then what the console runs", () => { + const error = refusalOf(() => parseWeaviateRequest("DELETE /v1/objects/Article")); + expect(error).toBeInstanceOf(ConsoleRefusal); + expect(error.message).toBe( + `DELETE /v1/objects/Article is an object write, which this console does not run. ${WEAVIATE_RUNS} (line 1, column 1)`, + ); + }); + + test("near-text is refused as a search that sends its text to a model provider", () => { + expect(refusalOf(() => parseWeaviateRequest("POST /v1/search/Article/near-text {}")).message).toBe( + `POST /v1/search/Article/near-text is a search that sends its text or media to a model provider, which this console does not run. ${WEAVIATE_RUNS} (line 1, column 6)`, + ); + }); + + test("an unknown read path, and a method outside GET and POST, each get the console's sentence", () => { + expect(refusalOf(() => parseWeaviateRequest("GET /v1/foo")).message).toBe( + `GET /v1/foo is not a route this console runs. ${WEAVIATE_RUNS} (line 1, column 5)`, + ); + expect(refusalOf(() => parseWeaviateRequest("PUT /v1/foo")).message).toBe( + `PUT /v1/foo is not a request this console runs: it sends GET and POST only. ${WEAVIATE_RUNS} (line 1, column 1)`, + ); + }); + + test("a method with no route keeps the grammar's own sentence", () => { + expect(refusalOf(() => parseWeaviateRequest("FOO")).message).toBe( + "FOO is not a method this console takes: it takes GET and POST. (line 1, column 1)", + ); + expect(refusalOf(() => parseWeaviateRequest("GET")).message).toBe("GET needs a route after it. (line 1, column 4)"); + }); + + test("a refusal that is not about the route keeps the grammar's sentence", () => { + expect(refusalOf(() => parseWeaviateRequest("GET /v1/meta {}")).message).toBe( + "GET meta takes no body. (line 1, column 13)", + ); + expect(refusalOf(() => parseWeaviateRequest("GET /v1/nodes?include=vector")).message).toBe( + "GET nodes takes no query key include. (line 1, column 15)", + ); + }); + + test("the prefix may be left out", () => { + expect(plan("GET schema").route.op).toBe("schema"); + expect(plan("GET /v1/meta").route.op).toBe("meta"); + }); +}); + +describe("collection, alias, tenant and id names (W1)", () => { + test("a collection name is spelled as the server spells it, first letter capitalised", () => { + expect(plan("GET /v1/schema/article").collection).toBe("Article"); + expect(serverClassName("tenantNotes")).toBe("TenantNotes"); + }); + + test("a name of 255 characters opens and one of 256 is refused", () => { + const longest = `A${"b".repeat(254)}`; + expect(weaviateClassNameRefusal(longest)).toBeUndefined(); + expect(weaviateClassNameRefusal(`${longest}b`)).toBe( + `"${"A" + "b".repeat(79)}..." is not a Weaviate collection name: it starts with a letter and holds only letters, digits and _, at most 255 characters.`, + ); + }); + + test("the empty name has its own sentence", () => { + expect(weaviateClassNameRefusal("")).toBe("A collection name cannot be empty."); + }); + + test("a collection name with a character Weaviate refuses is refused naming the path parameter", () => { + expect(refused("GET /v1/schema/1abc")).toEqual({ + phase: 0, + key: "collection", + message: + 'collection: "1abc" is not a Weaviate collection name: it starts with a letter and holds only letters, digits and _, at most 255 characters.', + }); + }); + + test("an alias follows the collection rule", () => { + expect(plan("GET /v1/aliases/Articles").route.op).toBe("alias"); + expect(refused("GET /v1/aliases/my-alias")).toEqual({ + phase: 0, + key: "alias", + message: + 'alias: "my-alias" is not a Weaviate collection name: it starts with a letter and holds only letters, digits and _, at most 255 characters.', + }); + }); + + test("a tenant holds letters, digits, - and _, 1 to 64 characters", () => { + expect(weaviateTenantNameRefusal("acme-1_x")).toBeUndefined(); + expect(weaviateTenantNameRefusal("x".repeat(64))).toBeUndefined(); + expect(weaviateTenantNameRefusal("x".repeat(65))).toBe( + `"${"x".repeat(65)}" is not a Weaviate tenant name: it holds only letters, digits, - and _, 1 to 64 characters.`, + ); + expect(plan("GET /v1/schema/TenantNotes/tenants/acme").tenant).toBe("acme"); + expect(refused("GET /v1/schema/TenantNotes/tenants/a.b")).toEqual({ + phase: 0, + key: "tenant", + message: + 'tenant: "a.b" is not a Weaviate tenant name: it holds only letters, digits, - and _, 1 to 64 characters.', + }); + }); + + test("an object id is a UUID", () => { + expect(plan("GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d").route.op).toBe("object"); + expect(refused("GET /v1/objects/Article/42")).toEqual({ + phase: 0, + key: "id", + message: 'id is "42", which is not a UUID: Weaviate\'s object ids are UUIDs.', + }); + }); + + test("a tenant in the query string is the plan's tenant", () => { + expect(plan("GET /v1/schema/TenantNotes/shards?tenant=acme").tenant).toBe("acme"); + expect(refused("GET /v1/schema/TenantNotes/shards?tenant=a.b").key).toBe("tenant"); + }); + + test("a route that names no collection plans none, and takes no body", () => { + const meta = plan("GET /v1/meta"); + expect({ collection: meta.collection, tenant: meta.tenant, body: meta.body, search: meta.search }).toEqual({ + collection: null, + tenant: null, + body: null, + search: null, + }); + expect(meta.warnings).toEqual([]); + }); +}); + +describe("GET /v1/objects (spec 5.2, 5.3)", () => { + test("names its class, which is the plan's collection, and is sent with the default limit 25", () => { + const read = plan("GET /v1/objects?class=article"); + expect(read.collection).toBe("Article"); + expect(read.query).toEqual({ class: "article", limit: "25" }); + }); + + test("keeps a limit the user wrote", () => { + expect(plan("GET /v1/objects?class=Article&limit=50").query.limit).toBe("50"); + }); + + test("without a class is refused", () => { + expect(refused("GET /v1/objects")).toEqual({ + phase: 0, + key: "class", + message: "GET /v1/objects needs ?class=: without it Weaviate answers no objects.", + }); + }); + + test("a class that is no collection name is refused naming class", () => { + expect(refused("GET /v1/objects?class=a-b").message).toBe( + 'class: "a-b" is not a Weaviate collection name: it starts with a letter and holds only letters, digits and _, at most 255 characters.', + ); + }); + + test.each([ + ["after=9e6866af-ef70-5a5a-9b61-1ae7a41bad0d&offset=3", "after"], + ["after=9e6866af-ef70-5a5a-9b61-1ae7a41bad0d&sort=title", "after"], + ])("after with %s is refused: after pages by id", (keys, key) => { + expect(refused(`GET /v1/objects?class=Article&${keys}`)).toEqual({ + phase: 0, + key, + message: "after pages by id, so it takes neither offset nor sort.", + }); + }); + + test("after must be a UUID", () => { + expect(refused("GET /v1/objects?class=Article&after=abc").message).toBe( + 'after is "abc", which is not a UUID: Weaviate\'s object ids are UUIDs.', + ); + }); + + test("order needs sort", () => { + expect(refused("GET /v1/objects?class=Article&order=asc")).toEqual({ + phase: 0, + key: "order", + message: "order needs sort.", + }); + }); + + test("every sort entry is a property name", () => { + expect(plan("GET /v1/objects?class=Article&sort=title,wordCount&order=desc").query.sort).toBe("title,wordCount"); + expect(refused("GET /v1/objects?class=Article&sort=title,9x")).toEqual({ + phase: 0, + key: "sort[1]", + message: 'sort[1] is "9x", which is not a Weaviate property name.', + }); + }); + + test("a tenant in the query string is checked and planned", () => { + expect(plan("GET /v1/objects?class=TenantNotes&tenant=acme").tenant).toBe("acme"); + expect(refused("GET /v1/objects?class=TenantNotes&tenant=a.b").key).toBe("tenant"); + }); + + test("limit plus offset is at most 1,000", () => { + expect(plan("GET /v1/objects?class=Article&limit=990&offset=10").query).toEqual({ + class: "Article", + limit: "990", + offset: "10", + }); + expect(refused("GET /v1/objects?class=Article&limit=1001")).toEqual({ + phase: 0, + key: "limit", + message: "limit plus offset is 1001, above the bound of 1000 rows.", + }); + expect(refused("GET /v1/objects?class=Article&offset=980").message).toBe( + "limit plus offset is 1005, above the bound of 1000 rows.", + ); + }); + + test("offset takes 0, which Weaviate reads as the first object, and refuses anything else that is not a count", () => { + expect(plan("GET /v1/objects?class=Article&offset=0").query.offset).toBe("0"); + for (const value of ["-1", "01", "1.5", "x"]) { + expect(refused(`GET /v1/objects?class=Article&offset=${value}`)).toEqual({ + phase: 0, + key: "offset", + message: `offset is "${value}"; it takes an integer from 0 to 1000.`, + }); + } + }); + + test("a groupBy that names no limit is sent with the server's own 100, and an aggregate without one with none", () => { + expect(bodyText('POST /v1/aggregate/Article {"groupBy": "category"}')).toBe('{"groupBy":"category","limit":100}'); + expect(bodyText('POST /v1/aggregate/Article {"groupBy": "category", "limit": 7}')).toBe( + '{"groupBy":"category","limit":7}', + ); + expect(bodyText("POST /v1/aggregate/Article {}")).toBe("{}"); + }); + + test("include is a key of the two object reads only", () => { + expect(plan("GET /v1/objects?class=Article&include=vector").query.include).toBe("vector"); + expect(plan("GET /v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d?include=vector").query.include).toBe( + "vector", + ); + }); +}); + +describe("GET /v1/nodes", () => { + test("output takes one word", () => { + expect(plan("GET /v1/nodes?output=verbose").query).toEqual({ output: "verbose" }); + expect(plan("GET /v1/nodes/Article?output=minimal").collection).toBe("Article"); + expect(refused("GET /v1/nodes?output=minimal,verbose")).toEqual({ + phase: 0, + key: "output", + message: "output takes one of minimal or verbose.", + }); + }); +}); + +describe("POST /v1/aggregate/{collection} (spec 5.2)", () => { + test("an absent body is an empty aggregate, one count", () => { + const read = plan("POST /v1/aggregate/Article"); + expect(bodyText("POST /v1/aggregate/Article")).toBe("{}"); + expect(read.search).toEqual({ + op: "aggregate", + collection: "Article", + tenant: null, + where: null, + limit: null, + offset: null, + autoLimit: null, + consistencyLevel: null, + returnProperties: null, + returnMetadata: [], + query: null, + queryProperties: null, + fusionType: null, + maxVectorDistance: null, + vector: null, + id: null, + targetVector: null, + distance: null, + certainty: null, + groupBy: null, + }); + }); + + test("the body's tenant is the plan's tenant", () => { + const read = plan('POST /v1/aggregate/TenantNotes {"tenant": "acme"}'); + expect(read.tenant).toBe("acme"); + expect(read.search?.tenant).toBe("acme"); + expect(bodyText('POST /v1/aggregate/TenantNotes {"tenant": "acme"}')).toBe('{"tenant":"acme"}'); + }); + + test("a groupBy names a property, and a limit bounds its groups", () => { + const read = searchOf('POST /v1/aggregate/Article {"groupBy": "category", "limit": 3, "returnMetrics": ["count"]}'); + expect(read.groupBy).toBe("category"); + expect(toJsonText(read.limit as TaggedJson)).toBe("3"); + }); + + test("a limit without groupBy is refused, since an aggregate without groupBy has one row", () => { + expect(refused('POST /v1/aggregate/Article {"limit": 3}')).toEqual({ + phase: 0, + key: "limit", + message: "limit bounds the groups of a groupBy; an aggregate without groupBy has one row.", + }); + }); + + test("a groupBy limit is bounded from 1 to 1000", () => { + expect(refused('POST /v1/aggregate/Article {"groupBy": "category", "limit": 0}').message).toBe( + "limit is 0; it takes an integer from 1 to 1000.", + ); + }); + + test("groupBy must be a property name, written as a string", () => { + expect(refused('POST /v1/aggregate/Article {"groupBy": "9x"}')).toEqual({ + phase: 0, + key: "groupBy", + message: 'groupBy is "9x", which is not a Weaviate property name.', + }); + expect(refused('POST /v1/aggregate/Article {"groupBy": ["category"]}').message).toBe( + "groupBy must be a string, found a list.", + ); + }); + + test("returnMetrics takes count only", () => { + expect(refused('POST /v1/aggregate/Article {"returnMetrics": ["mean"]}')).toEqual({ + phase: 0, + key: "returnMetrics[0]", + message: 'returnMetrics[0] takes one of count, not "mean".', + }); + expect(refused('POST /v1/aggregate/Article {"returnMetrics": "count"}').message).toBe( + "returnMetrics must be a list, found a string.", + ); + }); + + test("over and objectLimit are refused as reserved, an unknown key by the closed set", () => { + expect(refused('POST /v1/aggregate/Article {"over": {}}')).toEqual({ + phase: 0, + key: "over", + message: + 'The body takes no key "over" in this console: aggregate over a search is reserved in Weaviate\'s REST aggregate.', + }); + expect(refused('POST /v1/aggregate/Article {"filter": {}}').message).toBe( + 'The body takes no key "filter": Weaviate reads where, tenant, groupBy, limit, returnMetrics there and nothing else.', + ); + }); + + test("a where filter is read by the same rules as a search's", () => { + const read = searchOf( + 'POST /v1/aggregate/Article {"where": {"path": ["category"], "operator": "Equal", "valueText": "alpha"}}', + ); + expect(read.where).not.toBeNull(); + }); +}); diff --git a/tests/unit/db/weaviate/request-phase1.test.ts b/tests/unit/db/weaviate/request-phase1.test.ts new file mode 100644 index 0000000000..95e7aa138e --- /dev/null +++ b/tests/unit/db/weaviate/request-phase1.test.ts @@ -0,0 +1,179 @@ +/** + * Phase 1 of the Weaviate console (#1566 spec 3.4, 5.3, W6): the rules that read the collection's definition, the + * tenancy rule, every property a request names, the target vector, and the query vector's numbers. A refusal is a + * `RequestRefusal` of phase 1 naming its key; nothing is sent. The definitions are the seeded server's own. + */ +import { describe, expect, test } from "bun:test"; +import { type WeaviatePlan, weaviatePhase1 } from "@/lib/db/providers/vector/weaviate/request"; +import type { WeaviateCollectionFacts } from "@/lib/db/providers/vector/weaviate/schema"; +import { handFacts, plan, recordedFacts, refusalOf } from "../../../helpers/weaviate-request-fixtures"; + +const ARTICLE = recordedFacts("Article"); +const PRODUCT = recordedFacts("Product"); +const TENANT_NOTES = recordedFacts("TenantNotes"); + +const phase1 = (text: string, facts: WeaviateCollectionFacts): WeaviatePlan => weaviatePhase1(plan(text), facts); +function refused(text: string, facts: WeaviateCollectionFacts) { + const error = refusalOf(() => phase1(text, facts)); + return { phase: error.phase, key: error.key, message: error.message }; +} + +describe("the tenancy rule (W6)", () => { + test("a multi-tenant collection's data read without a tenant is refused, naming the tenant list", () => { + expect(refused("GET /v1/objects?class=TenantNotes", TENANT_NOTES)).toEqual({ + phase: 1, + key: "tenant", + message: + 'The collection "TenantNotes" is multi-tenant, so the request needs a tenant (?tenant=...). Nothing was read: GET /v1/schema/TenantNotes/tenants lists its tenants and which are HOT, without waking any.', + }); + expect(refused('POST /v1/search/TenantNotes/bm25 {"query": "note"}', TENANT_NOTES).message).toBe( + 'The collection "TenantNotes" is multi-tenant, so the request needs a tenant ("tenant": "..."). Nothing was read: GET /v1/schema/TenantNotes/tenants lists its tenants and which are HOT, without waking any.', + ); + }); + + test("the collection's own record, its tenant list and its nodes name no tenant", () => { + for (const text of [ + "GET /v1/schema/TenantNotes", + "GET /v1/schema/TenantNotes/tenants", + "GET /v1/nodes/TenantNotes", + ]) { + expect(phase1(text, TENANT_NOTES).tenant).toBeNull(); + } + }); + + test("a multi-tenant read with its tenant opens", () => { + expect(phase1("GET /v1/objects?class=TenantNotes&tenant=acme", TENANT_NOTES).tenant).toBe("acme"); + expect(phase1('POST /v1/aggregate/TenantNotes {"tenant": "acme"}', TENANT_NOTES).tenant).toBe("acme"); + }); + + test("a tenant on a collection that is not multi-tenant is refused, but the tenant record route is not", () => { + expect(refused("GET /v1/objects?class=Article&tenant=acme", ARTICLE)).toEqual({ + phase: 1, + key: "tenant", + message: 'The collection "Article" is not multi-tenant, so the request takes no tenant.', + }); + expect(phase1("GET /v1/schema/Article/tenants/acme", ARTICLE).route.op).toBe("tenant"); + }); + + test("a route that is no search answers the plan unchanged", () => { + const read = plan("GET /v1/schema/Article"); + expect(weaviatePhase1(read, ARTICLE)).toBe(read); + }); +}); + +describe("the properties a request names", () => { + test("a property the collection does not have is refused by name", () => { + expect(refused('POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["titel"]}', ARTICLE)).toEqual({ + phase: 1, + key: "returnProperties", + message: 'returnProperties names "titel", which is no property of "Article".', + }); + }); + + test("a cross-reference is refused, outside this version", () => { + expect(refused('POST /v1/search/Article/bm25 {"query": "x", "returnProperties": ["writtenBy"]}', ARTICLE)).toEqual({ + phase: 1, + key: "returnProperties", + message: + 'returnProperties names "writtenBy", a cross-reference: returning cross-references is outside this version of the console.', + }); + }); + + test("a boosted query property is checked without its boost", () => { + const read = phase1('POST /v1/search/Article/bm25 {"query": "x", "queryProperties": ["title^2", "body"]}', ARTICLE); + expect(read.search?.queryProperties).toEqual(["title^2", "body"]); + expect(refused('POST /v1/search/Article/bm25 {"query": "x", "queryProperties": ["nope^2"]}', ARTICLE).message).toBe( + 'queryProperties names "nope", which is no property of "Article".', + ); + }); + + test("an aggregate's groupBy names a property, and an aggregate needs no vector", () => { + expect(phase1('POST /v1/aggregate/Article {"groupBy": "category"}', ARTICLE).search?.groupBy).toBe("category"); + expect(refused('POST /v1/aggregate/Article {"groupBy": "nope"}', ARTICLE)).toEqual({ + phase: 1, + key: "groupBy", + message: 'groupBy names "nope", which is no property of "Article".', + }); + const none = handFacts({ name: "Article", vectors: [], properties: ["category"] }); + expect(phase1("POST /v1/aggregate/Article", none).search?.targetVector).toBeNull(); + }); +}); + +describe("the target vector", () => { + test("the unnamed vector is the target of a collection that has only it, written as none", () => { + expect(phase1('POST /v1/search/Article/near-vector {"vector": [0.1]}', ARTICLE).search?.targetVector).toBeNull(); + }); + + test("a collection's only named vector is filled in for the encoders", () => { + const single = handFacts({ name: "Article", vectors: ["text"] }); + expect(phase1('POST /v1/search/Article/near-vector {"vector": [0.1]}', single).search?.targetVector).toBe("text"); + }); + + test("a collection with several vectors needs targetVector, and the one named must exist", () => { + expect(refused('POST /v1/search/Product/near-vector {"vector": [0.1]}', PRODUCT)).toEqual({ + phase: 1, + key: "targetVector", + message: + 'The collection "Product" has more than one vector, so the search needs targetVector: it has image, text.', + }); + expect( + phase1('POST /v1/search/Product/near-vector {"vector": [0.1], "targetVector": "image"}', PRODUCT).search + ?.targetVector, + ).toBe("image"); + expect(refused('POST /v1/search/Product/near-vector {"vector": [0.1], "targetVector": "audio"}', PRODUCT)).toEqual({ + phase: 1, + key: "targetVector", + message: 'targetVector names "audio", which is no vector of "Product": it has image, text.', + }); + }); + + test("the unnamed vector is named as such, and a collection with none says so", () => { + const both = handFacts({ name: "Mixed", vectors: ["", "image"] }); + expect(refused('POST /v1/search/Mixed/near-vector {"vector": [0.1], "targetVector": "x"}', both).message).toBe( + 'targetVector names "x", which is no vector of "Mixed": it has the unnamed vector, image.', + ); + const none = handFacts({ name: "Bare", vectors: [] }); + expect(refused('POST /v1/search/Bare/near-vector {"vector": [0.1], "targetVector": "x"}', none).message).toBe( + 'targetVector names "x", which is no vector of "Bare": it has no vector.', + ); + expect(refused('POST /v1/search/Bare/near-object {"id": "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d"}', none)).toEqual({ + phase: 1, + key: "targetVector", + message: 'The collection "Bare" has no vector to search.', + }); + }); + + test("bm25 needs no vector, and names none on a collection with several", () => { + const none = handFacts({ name: "Bare", vectors: [] }); + expect(phase1('POST /v1/search/Bare/bm25 {"query": "x"}', none).search?.targetVector).toBeNull(); + // A BM25 search reads no vector, so none is sent on either path (the REST server ignores one, measured on 1.40.2). + expect(phase1('POST /v1/search/Product/bm25 {"query": "x"}', PRODUCT).search?.targetVector).toBeNull(); + }); + + test("hybrid at alpha 0 opens on a vectorized collection, as measured", () => { + const vectorized = handFacts({ name: "Doc", vectors: [["", "text2vec-openai"]] }); + expect(phase1('POST /v1/search/Doc/hybrid {"query": "x", "alpha": 0}', vectorized).search?.op).toBe( + "search_hybrid", + ); + }); +}); + +describe("the query vector's numbers", () => { + test("an integer a double cannot hold exactly is refused in phase 1", () => { + expect(refused('POST /v1/search/Article/near-vector {"vector": [0.1, 9007199254740993]}', ARTICLE)).toEqual({ + phase: 1, + key: "vector", + message: + "vector: The unnamed vector (float32): element 1 is 9007199254740993, outside the range a double holds exactly.", + }); + }); + + test("a number a float32 cannot hold is refused in phase 1", () => { + expect(refused('POST /v1/search/Article/near-vector {"vector": [1e39]}', ARTICLE)).toEqual({ + phase: 1, + key: "vector", + message: + "vector: The unnamed vector (float32): element 0 is 1e+39, not a finite number of absolute value at most 3.4028234663852886e+38.", + }); + }); +}); diff --git a/tests/unit/db/weaviate/request-search.test.ts b/tests/unit/db/weaviate/request-search.test.ts new file mode 100644 index 0000000000..842432ce58 --- /dev/null +++ b/tests/unit/db/weaviate/request-search.test.ts @@ -0,0 +1,297 @@ +/** + * Phase 0 of the four Weaviate searches (#1566 spec 5.2, 5.3, W3): the closed body and its refused keys, the + * inference rule (hybrid only at alpha 0), every value's kind and bound, and the default limit written in so the + * REST and the GraphQL paths answer the same rows. + */ +import { describe, expect, test } from "bun:test"; +import { type TaggedJson, toJsonText } from "@/lib/db/console/tagged-json"; +import { bodyText, plan, refused, searchOf } from "../../../helpers/weaviate-request-fixtures"; + +const UUID = "9e6866af-ef70-5a5a-9b61-1ae7a41bad0d"; +const bm25 = (body: string) => `POST /v1/search/Article/bm25 ${body}`; +const hybrid = (body: string) => `POST /v1/search/Article/hybrid ${body}`; +const nearVector = (body: string) => `POST /v1/search/Article/near-vector ${body}`; +const nearObject = (body: string) => `POST /v1/search/Article/near-object ${body}`; +const text = (value: TaggedJson | null) => (value === null ? null : toJsonText(value)); + +describe("the default limit", () => { + test("a search with no limit is sent with 10, written into the body and the model", () => { + expect(bodyText(bm25('{"query": "vector"}'))).toBe('{"query":"vector","limit":10}'); + expect(text(searchOf(bm25('{"query": "vector"}')).limit)).toBe("10"); + }); + + test("a null key is dropped, and a null limit takes the default", () => { + expect(bodyText(bm25('{"query": "vector", "limit": null, "tenant": null}'))).toBe('{"query":"vector","limit":10}'); + }); + + test("a limit as typed is kept, digits and all", () => { + expect(bodyText(bm25('{"query": "vector", "limit": 3}'))).toBe('{"query":"vector","limit":3}'); + }); +}); + +describe("bm25", () => { + test("the model holds every value as written", () => { + const search = searchOf( + bm25( + `{"query": "vector search", "queryProperties": ["title^2", "body"], "limit": 5, "offset": 2, "autoLimit": 1, "returnProperties": ["title"], "returnMetadata": ["score", "explainScore"], "consistencyLevel": "QUORUM", "tenant": "acme"}`, + ), + ); + expect({ + op: search.op, + collection: search.collection, + query: search.query, + queryProperties: search.queryProperties, + limit: text(search.limit), + offset: text(search.offset), + autoLimit: text(search.autoLimit), + returnProperties: search.returnProperties, + returnMetadata: search.returnMetadata, + consistencyLevel: search.consistencyLevel, + tenant: search.tenant, + targetVector: search.targetVector, + }).toEqual({ + op: "search_bm25", + collection: "Article", + query: "vector search", + queryProperties: ["title^2", "body"], + limit: "5", + offset: "2", + autoLimit: "1", + returnProperties: ["title"], + returnMetadata: ["score", "explainScore"], + consistencyLevel: "QUORUM", + tenant: "acme", + targetVector: null, + }); + expect(plan(bm25('{"query": "x", "tenant": "acme"}')).tenant).toBe("acme"); + }); + + test("query is required, must be a string and must hold words", () => { + expect(refused(bm25("{}"))).toEqual({ phase: 0, key: "query", message: "The body needs the key query." }); + expect(refused(bm25('{"query": 3}')).message).toBe("query must be a string, found a number."); + expect(refused(bm25('{"query": " "}'))).toEqual({ + phase: 0, + key: "query", + message: "query is empty: a keyword search needs words.", + }); + }); + + test("an unknown key is refused naming the keys the body takes", () => { + expect(refused(bm25('{"query": "x", "filter": {}}'))).toEqual({ + phase: 0, + key: "filter", + message: + 'The body takes no key "filter": Weaviate reads where, limit, offset, autoLimit, returnProperties, returnMetadata, tenant, consistencyLevel, query, queryProperties there and nothing else.', + }); + }); + + test("a key longer than 80 characters is shown cut", () => { + const key = "k".repeat(81); + expect(refused(bm25(`{"query": "x", "${key}": 1}`)).message).toStartWith( + `The body takes no key "${"k".repeat(80)}...": Weaviate reads`, + ); + }); + + test.each([ + ["singlePrompt", "generative search sends the results to a model provider"], + ["groupedTask", "generative search sends the results to a model provider"], + ["rerank", "reranking sends the results to a model provider"], + ["groupBy", "grouped search is reserved in Weaviate's REST search"], + ["numberOfGroups", "grouped search is reserved in Weaviate's REST search"], + ["objectsPerGroup", "grouped search is reserved in Weaviate's REST search"], + ["returnReferences", "returning cross-references is outside this version of the console"], + ])("%s is refused by name with its reason", (key, reason) => { + expect(refused(bm25(`{"query": "x", "${key}": 1}`))).toEqual({ + phase: 0, + key, + message: `The body takes no key "${key}" in this console: ${reason}.`, + }); + }); + + test("queryProperties takes 1 to 256 boosted property names, each once", () => { + expect(refused(bm25('{"query": "x", "queryProperties": []}'))).toEqual({ + phase: 0, + key: "queryProperties", + message: "queryProperties holds 0 properties; it takes 1 to 256.", + }); + const many = JSON.stringify(Array.from({ length: 257 }, (_, index) => `p${index}`)); + expect(refused(bm25(`{"query": "x", "queryProperties": ${many}}`)).message).toBe( + "queryProperties holds 257 properties; it takes 1 to 256.", + ); + expect(refused(bm25('{"query": "x", "queryProperties": ["title^x"]}')).message).toBe( + 'queryProperties[0] is "title^x", which is not a Weaviate property name.', + ); + expect(refused(bm25('{"query": "x", "queryProperties": ["title", "title"]}')).message).toBe( + 'queryProperties names "title" twice.', + ); + expect(refused(bm25('{"query": "x", "queryProperties": [1]}')).message).toBe( + "queryProperties[0] must be a string, found a number.", + ); + expect(refused(bm25('{"query": "x", "queryProperties": "title"}')).message).toBe( + "queryProperties must be a list, found a string.", + ); + }); + + test("returnProperties takes plain names, no boost", () => { + expect(refused(bm25('{"query": "x", "returnProperties": ["title^2"]}'))).toEqual({ + phase: 0, + key: "returnProperties", + message: 'returnProperties[0] is "title^2", which is not a Weaviate property name.', + }); + }); + + test("returnMetadata and consistencyLevel take their words", () => { + expect(refused(bm25('{"query": "x", "returnMetadata": ["vector"]}'))).toEqual({ + phase: 0, + key: "returnMetadata[0]", + message: + 'returnMetadata[0] takes one of distance, certainty, score, explainScore, creationTime, lastUpdateTime, not "vector".', + }); + expect(refused(bm25('{"query": "x", "consistencyLevel": 1}')).message).toBe( + "consistencyLevel takes one of ONE, QUORUM, ALL, not a number.", + ); + }); + + test("a body tenant is a tenant name", () => { + expect(refused(bm25('{"query": "x", "tenant": "a.b"}'))).toEqual({ + phase: 0, + key: "tenant", + message: + 'tenant: "a.b" is not a Weaviate tenant name: it holds only letters, digits, - and _, 1 to 64 characters.', + }); + expect(refused(bm25('{"query": "x", "tenant": true}')).message).toBe("tenant must be a string, found a boolean."); + }); +}); + +describe("limit, offset and autoLimit", () => { + test.each([ + ['"limit": 0', "limit is 0; it takes an integer from 1 to 1000."], + ['"limit": 1001', "limit is 1001; it takes an integer from 1 to 1000."], + ['"limit": 1.5', "limit must be an integer, found a number."], + ['"limit": "5"', "limit must be an integer, found a string."], + ['"limit": 99999999999999999999', "limit is 99999999999999999999; it takes an integer from 1 to 1000."], + ['"offset": -1', "offset is -1; it takes an integer from 0 to 1000."], + ['"autoLimit": 0', "autoLimit is 0; it takes an integer from 1 to 1000."], + ])("%s is refused", (pair, message) => { + expect(refused(bm25(`{"query": "x", ${pair}}`)).message).toBe(message); + }); + + test("limit plus offset is at most 1,000, with the default limit counted", () => { + expect(refused(bm25('{"query": "x", "offset": 995}'))).toEqual({ + phase: 0, + key: "limit", + message: "limit plus offset is 1005, above the bound of 1000 rows.", + }); + expect(text(searchOf(bm25('{"query": "x", "limit": 500, "offset": 500}')).offset)).toBe("500"); + }); +}); + +describe("hybrid (W3)", () => { + test("at alpha 0 is a keyword-only search, with its own keys", () => { + const search = searchOf( + hybrid( + '{"query": "vector", "alpha": 0, "fusionType": "relativeScore", "maxVectorDistance": 0.5, "targetVector": "text"}', + ), + ); + expect({ + op: search.op, + fusionType: search.fusionType, + maxVectorDistance: text(search.maxVectorDistance), + targetVector: search.targetVector, + }).toEqual({ op: "search_hybrid", fusionType: "relativeScore", maxVectorDistance: "0.5", targetVector: "text" }); + expect(searchOf(hybrid('{"query": "vector", "alpha": 0.0}')).op).toBe("search_hybrid"); + }); + + test("alpha is required, since the server's default is 0.7", () => { + expect(refused(hybrid('{"query": "vector"}'))).toEqual({ + phase: 0, + key: "alpha", + message: "The body needs the key alpha.", + }); + }); + + test("any alpha other than 0 is refused with the sentence naming the model provider", () => { + expect(refused(hybrid('{"query": "vector", "alpha": 0.5}'))).toEqual({ + phase: 0, + key: "alpha", + message: + 'alpha must be 0 in this console: any other value makes Weaviate embed the query text with the collection\'s vectorizer, which sends it to a model provider. Write "alpha": 0 for a keyword-only hybrid search.', + }); + expect(refused(hybrid('{"query": "vector", "alpha": "0"}')).message).toBe( + "alpha must be a number, found a string.", + ); + }); + + test("fusionType, maxVectorDistance and targetVector are checked", () => { + expect(refused(hybrid('{"query": "v", "alpha": 0, "fusionType": "rankedFusion"}')).message).toBe( + 'fusionType takes one of ranked, relativeScore, not "rankedFusion".', + ); + expect(refused(hybrid('{"query": "v", "alpha": 0, "maxVectorDistance": "far"}')).message).toBe( + "maxVectorDistance must be a number, found a string.", + ); + expect(refused(hybrid('{"query": "v", "alpha": 0, "targetVector": "a b"}'))).toEqual({ + phase: 0, + key: "targetVector", + message: 'targetVector is "a b", which is not a Weaviate vector name.', + }); + expect(refused(hybrid('{"query": "v", "alpha": 0, "targetVector": ["a"]}')).message).toBe( + "targetVector must be a string, found a list.", + ); + }); +}); + +describe("near-vector", () => { + test("keeps every number as typed", () => { + const search = searchOf(nearVector('{"vector": [0.1, -2, 3e-1], "distance": 0.4}')); + expect(search.vector?.map((entry) => toJsonText(entry))).toEqual(["0.1", "-2", "3e-1"]); + expect(text(search.distance)).toBe("0.4"); + expect(bodyText(nearVector('{"vector": [0.1, -2, 3e-1]}'))).toBe('{"vector":[0.1,-2,3e-1],"limit":10}'); + }); + + test("the vector is one dense list of 1 to 65,536 numbers", () => { + expect(refused(nearVector("{}")).message).toBe("The body needs the key vector."); + expect(refused(nearVector('{"vector": {"a": 1}}')).message).toBe("vector must be a list, found an object."); + expect(refused(nearVector('{"vector": [[0.1], [0.2]]}'))).toEqual({ + phase: 0, + key: "vector", + message: "vector is a list of lists: this console searches with one dense vector, a list of numbers.", + }); + expect(refused(nearVector('{"vector": []}')).message).toBe("vector holds 0 numbers; it takes 1 to 65536."); + const long = `[${new Array(65_537).fill("0").join(",")}]`; + expect(refused(nearVector(`{"vector": ${long}}`)).message).toBe("vector holds 65537 numbers; it takes 1 to 65536."); + expect(refused(nearVector('{"vector": [0.1, "x"]}')).message).toBe("vector[1] must be a number, found a string."); + expect(refused(nearVector('{"vector": [null]}')).message).toBe("vector[0] must be a number, found null."); + }); + + test("certainty is from 0 to 1, and distance and certainty do not go together", () => { + expect(text(searchOf(nearVector('{"vector": [1], "certainty": 1}')).certainty)).toBe("1"); + expect(refused(nearVector('{"vector": [1], "certainty": 1.5}'))).toEqual({ + phase: 0, + key: "certainty", + message: "certainty takes a number from 0 to 1.", + }); + expect(refused(nearVector('{"vector": [1], "certainty": -0.1}')).message).toBe( + "certainty takes a number from 0 to 1.", + ); + expect(refused(nearVector('{"vector": [1], "distance": "near"}')).message).toBe( + "distance must be a number, found a string.", + ); + expect(refused(nearVector('{"vector": [1], "distance": 0.1, "certainty": 0.9}'))).toEqual({ + phase: 0, + key: "distance", + message: "A search takes distance or certainty, not both.", + }); + }); +}); + +describe("near-object", () => { + test("takes an object id, a UUID", () => { + expect(searchOf(nearObject(`{"id": "${UUID}"}`)).id).toBe(UUID); + expect(refused(nearObject('{"id": "42"}'))).toEqual({ + phase: 0, + key: "id", + message: 'id is "42", which is not a UUID: Weaviate\'s object ids are UUIDs.', + }); + expect(refused(nearObject('{"id": 42}')).message).toBe("id must be a string, found a number."); + }); +}); diff --git a/tests/unit/db/weaviate/rest-client.test.ts b/tests/unit/db/weaviate/rest-client.test.ts new file mode 100644 index 0000000000..8813ddbc71 --- /dev/null +++ b/tests/unit/db/weaviate/rest-client.test.ts @@ -0,0 +1,443 @@ +/** + * The Weaviate REST client over a recording transport (#1566 spec 3.2, W7): what it hands the shared transport, the + * nineteen routes it builds and nothing else, and every refusal it raises before the wire: an operation outside the + * table, a path parameter that would leave its segment, an undeclared parameter or query key, a body on a GET and + * none on a POST. A route table that is not exactly the operations of `WEAVIATE_OPS` fails when the client is built. + */ +import { describe, expect, test } from "bun:test"; +import { QueryError } from "@/lib/db/errors"; +import { TransportError } from "@/lib/db/http/node-transport"; +import { + WEAVIATE_OPS, + type WeaviateOp, + type WeaviateRequest, + type WeaviateRouteTemplates, +} from "@/lib/db/providers/vector/weaviate/client"; +import { buildWeaviateConnectionOptions } from "@/lib/db/providers/vector/weaviate/connection-options"; +import { createRestWeaviateClient } from "@/lib/db/providers/vector/weaviate/rest-client"; +import { WEAVIATE_CLIENT_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; +import type { DatabaseConnection } from "@/lib/types"; +import { expectCalls } from "../../../helpers/call-log"; +import { okAnswer, type RecordedAnswer, recordingWeaviateTransport } from "../../../helpers/weaviate-wire"; + +// A named placeholder, never a realistic value: a credential in a test fixture is a stand-in. +const TEST_PASSWORD = "password"; +const ID = "00000000-0000-0000-0000-000000000001"; + +const OPTIONS = buildWeaviateConnectionOptions( + { + id: "c1", + name: "Weaviate", + type: "weaviate", + host: "127.0.0.1", + port: 8080, + password: TEST_PASSWORD, + createdAt: new Date(0), + } as unknown as DatabaseConnection, + { executionReadOnly: false, queryTimeout: 30_000 }, +); + +const signal = () => new AbortController().signal; + +/** Each operation's parameters and body, and the request line they make. */ +const SAMPLES: Readonly; body?: string; line: string }>> = { + meta: { params: {}, line: "GET /v1/meta" }, + schema: { params: {}, line: "GET /v1/schema" }, + collection: { params: { collection: "Article" }, line: "GET /v1/schema/Article" }, + shards: { params: { collection: "Article" }, line: "GET /v1/schema/Article/shards" }, + tenants: { params: { collection: "Article" }, line: "GET /v1/schema/Article/tenants" }, + tenant: { params: { collection: "Article", tenant: "tenantA" }, line: "GET /v1/schema/Article/tenants/tenantA" }, + aliases: { params: {}, line: "GET /v1/aliases" }, + alias: { params: { alias: "Docs" }, line: "GET /v1/aliases/Docs" }, + nodes: { params: {}, line: "GET /v1/nodes" }, + collection_nodes: { params: { collection: "Article" }, line: "GET /v1/nodes/Article" }, + objects: { params: {}, line: "GET /v1/objects" }, + object: { params: { collection: "Article", id: ID }, line: `GET /v1/objects/Article/${ID}` }, + search_bm25: { params: { collection: "Article" }, body: "{}", line: "POST /v1/search/Article/bm25" }, + search_hybrid: { params: { collection: "Article" }, body: "{}", line: "POST /v1/search/Article/hybrid" }, + search_near_vector: { + params: { collection: "Article" }, + body: "{}", + line: "POST /v1/search/Article/near-vector", + }, + search_near_object: { + params: { collection: "Article" }, + body: "{}", + line: "POST /v1/search/Article/near-object", + }, + aggregate: { params: { collection: "Article" }, body: "{}", line: "POST /v1/aggregate/Article" }, + ready: { params: {}, line: "GET /v1/.well-known/ready" }, + graphql: { params: {}, body: '{"query":"{Get{Article{title}}}"}', line: "POST /v1/graphql" }, +}; + +function client(answer?: RecordedAnswer, routes: WeaviateRouteTemplates = WEAVIATE_CLIENT_ROUTES) { + const wire = recordingWeaviateTransport(answer); + return { wire, weaviate: createRestWeaviateClient(OPTIONS, routes, wire.factory) }; +} + +const request = (op: WeaviateOp, overrides: Partial = {}): WeaviateRequest => ({ + op, + params: SAMPLES[op].params, + query: {}, + ...(SAMPLES[op].body === undefined ? {} : { body: SAMPLES[op].body }), + ...overrides, +}); + +async function refused(run: () => Promise): Promise { + try { + await run(); + } catch (error) { + expect(error).toBeInstanceOf(QueryError); + expect(String((error as QueryError).provider)).toBe("weaviate"); + return error as QueryError; + } + throw new Error("the client sent a request this case must refuse"); +} + +describe("what the client hands the transport", () => { + test("one transport per client, built from the connection's options, with the bearer header set once", () => { + const { wire } = client(); + expect(wire.built).toEqual([ + { + origin: { scheme: "http", host: "127.0.0.1", port: 8080 }, + tls: null, + maxSockets: 4, + headers: { authorization: `Bearer ${TEST_PASSWORD}` }, + reportsUnreachable: true, + }, + ]); + }); + + test("a request carries the caller's signal, the response cap and the body as written", async () => { + const { wire, weaviate } = client(); + const controller = new AbortController(); + const body = '{"query":"alpha","limit":9007199254740993}'; + await weaviate.send(request("search_bm25", { body }), controller.signal); + expect(wire.requests).toEqual([ + { + method: "POST", + url: "http://127.0.0.1:8080/v1/search/Article/bm25", + body, + signal: controller.signal, + maxResponseBytes: 16_777_216, + }, + ]); + expect(wire.requests[0].signal).toBe(controller.signal); + }); + + test("a GET carries no body property at all", async () => { + const { wire, weaviate } = client(); + await weaviate.send(request("meta"), signal()); + expect(Object.hasOwn(wire.requests[0], "body")).toBe(false); + }); + + test("close closes the transport", () => { + const { wire, weaviate } = client(); + weaviate.close(); + expect(wire.closed()).toBe(1); + }); +}); + +describe("the answer is data, whatever its status, and nothing is sent twice", () => { + test.each([200, 401, 403, 404, 422, 429, 500, 503])("a %d answer is handed back as it arrived", async (status) => { + const answer = { status, contentType: "application/json", retryAfter: status === 429 ? "7" : null, text: "{}" }; + const { wire, weaviate } = client(() => answer); + expect(await weaviate.send(request("schema"), signal())).toEqual(answer); + expect(wire.calls).toHaveLength(1); + }); + + test("a property the transport adds does not cross the seam", async () => { + const { weaviate } = client(() => ({ ...okAnswer("{}"), extra: 1 }) as never); + expect(Object.keys(await weaviate.send(request("meta"), signal())).sort()).toEqual([ + "contentType", + "retryAfter", + "status", + "text", + ]); + }); + + test.each([...WEAVIATE_OPS])("a lost answer to %s is reported as lost after exactly one request", async (op) => { + const lost = new TransportError("network", "The request failed before a complete response arrived (ECONNRESET)"); + const { wire, weaviate } = client(() => { + throw lost; + }); + await expect(weaviate.send(request(op), signal())).rejects.toBe(lost); + expect(wire.calls).toHaveLength(1); + }); +}); + +describe("the client builds exactly the routes of the table (W7)", () => { + test("the seam names nineteen operations, each once", () => { + expect(WEAVIATE_OPS).toHaveLength(19); + expect(new Set(WEAVIATE_OPS).size).toBe(19); + expect(Object.keys(SAMPLES).sort()).toEqual([...WEAVIATE_OPS].sort()); + }); + + test.each([...WEAVIATE_OPS])("%s is its one method and path", async (op) => { + const { wire, weaviate } = client(); + await weaviate.send(request(op), signal()); + expectCalls(wire, [{ method: SAMPLES[op].line, args: [SAMPLES[op].body ?? null] }]); + }); + + test("only GET and POST are ever sent, and every path is under /v1/", async () => { + const { wire, weaviate } = client(); + for (const op of WEAVIATE_OPS) { + // oxlint-disable-next-line no-await-in-loop -- one request at a time, in table order. + await weaviate.send(request(op), signal()); + } + expect([...new Set(wire.requests.map((sent) => sent.method))].sort()).toEqual(["GET", "POST"]); + for (const call of wire.calls) expect(call.method.split(" ")[1]).toStartWith("/v1/"); + }); + + test.each([ + ["one operation fewer", (table: Record) => delete table.ready], + [ + "one operation more", + (table: Record) => (table.backups = { method: "GET", path: "/v1/backups", query: [] }), + ], + [ + "another operation in place of one", + (table: Record) => { + delete table.ready; + table.users = { method: "GET", path: "/v1/users/db", query: [] }; + }, + ], + [ + "a method outside GET and POST", + (table: Record) => + (table.collection = { method: "DELETE", path: "/v1/schema/{collection}", query: [] }), + ], + [ + "a path that is not absolute", + (table: Record) => (table.meta = { method: "GET", path: "v1/meta", query: [] }), + ], + [ + "a path with a dot segment", + (table: Record) => (table.meta = { method: "GET", path: "/v1/../users", query: [] }), + ], + [ + "a path with a single dot segment", + (table: Record) => (table.meta = { method: "GET", path: "/v1/./meta", query: [] }), + ], + [ + "a path with an encoded byte", + (table: Record) => (table.meta = { method: "GET", path: "/v1/%2e%2e", query: [] }), + ], + [ + "a path with a query string", + (table: Record) => (table.meta = { method: "GET", path: "/v1/meta?x=1", query: [] }), + ], + [ + "a path with an empty segment", + (table: Record) => (table.meta = { method: "GET", path: "/v1//meta", query: [] }), + ], + [ + "a query key that is not a plain word", + (table: Record) => (table.meta = { method: "GET", path: "/v1/meta", query: ["a&b"] }), + ], + ])("a route table with %s is refused when the client is built, before any transport", (_name, change) => { + const table: Record = { ...WEAVIATE_CLIENT_ROUTES }; + change(table); + const wire = recordingWeaviateTransport(); + expect(() => createRestWeaviateClient(OPTIONS, table as unknown as WeaviateRouteTemplates, wire.factory)).toThrow( + TypeError, + ); + expect(wire.built).toHaveLength(0); + }); + + test("the table's own refusal sentences name the operation", () => { + const build = (change: Record) => () => + createRestWeaviateClient( + OPTIONS, + { ...WEAVIATE_CLIENT_ROUTES, ...change } as unknown as WeaviateRouteTemplates, + recordingWeaviateTransport().factory, + ); + expect(build({ meta: { method: "PUT", path: "/v1/meta", query: [] } })).toThrow( + "The Weaviate route table gives meta a method that is neither GET nor POST", + ); + expect(build({ meta: { method: "GET", path: "v1/meta", query: [] } })).toThrow( + "The Weaviate route table gives meta a path that is not absolute", + ); + expect(build({ meta: { method: "GET", path: "/v1/Meta", query: [] } })).toThrow( + "The Weaviate route table gives meta a path segment this client cannot read", + ); + expect(build({ meta: { method: "GET", path: "/v1/meta", query: ["Limit"] } })).toThrow( + "The Weaviate route table gives meta a query key this client cannot read", + ); + expect(build({ backups: { method: "GET", path: "/v1/backups", query: [] } })).toThrow( + "The Weaviate route table must name exactly the 19 operations", + ); + }); + + test("an operation outside the table is refused with zero requests", async () => { + const { wire, weaviate } = client(); + for (const op of ["backups", "users", "toString", "__proto__"]) { + // oxlint-disable-next-line no-await-in-loop -- one refusal at a time. + const error = await refused(() => weaviate.send({ op: op as WeaviateOp, params: {}, query: {} }, signal())); + expect(error.message).toBe("The request names an operation this client does not send, so nothing was sent."); + } + expectCalls(wire, []); + }); +}); + +describe("a path parameter is refused before it reaches a path, and every other character is encoded", () => { + const INVALID = + "A name in the request path is empty, `.` or `..`, holds `/` or a NUL character, as written or once percent-decoded, or is longer than 255 characters, so nothing was sent."; + + test.each([ + ["the empty name", ""], + ["a single dot", "."], + ["two dots", ".."], + ["a slash", "a/b"], + ["a NUL", "a\u0000b"], + ["256 characters", "a".repeat(256)], + ["a value that is not text", 7 as unknown as string], + ["two percent-encoded dots", "%2e%2e"], + ["one upper-case percent-encoded dot and a dot", "%2E."], + ["one percent-encoded dot", "%2e"], + ["a percent-encoded slash", "a%2fb"], + ["a percent-encoded NUL", "a%00b"], + ["percent-encoded dot segments toward another route", "..%2f..%2fusers"], + ])("%s is refused with zero requests", async (_what, name) => { + const { wire, weaviate } = client(); + const error = await refused(() => weaviate.send(request("collection", { params: { collection: name } }), signal())); + expect(error.message).toBe(INVALID); + expectCalls(wire, []); + }); + + test("every parameter of a two-parameter route is held to the rule", async () => { + const { wire, weaviate } = client(); + for (const [op, params] of [ + ["object", { collection: "Article", id: ".." }], + ["object", { collection: "..", id: ID }], + ["tenant", { collection: "Article", tenant: "a/b" }], + ] as const satisfies readonly (readonly [WeaviateOp, Readonly>])[]) { + // oxlint-disable-next-line no-await-in-loop -- one refusal at a time. + expect((await refused(() => weaviate.send(request(op, { params }), signal()))).message).toBe(INVALID); + } + expectCalls(wire, []); + }); + + test("a parameter the request leaves out, or holds only by inheritance, is refused the same way", async () => { + const { wire, weaviate } = client(); + await refused(() => weaviate.send({ op: "object", params: { collection: "Article" }, query: {} }, signal())); + await refused(() => + weaviate.send({ op: "collection", params: Object.create({ collection: "Article" }), query: {} }, signal()), + ); + expectCalls(wire, []); + }); + + test("a parameter the route's template does not declare is refused", async () => { + const { wire, weaviate } = client(); + const error = await refused(() => + weaviate.send(request("schema", { params: { collection: "Article" } }), signal()), + ); + expect(error.message).toBe("The request names a path parameter its route does not declare, so nothing was sent."); + await refused(() => weaviate.send(request("collection", { params: { collection: "Article", x: "y" } }), signal())); + expectCalls(wire, []); + }); + + test.each([ + ["a:b", "/v1/schema/a%3Ab"], + ["%zz", "/v1/schema/%25zz"], + ["%zz%2e", "/v1/schema/%25zz%252e"], + ["100%", "/v1/schema/100%25"], + ["a b", "/v1/schema/a%20b"], + ["a?b#c", "/v1/schema/a%3Fb%23c"], + ["a".repeat(255), `/v1/schema/${"a".repeat(255)}`], + ["...", "/v1/schema/..."], + ["café", "/v1/schema/caf%C3%A9"], + ["a\\b", "/v1/schema/a%5Cb"], + ])("the name %j reaches the server as one segment, in exactly one request", async (name, path) => { + const { wire, weaviate } = client(); + await weaviate.send(request("collection", { params: { collection: name } }), signal()); + expectCalls(wire, [{ method: `GET ${path}`, args: [null] }]); + }); + + test("a name that is not well-formed Unicode is refused by name, never thrown as a URIError", async () => { + const { wire, weaviate } = client(); + const error = await refused(() => + weaviate.send(request("collection", { params: { collection: "a\ud800b" } }), signal()), + ); + expect(error.message).toBe("A name in the request path is not well-formed Unicode text, so nothing was sent."); + expectCalls(wire, []); + }); + + test("the 255 is counted in characters", async () => { + const { wire, weaviate } = client(); + await weaviate.send(request("collection", { params: { collection: "\u{1F600}".repeat(255) } }), signal()); + await refused(() => + weaviate.send(request("collection", { params: { collection: "\u{1F600}".repeat(256) } }), signal()), + ); + expect(wire.calls).toHaveLength(1); + }); +}); + +describe("only the query keys a route declares", () => { + test("declared keys are sent, encoded, in the order given", async () => { + const { wire, weaviate } = client(); + await weaviate.send( + request("objects", { query: { class: "Article", limit: "25", after: ID, include: "vector,classification" } }), + signal(), + ); + await weaviate.send(request("shards", { query: { tenant: "tenant A" } }), signal()); + await weaviate.send(request("nodes", { query: { output: "verbose" } }), signal()); + expectCalls(wire, [ + { + method: `GET /v1/objects?class=Article&limit=25&after=${ID}&include=vector%2Cclassification`, + args: [null], + }, + { method: "GET /v1/schema/Article/shards?tenant=tenant+A", args: [null] }, + { method: "GET /v1/nodes?output=verbose", args: [null] }, + ]); + }); + + test.each([...WEAVIATE_OPS])("%s never carries an undeclared key, and the sentence never names it", async (op) => { + const { wire, weaviate } = client(); + for (const key of ["api_key", "consistency_level", "node_name", "x-openai-api-key"]) { + // oxlint-disable-next-line no-await-in-loop -- one refusal at a time. + const error = await refused(() => weaviate.send(request(op, { query: { [key]: "x" } }), signal())); + expect(error.message).toBe("The request carries a query key its route does not declare, so nothing was sent."); + expect(error.message).not.toContain(key); + } + expectCalls(wire, []); + }); + + test("a query value that is not text is refused", async () => { + const { wire, weaviate } = client(); + const error = await refused(() => + weaviate.send(request("objects", { query: { limit: 25 as unknown as string } }), signal()), + ); + expect(error.message).toBe("The request carries a query value that is not text, so nothing was sent."); + expectCalls(wire, []); + }); +}); + +describe("a GET takes no body and a POST takes one", () => { + test.each(WEAVIATE_OPS.filter((op) => WEAVIATE_CLIENT_ROUTES[op].method === "GET"))( + "a body on %s is refused with zero requests", + async (op) => { + const { wire, weaviate } = client(); + for (const body of ["{}", ""]) { + // oxlint-disable-next-line no-await-in-loop -- one refusal at a time. + const error = await refused(() => weaviate.send(request(op, { body }), signal())); + expect(error.message).toBe("The request gives a body to a route that takes none, so nothing was sent."); + } + expectCalls(wire, []); + }, + ); + + test.each(WEAVIATE_OPS.filter((op) => WEAVIATE_CLIENT_ROUTES[op].method === "POST"))( + "%s with no JSON text is refused with zero requests", + async (op) => { + const { wire, weaviate } = client(); + const { body: _body, ...bodiless } = request(op); + for (const sent of [bodiless, { ...bodiless, body: { query: "x" } as unknown as string }]) { + // oxlint-disable-next-line no-await-in-loop -- one refusal at a time. + const error = await refused(() => weaviate.send(sent, signal())); + expect(error.message).toBe("The request gives a POST route no JSON text, so nothing was sent."); + } + expectCalls(wire, []); + }, + ); +}); diff --git a/tests/unit/db/weaviate/results.test.ts b/tests/unit/db/weaviate/results.test.ts new file mode 100644 index 0000000000..a9970fa4e9 --- /dev/null +++ b/tests/unit/db/weaviate/results.test.ts @@ -0,0 +1,476 @@ +/** + * A Weaviate answer to a `QueryResult` (#1566 spec 5.2, 5.6, 5.7, 3.6), over answers the seeded servers gave and + * hand-written ones in their shape: one row per entry for the metadata reads, per object for the object reads with + * their vectors and times, per hit for a search with the same columns on REST and GraphQL, one count row or one per + * group for an aggregate; the GraphQL int32 null marked, a long text cut with a marker, and the byte budget dropping + * whole rows with a warning. + */ +import { describe, expect, test } from "bun:test"; +import { taggedNumber } from "@/lib/db/console/tagged-json"; +import { QueryError } from "@/lib/db/errors"; +import type { WeaviateConsoleOp } from "@/lib/db/providers/vector/weaviate/client"; +import type { WeaviateSearchModel } from "@/lib/db/providers/vector/weaviate/request"; +import { type WeaviateResultShape, weaviateResult } from "@/lib/db/providers/vector/weaviate/results"; +import { readWeaviateClass, weaviateCollectionFacts } from "@/lib/db/providers/vector/weaviate/schema"; +import { capturedText } from "../../../helpers/weaviate-surface"; + +const OPTIONS = { executionTime: 3 }; +const factsOf = (name: string) => + weaviateCollectionFacts( + readWeaviateClass(JSON.parse(capturedText("weaviate/reads.json", "GET", `/v1/schema/${name}`)), name), + ); + +function model(over: Partial = {}): WeaviateSearchModel { + return { + op: "search_bm25", + collection: "Article", + tenant: null, + where: null, + limit: null, + offset: null, + autoLimit: null, + consistencyLevel: null, + returnProperties: null, + returnMetadata: [], + query: null, + queryProperties: null, + fusionType: null, + maxVectorDistance: null, + vector: null, + id: null, + targetVector: null, + distance: null, + certainty: null, + groupBy: null, + ...over, + }; +} + +function shape(op: WeaviateConsoleOp, over: Partial = {}): WeaviateResultShape { + return { op, facts: null, path: null, model: null, limit: null, warnings: [], ...over }; +} + +const row = (value: Record) => Object.assign(Object.create(null), value); + +describe("the metadata reads", () => { + test("meta, a definition, a tenant, an alias: one row, one column per top-level key in order", () => { + const result = weaviateResult( + capturedText("weaviate/reads.json", "GET", "/v1/aliases/Articles"), + shape("alias"), + OPTIONS, + ); + expect(result).toEqual({ + rows: [row({ alias: "Articles", class: "Article" })], + fields: ["alias", "class"], + rowCount: 1, + executionTime: 3, + columnTypes: {}, + }); + expect(Object.getPrototypeOf(result.rows[0])).toBeNull(); + const meta = weaviateResult(capturedText("weaviate/reads.json", "GET", "/v1/meta"), shape("meta"), OPTIONS); + expect(meta.fields).toEqual(["grpcMaxMessageSize", "hostname", "license", "modules", "version"]); + }); + + test("the lists: schema classes, shards, tenants, aliases, nodes; a key absent on one row is null", () => { + const tenants = weaviateResult( + capturedText("weaviate/reads.json", "GET", "/v1/schema/TenantNotes/tenants"), + shape("tenants"), + OPTIONS, + ); + // Weaviate's own order differs between two identical reads, so the rows are compared by name. + const byName = (a: Record, b: Record) => + String(a.name).localeCompare(String(b.name)); + expect([...tenants.rows].sort(byName)).toEqual([ + row({ activityStatus: "HOT", name: "acme" }), + row({ activityStatus: "HOT", name: "globex" }), + row({ activityStatus: "COLD", name: "initech" }), + ]); + const mixed = weaviateResult('[{"a":1},{"b":2}]', shape("shards"), OPTIONS); + expect(mixed.fields).toEqual(["a", "b"]); + expect(mixed.rows).toEqual([row({ a: 1, b: null }), row({ a: null, b: 2 })]); + expect( + weaviateResult(capturedText("weaviate/reads.json", "GET", "/v1/schema"), shape("schema"), OPTIONS).rowCount, + ).toBe(7); + expect( + weaviateResult(capturedText("weaviate/reads.json", "GET", "/v1/aliases"), shape("aliases"), OPTIONS).rowCount, + ).toBe(1); + expect( + weaviateResult(capturedText("weaviate/reads.json", "GET", "/v1/nodes"), shape("nodes"), OPTIONS).rowCount, + ).toBe(1); + expect( + weaviateResult( + capturedText("weaviate/reads.json", "GET", "/v1/nodes/Article?output=verbose"), + shape("collection_nodes"), + OPTIONS, + ).rowCount, + ).toBe(1); + }); + + test("an empty or absent list still names a column", () => { + for (const [text, op] of [ + ['{"classes":[]}', "schema"], + ['{"classes":null}', "schema"], + ["[]", "tenants"], + ["{}", "aliases"], + ] as const) { + const result = weaviateResult(text, shape(op), OPTIONS); + expect(result.fields, text).toEqual(["$id"]); + expect(result.rows).toEqual([]); + } + }); + + test("an answer that is not JSON, not a list, or holds a non-object entry is refused", () => { + expect(() => weaviateResult("", shape("meta"), OPTIONS)).toThrow( + new QueryError("Weaviate answered with a body that is not JSON.", "weaviate"), + ); + expect(() => weaviateResult('{"classes":{}}', shape("schema"), OPTIONS)).toThrow( + "Weaviate answered with no list of classes.", + ); + expect(() => weaviateResult('{"nodes":"x"}', shape("nodes"), OPTIONS)).toThrow( + "Weaviate answered with no list of nodes.", + ); + expect(() => weaviateResult("[1]", shape("shards"), OPTIONS)).toThrow( + "Weaviate answered with no object where one was expected.", + ); + }); +}); + +describe("the object reads", () => { + test("an object list: $id, the declared properties first, the vector, the times in epoch ms", () => { + const result = weaviateResult( + capturedText("weaviate/reads.json", "GET", "/v1/objects?class=Article&limit=2&include=vector"), + shape("objects", { facts: factsOf("Article"), limit: 2 }), + OPTIONS, + ); + const declared = factsOf("Article").plainProperties.filter((name) => result.fields.includes(name)); + expect(result.fields.slice(0, declared.length + 1)).toEqual(["$id", ...declared]); + expect(result.fields.slice(-3)).toEqual(["$vector", "$creationTime", "$lastUpdateTime"]); + expect(result.vectorColumns).toEqual({ $vector: { kind: "dense", dtype: "float32", dimension: 16 } }); + expect(result.columnTypes).toEqual({ $id: "uuid", $creationTime: "epoch ms", $lastUpdateTime: "epoch ms" }); + expect(result.rows[0]?.$creationTime).toBe(1792754764912); + }); + + test("a list that fills its limit says how to read the next page; one that does not, nothing", () => { + const text = capturedText("weaviate/reads.json", "GET", "/v1/objects?class=Author&limit=2"); + const full = weaviateResult(text, shape("objects", { limit: 2 }), OPTIONS); + const last = full.rows[1]?.$id as string; + expect(full.warnings).toEqual([{ message: `More objects may follow: add &after=${last} to read the next 2.` }]); + expect(full.vectorColumns).toBeUndefined(); + expect(weaviateResult(text, shape("objects", { limit: 5 }), OPTIONS).warnings).toBeUndefined(); + expect(weaviateResult('{"objects":[]}', shape("objects", { limit: 0 }), OPTIONS).warnings).toBeUndefined(); + }); + + test("a list that already names after is told to set it, not to add a second", () => { + const text = capturedText("weaviate/reads.json", "GET", "/v1/objects?class=Author&limit=2"); + const full = weaviateResult(text, shape("objects", { limit: 2, afterGiven: true }), OPTIONS); + expect(full.warnings).toEqual([ + { message: `More objects may follow: set after=${full.rows[1]?.$id as string} to read the next 2.` }, + ]); + }); + + test("named vectors are one column each, with their own dimension", () => { + const result = weaviateResult( + capturedText("weaviate/reads.json", "GET", "/v1/objects?class=Product&limit=1&include=vector"), + shape("objects", { facts: factsOf("Product"), limit: 1 }), + OPTIONS, + ); + expect(result.vectorColumns).toEqual({ + "$vector.image": { kind: "dense", dtype: "float32", dimension: 8 }, + "$vector.text": { kind: "dense", dtype: "float32", dimension: 16 }, + }); + }); + + test("one object by id is one row; an empty unnamed vector or a non-list named one is no column", () => { + const one = weaviateResult( + JSON.stringify({ id: "a", properties: { x: 1 }, vector: [], vectors: { v: "x", w: [1, 2] } }), + shape("object"), + OPTIONS, + ); + expect(one.fields).toEqual(["$id", "x", "$vector.w"]); + expect(one.rows).toEqual([row({ $id: "a", x: 1, "$vector.w": [1, 2] })]); + expect(one.columnTypes).toEqual({ $id: "uuid" }); + }); + + test("an object with no id is refused", () => { + expect(() => weaviateResult('{"properties":{}}', shape("object"), OPTIONS)).toThrow( + "Weaviate answered an object with no id.", + ); + }); +}); + +describe("the searches", () => { + test("REST and GraphQL answer the same columns; GraphQL's times are numbers too", () => { + const facts = factsOf("Article"); + const asked = model({ returnProperties: ["title"], returnMetadata: ["distance", "creationTime"] }); + const rest = weaviateResult( + JSON.stringify({ + results: [{ id: "a", properties: { title: "t" }, metadata: { distance: 0.25, creationTime: 1792754764912 } }], + }), + shape("search_near_vector", { facts, path: "rest", model: asked }), + OPTIONS, + ); + const graphql = weaviateResult( + JSON.stringify({ + data: { + Get: { + Article: [{ title: "t", _additional: { id: "a", distance: 0.25, creationTimeUnix: "1792754764912" } }], + }, + }, + }), + shape("search_near_vector", { facts, path: "graphql", model: asked }), + OPTIONS, + ); + expect(rest.fields).toEqual(["$id", "title", "$distance", "$creationTime"]); + expect(graphql.fields).toEqual(rest.fields); + expect(graphql.rows).toEqual(rest.rows); + expect(rest.columnTypes).toEqual({ + $id: "uuid", + $distance: "distance, lower is closer", + $creationTime: "epoch ms", + }); + }); + + test("with no property named, every plain property, then any the answer adds; a missing value is null", () => { + const facts = factsOf("Author"); + const result = weaviateResult( + JSON.stringify({ results: [{ id: "a", properties: { name: "n", extra: 1 } }, { id: "b" }] }), + shape("search_bm25", { facts, path: "rest", model: model({ collection: "Author" }) }), + OPTIONS, + ); + expect(result.fields).toEqual(["$id", ...facts.plainProperties, "extra"]); + expect(result.rows[1]).toEqual(row({ $id: "b", name: null, country: null, extra: null })); + }); + + test("a GraphQL null in an int column is marked as maybe outside int32; REST's never is", () => { + const facts = factsOf("EdgeValues"); + const text = + '{"data":{"Get":{"EdgeValues":[{"_additional":{"id":"08f3aa7e"},"big":null,"label":"9007199254740991"}]}}}'; + const graphql = weaviateResult( + text, + shape("search_bm25", { + facts, + path: "graphql", + model: model({ collection: "EdgeValues", returnProperties: ["label", "big"] }), + warnings: [{ message: "Answered via GraphQL." }], + }), + OPTIONS, + ); + expect(graphql.warnings).toEqual([ + { message: "Answered via GraphQL." }, + { + message: + "GraphQL answers null for an int outside the 32-bit range, so a null in big may be such a value; Weaviate 1.39.7 and later answer it over REST.", + }, + ]); + const rest = weaviateResult( + '{"results":[{"id":"08f3aa7e","properties":{"big":null}}]}', + shape("search_bm25", { + facts, + path: "rest", + model: model({ collection: "EdgeValues", returnProperties: ["big"] }), + }), + OPTIONS, + ); + expect(rest.warnings).toBeUndefined(); + }); + + test("an empty near-vector result on a compressed index says a wrong vector length looks the same", () => { + const facts = { ...factsOf("Article"), vectors: [{ ...factsOf("Article").vectors[0], quantization: "pq" }] }; + const empty = weaviateResult( + '{"results":[]}', + shape("search_near_vector", { facts, path: "rest", model: model({ op: "search_near_vector" }) }), + OPTIONS, + ); + expect(empty.warnings?.[0]?.message).toStartWith("No results. The vector index is pq-compressed"); + const uncompressed = weaviateResult( + '{"results":[]}', + shape("search_near_vector", { + facts: factsOf("Article"), + path: "rest", + model: model({ op: "search_near_vector" }), + }), + OPTIONS, + ); + expect(uncompressed.warnings).toBeUndefined(); + const otherVector = weaviateResult( + '{"results":[]}', + shape("search_near_vector", { + facts, + path: "rest", + model: model({ op: "search_near_vector", targetVector: "image" }), + }), + OPTIONS, + ); + expect(otherVector.warnings).toBeUndefined(); + }); + + test("a hit with no id is refused on either path; an absent list is no hit", () => { + const facts = factsOf("Article"); + expect(() => + weaviateResult( + '{"results":[{"properties":{}}]}', + shape("search_bm25", { facts, path: "rest", model: model() }), + OPTIONS, + ), + ).toThrow("Weaviate answered a result with no id."); + expect(() => + weaviateResult( + '{"data":{"Get":{"Article":[{"title":"t"}]}}}', + shape("search_bm25", { facts, path: "graphql", model: model() }), + OPTIONS, + ), + ).toThrow("Weaviate answered a result with no id."); + for (const text of ['{"data":null}', '{"data":{"Get":null}}', "[]"]) { + expect( + weaviateResult(text, shape("search_bm25", { facts, path: "graphql", model: model() }), OPTIONS).rowCount, + ).toBe(0); + } + expect(weaviateResult("[]", shape("search_bm25", { facts, path: "rest", model: model() }), OPTIONS).rowCount).toBe( + 0, + ); + }); + + test("REST hit properties and metadata that are not objects read as none", () => { + const result = weaviateResult( + '{"results":[{"id":"a","properties":"x","metadata":[1]}]}', + shape("search_bm25", { + facts: factsOf("Author"), + path: "rest", + model: model({ returnProperties: [], returnMetadata: ["score"] }), + }), + OPTIONS, + ); + expect(result.rows).toEqual([row({ $id: "a", $score: null })]); + }); +}); + +describe("the aggregate", () => { + const facts = factsOf("Article"); + const count = (text: string, path: "rest" | "graphql", groupBy: string | null = null) => + weaviateResult(text, shape("aggregate", { facts, path, model: model({ op: "aggregate", groupBy }) }), OPTIONS); + + test("one exact count row over either path", () => { + for (const result of [ + count('{"count":500}', "rest"), + count('{"data":{"Aggregate":{"Article":[{"meta":{"count":500}}]}}}', "graphql"), + ]) { + expect(result.fields).toEqual(["count"]); + expect(result.rows).toEqual([row({ count: 500 })]); + expect(result.columnTypes).toEqual({ count: "Int64, exact count" }); + } + }); + + test("one row per group over either path, the group's value under the property's name", () => { + const rest = count( + '{"groups":[{"count":100,"groupedBy":{"value":"alpha"}},{"count":3},"junk"]}', + "rest", + "category", + ); + const graphql = count( + '{"data":{"Aggregate":{"Article":[{"groupedBy":{"value":"alpha"},"meta":{"count":100}},{"meta":{"count":3}},1]}}}', + "graphql", + "category", + ); + for (const result of [rest, graphql]) { + expect(result.fields).toEqual(["category", "count"]); + expect(result.rows).toEqual([row({ category: "alpha", count: 100 }), row({ category: null, count: 3 })]); + } + expect( + count('{"data":{"Aggregate":{"Article":[{"groupedBy":{"value":"x"}}]}}}', "graphql", "category").rows, + ).toEqual([row({ category: "x", count: null })]); + }); + + test("groups that reach their limit say more may exist; fewer say nothing", () => { + // Both paths stop at 100 groups when no limit is given (measured on 1.37.4 and 1.40.2); phase 0 writes it out. + const grouped = (n: number, limit: number) => + weaviateResult( + JSON.stringify({ groups: Array.from({ length: n }, (_, i) => ({ count: 1, groupedBy: { value: `g${i}` } })) }), + shape("aggregate", { + facts, + path: "rest", + model: model({ op: "aggregate", groupBy: "title", limit: taggedNumber(String(limit)) }), + }), + OPTIONS, + ); + expect(grouped(2, 2).warnings).toEqual([ + { message: "Weaviate answered the 2 groups the limit allows; more may exist: raise limit (at most 1000)." }, + ]); + expect(grouped(1, 2).warnings).toBeUndefined(); + }); + + test("an aggregate with no count is refused", () => { + for (const [text, path] of [ + ['{"count":"500"}', "rest"], + ["[]", "rest"], + ['{"data":{"Aggregate":{"Article":[]}}}', "graphql"], + ['{"data":{"Aggregate":null}}', "graphql"], + ['{"data":"x"}', "graphql"], + ] as const) { + expect(() => count(text, path), text).toThrow("Weaviate answered an aggregate with no count."); + } + }); +}); + +describe("the bounds", () => { + test("a text cell past 65,536 characters is cut with a marker, never inside a surrogate pair", () => { + const long = "x".repeat(70_000); + const result = weaviateResult( + JSON.stringify([{ a: long, b: `${"y".repeat(65_535)}😀z` }]), + shape("shards"), + OPTIONS, + ); + expect(result.rows[0]?.a).toBe(`${"x".repeat(65_536)}...[cut: 65536 of 70000 characters shown]`); + expect(result.rows[0]?.b).toBe(`${"y".repeat(65_535)}...[cut: 65535 of 65538 characters shown]`); + expect(result.warnings).toEqual([ + { message: "2 text cells were longer than 65536 characters and are cut, with a marker." }, + ]); + }); + + test("a vector cell is never cut", () => { + const vector = Array.from({ length: 70_000 }, () => 0.5); + const result = weaviateResult(JSON.stringify({ id: "a", vector }), shape("object"), OPTIONS); + expect(result.rows[0]?.$vector).toHaveLength(70_000); + }); + + test("past the byte budget the remaining rows are dropped whole, with a warning and a limited page", () => { + const rows = JSON.stringify([{ a: "x".repeat(40) }, { a: "y".repeat(40) }, { a: "z".repeat(40) }]); + const result = weaviateResult(rows, shape("shards"), { executionTime: 1, budgetBytes: 100 }); + expect(result.rowCount).toBe(2); + expect(result.warnings).toEqual([ + { + message: + "The result reached Studio's 100-byte result budget after 2 rows; the remaining 1 rows are not shown. Lower the limit, or ask for fewer properties.", + }, + ]); + expect(result.pagination).toEqual({ limit: 2, offset: 0, hasMore: false, totalReturned: 2, wasLimited: true }); + const mib = weaviateResult(rows, shape("shards"), { executionTime: 1, budgetBytes: 1_048_576 }); + expect(mib.warnings).toBeUndefined(); + expect(mib.pagination).toBeUndefined(); + }); + + test("a full page the budget cuts names the last row shown for the next page, so no dropped row is skipped", () => { + // Measured on a 3000-object collection: limit=1000 kept 689 rows, and the notice named the 1000th id until fixed. + const objects = ["a", "b", "c"].map((id) => ({ class: "Big", id, properties: { body: id.repeat(40) } })); + const result = weaviateResult(JSON.stringify({ objects }), shape("objects", { limit: 3 }), { + executionTime: 1, + budgetBytes: 150, + }); + expect(result.rows.map((row) => row.$id)).toEqual(["a", "b"]); + expect(result.warnings?.[0]).toEqual({ message: "More objects may follow: add &after=b to read the next 3." }); + }); + + test("the default budget is 8 MiB, named so in the warning", () => { + const cell = "x".repeat(60_000); + const perRow = JSON.stringify({ a: cell }).length; + const kept = Math.floor((8 * 1_048_576) / perRow); + const result = weaviateResult( + JSON.stringify(Array.from({ length: 200 }, () => ({ a: cell }))), + shape("tenants"), + OPTIONS, + ); + expect(result.rowCount).toBe(kept); + expect(result.warnings?.at(-1)?.message).toBe( + `The result reached Studio's 8 MiB result budget after ${kept} rows; the remaining ${200 - kept} rows are not shown. Lower the limit, or ask for fewer properties.`, + ); + }); +}); diff --git a/tests/unit/db/weaviate/routes.test.ts b/tests/unit/db/weaviate/routes.test.ts new file mode 100644 index 0000000000..6d096fdfa3 --- /dev/null +++ b/tests/unit/db/weaviate/routes.test.ts @@ -0,0 +1,256 @@ +/** + * The Weaviate console as data (#1566 spec 5.1, 5.2, 5.7, 3.2, 3.3): the dialect, the 17 read routes in the REST + * reference's order, the client's table of those plus the readiness probe and the GraphQL read, the closed body key + * sets, the refused keys with their reasons, the bounds, and the sentence a route version 1 does not run is refused + * with, naming what the route is and what the console runs. + */ +import { describe, expect, test } from "bun:test"; +import { WEAVIATE_OPS } from "@/lib/db/providers/vector/weaviate/client"; +import { + refusedRouteSentence, + WEAVIATE_BOUNDS, + WEAVIATE_CLIENT_ROUTES, + WEAVIATE_CONSOLE, + WEAVIATE_ENUMS, + WEAVIATE_KEYS, + WEAVIATE_QUERY_KEYS, + WEAVIATE_REFUSED_KEYS, + WEAVIATE_ROUTES, + WEAVIATE_RUNS, +} from "@/lib/db/providers/vector/weaviate/routes"; + +describe("the dialect and the route table", () => { + test("a GET or POST line under /v1/, with // and # comments", () => { + expect(WEAVIATE_CONSOLE).toEqual({ + id: "weaviate", + methods: ["GET", "POST"], + pathPrefix: "/v1/", + shortForm: true, + commentMarkers: ["//", "#"], + bodyComments: true, + maxTextBytes: 1_048_576, + maxDepth: 32, + maxNodes: 4_096, + maxNumericLeaves: 262_144, + maxScalarLeaves: 32_768, + }); + expect(Object.isFrozen(WEAVIATE_CONSOLE)).toBe(true); + }); + + test("17 routes, every one a read, in the REST reference's order", () => { + expect(WEAVIATE_ROUTES.map((route) => `${route.method} ${route.template}`)).toEqual([ + "GET meta", + "GET schema", + "GET schema/{collection}", + "GET schema/{collection}/shards", + "GET schema/{collection}/tenants", + "GET schema/{collection}/tenants/{tenant}", + "GET aliases", + "GET aliases/{alias}", + "GET nodes", + "GET nodes/{collection}", + "GET objects", + "GET objects/{collection}/{id}", + "POST search/{collection}/bm25", + "POST search/{collection}/hybrid", + "POST search/{collection}/near-vector", + "POST search/{collection}/near-object", + "POST aggregate/{collection}", + ]); + expect(WEAVIATE_ROUTES.every((route) => route.class === "read" && Object.isFrozen(route))).toBe(true); + expect(WEAVIATE_ROUTES.map((route): string => route.op)).toEqual(WEAVIATE_OPS.slice(0, 17)); + }); + + test("a GET takes no body; a search requires one, read by its schema; the aggregate body is optional", () => { + const byOp = Object.fromEntries(WEAVIATE_ROUTES.map((route) => [route.op, route])); + for (const route of WEAVIATE_ROUTES.filter((entry) => entry.method === "GET")) { + expect(route.body, route.op).toBe("none"); + expect(route.schema, route.op).toBeNull(); + } + expect(byOp.search_bm25).toMatchObject({ body: "required", schema: "SearchBm25Request" }); + expect(byOp.search_hybrid).toMatchObject({ body: "required", schema: "SearchHybridRequest" }); + expect(byOp.search_near_vector).toMatchObject({ body: "required", schema: "SearchNearVectorRequest" }); + expect(byOp.search_near_object).toMatchObject({ body: "required", schema: "SearchNearObjectRequest" }); + expect(byOp.aggregate).toMatchObject({ body: "optional", schema: "AggregateRequest" }); + }); + + test("the query keys each route declares, and the values each key takes", () => { + const keys = Object.fromEntries(WEAVIATE_ROUTES.map((route) => [route.op, Object.keys(route.query)])); + expect(keys.objects).toEqual(["class", "limit", "after", "offset", "include", "sort", "order", "tenant"]); + expect(keys.object).toEqual(["include", "tenant"]); + expect(keys.shards).toEqual(["tenant"]); + expect(keys.nodes).toEqual(["output"]); + expect(keys.collection_nodes).toEqual(["output"]); + expect(keys.meta).toEqual([]); + expect(WEAVIATE_QUERY_KEYS.include).toEqual({ + kind: "word-list", + words: ["vector", "classification", "interpretation"], + }); + expect(WEAVIATE_QUERY_KEYS.limit).toEqual({ kind: "positive-int" }); + expect(WEAVIATE_QUERY_KEYS.output).toEqual({ kind: "word-list", words: ["minimal", "verbose"] }); + }); + + test("the client's table: every operation, each route under /v1/, then the readiness probe and GraphQL", () => { + expect(Object.keys(WEAVIATE_CLIENT_ROUTES)).toEqual([...WEAVIATE_OPS]); + expect(WEAVIATE_CLIENT_ROUTES.search_near_vector).toEqual({ + method: "POST", + path: "/v1/search/{collection}/near-vector", + query: [], + }); + expect(WEAVIATE_CLIENT_ROUTES.objects.query).toEqual([ + "class", + "limit", + "after", + "offset", + "include", + "sort", + "order", + "tenant", + ]); + expect(WEAVIATE_CLIENT_ROUTES.ready).toEqual({ method: "GET", path: "/v1/.well-known/ready", query: [] }); + expect(WEAVIATE_CLIENT_ROUTES.graphql).toEqual({ method: "POST", path: "/v1/graphql", query: [] }); + expect(Object.values(WEAVIATE_CLIENT_ROUTES).every((route) => route.path.startsWith("/v1/"))).toBe(true); + }); +}); + +describe("the bodies", () => { + test("every search takes the common keys and its own; the required keys", () => { + const common = [ + "where", + "limit", + "offset", + "autoLimit", + "returnProperties", + "returnMetadata", + "tenant", + "consistencyLevel", + ]; + expect(WEAVIATE_KEYS.SearchBm25Request as unknown).toEqual({ + keys: [...common, "query", "queryProperties"], + required: ["query"], + }); + expect(WEAVIATE_KEYS.SearchHybridRequest.required).toEqual(["query", "alpha"]); + expect(WEAVIATE_KEYS.SearchNearVectorRequest.required).toEqual(["vector"]); + expect(WEAVIATE_KEYS.SearchNearObjectRequest.required).toEqual(["id"]); + expect(WEAVIATE_KEYS.AggregateRequest as unknown).toEqual({ + keys: ["where", "tenant", "groupBy", "limit", "returnMetrics"], + required: [], + }); + expect(WEAVIATE_KEYS.WhereFilter.required).toEqual(["operator"]); + }); + + test("the keys that send text to a model are refused with the reason", () => { + expect(WEAVIATE_REFUSED_KEYS.singlePrompt).toBe("generative search sends the results to a model provider"); + expect(WEAVIATE_REFUSED_KEYS.groupedTask).toBe("generative search sends the results to a model provider"); + expect(WEAVIATE_REFUSED_KEYS.rerank).toBe("reranking sends the results to a model provider"); + expect(Object.keys(WEAVIATE_REFUSED_KEYS)).toEqual([ + "singlePrompt", + "groupedTask", + "rerank", + "groupBy", + "numberOfGroups", + "objectsPerGroup", + "returnReferences", + "over", + "objectLimit", + ]); + }); + + test("the enumerations", () => { + expect(WEAVIATE_ENUMS.consistencyLevel).toEqual(["ONE", "QUORUM", "ALL"]); + expect(WEAVIATE_ENUMS.fusionType).toEqual(["ranked", "relativeScore"]); + expect(WEAVIATE_ENUMS.returnMetrics).toEqual(["count"]); + expect(WEAVIATE_ENUMS.returnMetadata).toEqual([ + "distance", + "certainty", + "score", + "explainScore", + "creationTime", + "lastUpdateTime", + ]); + expect(WEAVIATE_ENUMS.operator).toHaveLength(15); + }); +}); + +describe("the bounds", () => { + test("deadlines below Weaviate's 60 s write timeout, the byte budgets, the in-flight bounds", () => { + expect(WEAVIATE_BOUNDS).toMatchObject({ + defaultObjectsLimit: 25, + defaultSearchLimit: 10, + maxRows: 1_000, + transportCapBytes: 16 * 1024 * 1024, + resultBudgetBytes: 8 * 1024 * 1024, + stringCellUnits: 65_536, + metadataDeadlineMs: 10_000, + searchDeadlineMs: 30_000, + perProvider: 4, + perEngine: 16, + queueDepth: 64, + tablesPanelCollections: 200, + sourceTenants: 1_024, + }); + expect(WEAVIATE_BOUNDS.searchDeadlineMs).toBeLessThan(60_000); + }); +}); + +describe("the refusal sentence", () => { + const refused = (method: string, path: string, what: string) => + expect(refusedRouteSentence(method, path)).toBe( + `${method} /v1/${path + .replace(/^\/v1\//, "") + .replace(/^\/+/, "") + .replace(/[?#].*$/, "")} is ${what}, which this console does not run. ${WEAVIATE_RUNS}`, + ); + + test("a route is named by what it is", () => { + refused("POST", "/v1/search/Article/near-text", "a search that sends its text or media to a model provider"); + refused("POST", "/v1/search/Article/near-image", "a search that sends its text or media to a model provider"); + refused("POST", "/v1/graphql", "a GraphQL request, which this console writes for you from a REST search"); + refused("POST", "/v1/batch/objects", "a batch write"); + refused("GET", "/v1/backups/filesystem", "a backup route"); + refused("GET", "/v1/authz/roles", "a user, role or permission route"); + refused("GET", "/v1/users/own-info", "a user, role or permission route"); + refused("GET", "/v1/replication/replicate", "a replication route"); + refused("GET", "/v1/mcp", "the server's MCP endpoint"); + refused("POST", "/v1/tokenize", "a tokenize route"); + refused("POST", "/v1/schema/Article/properties/title/tokenize", "a tokenize route"); + refused("GET", "/v1/.well-known/ready", "a health or readiness route"); + refused("DELETE", "/v1/schema/Article", "a schema, tenant, index or alias change"); + refused("PUT", "/v1/aliases/Articles", "a schema, tenant, index or alias change"); + }); + + test("an object write is named by its method; an object read under another method is not a write", () => { + refused("POST", "/v1/objects", "an object write"); + refused("DELETE", "/v1/objects/Article/9e6866af-ef70-5a5a-9b61-1ae7a41bad0d", "an object write"); + expect(refusedRouteSentence("GET", "/v1/objects/Article/x/y/z")).toBe( + `GET /v1/objects/Article/x/y/z is not a route this console runs. ${WEAVIATE_RUNS}`, + ); + }); + + test("the prefix may be absent, and a query string or fragment is dropped", () => { + refused("GET", "backups?limit=1", "a backup route"); + refused("GET", "//batch#x", "a batch write"); + }); + + test("a method the console does not send, on a route no row names, says it sends GET and POST only", () => { + expect(refusedRouteSentence("PATCH", "/v1/nodes")).toBe( + `PATCH /v1/nodes is not a request this console runs: it sends GET and POST only. ${WEAVIATE_RUNS}`, + ); + }); + + test("anything else is not a route this console runs", () => { + expect(refusedRouteSentence("GET", "/v1/cluster/statistics")).toBe( + `GET /v1/cluster/statistics is not a route this console runs. ${WEAVIATE_RUNS}`, + ); + expect(refusedRouteSentence("GET", "/v1/batch/x/y")).toContain("is a batch write"); + expect(refusedRouteSentence("GET", "/v1/tokenize/extra")).toBe( + `GET /v1/tokenize/extra is not a route this console runs. ${WEAVIATE_RUNS}`, + ); + }); + + test("what the console runs is said after every refusal", () => { + expect(WEAVIATE_RUNS).toBe( + "This console runs Weaviate's read requests only, with GET and POST: the meta, schema, shard, tenant, alias and node reads, object list and read by id, the bm25, hybrid, near-vector and near-object searches, and aggregate counts.", + ); + }); +}); diff --git a/tests/unit/db/weaviate/schema.test.ts b/tests/unit/db/weaviate/schema.test.ts new file mode 100644 index 0000000000..509b950b7e --- /dev/null +++ b/tests/unit/db/weaviate/schema.test.ts @@ -0,0 +1,253 @@ +/** + * A Weaviate class definition read into the tree's columns, the vector family's fields and a console request's facts + * (#1566 spec 4.2, 3.6, 5.6, 6.1), over the definitions the seeded servers answered and hand-written ones in their + * shape: the unnamed vector and named vectors, the compression enabled, a cross-reference typed `ref → Target`, the + * GraphQL selection a geo, phone or object property needs, and the `int` properties whose GraphQL nulls are marked. + */ +import { describe, expect, test } from "bun:test"; +import { QueryError } from "@/lib/db/errors"; +import { + propertyTypeText, + readWeaviateClass, + readWeaviateSchema, + selectionOf, + vectorColumnName, + vectorField, + vectorTypeText, + WEAVIATE_PRIMITIVE_TYPES, + type WeaviateVector, + weaviateCollectionFacts, + weaviateColumns, + weaviateIndexes, +} from "@/lib/db/providers/vector/weaviate/schema"; +import { capturedText } from "../../../helpers/weaviate-surface"; + +const captured = (name: string, file = "weaviate/surface.json") => + readWeaviateClass(JSON.parse(capturedText(file, "GET", `/v1/schema/${name}`)), name); + +const vector = (over: Partial = {}): WeaviateVector => ({ + name: "", + vectorizer: "none", + indexType: "hnsw", + distance: "cosine", + quantization: null, + ...over, +}); + +describe("a class definition", () => { + test("Article: one unnamed vector, every property in schema order, a cross-reference", () => { + const article = captured("Article"); + expect(article.name).toBe("Article"); + expect(article.multiTenant).toBe(false); + expect(article.autoTenantActivation).toBe(false); + expect(article.vectors).toEqual([vector()]); + expect(article.properties.map((property) => property.name)).toEqual([ + "title", + "body", + "category", + "tags", + "wordCount", + "rating", + "published", + "publishedAt", + "location", + ...article.properties.slice(9).map((property) => property.name), + ]); + const references = article.properties.filter((property) => property.reference); + expect(references.length).toBeGreaterThan(0); + expect(article.definition).toEqual(JSON.parse(capturedText("weaviate/surface.json", "GET", "/v1/schema/Article"))); + }); + + test("Product: two named vectors, each with its own index type and distance", () => { + expect(captured("Product").vectors.map(({ name, indexType, distance }) => ({ name, indexType, distance }))).toEqual( + [ + { name: "image", indexType: "hnsw", distance: "cosine" }, + { name: "text", indexType: "flat", distance: "dot" }, + ], + ); + }); + + test("the tenancy flags, as declared", () => { + expect(captured("TenantNotes")).toMatchObject({ multiTenant: true, autoTenantActivation: false }); + expect(captured("TenantNotesAuto")).toMatchObject({ multiTenant: true, autoTenantActivation: true }); + expect(readWeaviateClass({ class: "A", multiTenancyConfig: "on" }, "A")).toMatchObject({ + multiTenant: false, + autoTenantActivation: false, + }); + }); + + test("the vectorizer: a module name, the first key of a named vector's, else none", () => { + const definition = readWeaviateClass( + { + class: "V", + vectorizer: "text2vec-openai", + vectorIndexType: "hnsw", + vectorIndexConfig: { distance: "l2-squared", pq: { enabled: false }, bq: { enabled: true } }, + vectorConfig: { + a: { vectorizer: { "text2vec-cohere": {} }, vectorIndexConfig: { sq: { enabled: true } } }, + b: { vectorizer: {}, vectorIndexType: "dynamic", vectorIndexConfig: "x" }, + c: { vectorizer: "" }, + skipped: "not an object", + }, + }, + "V", + ); + expect(definition.vectors).toEqual([ + { name: "", vectorizer: "text2vec-openai", indexType: "hnsw", distance: "l2-squared", quantization: "bq" }, + { name: "a", vectorizer: "text2vec-cohere", indexType: "hnsw", distance: null, quantization: "sq" }, + { name: "b", vectorizer: "none", indexType: "dynamic", distance: null, quantization: null }, + { name: "c", vectorizer: "none", indexType: "hnsw", distance: null, quantization: null }, + ]); + }); + + test("a definition with no vector config has no vector", () => { + expect(readWeaviateClass({ class: "Plain" }, "Plain").vectors).toEqual([]); + }); + + test("properties that are not objects or have no name are skipped; a non-string type word is dropped", () => { + const definition = readWeaviateClass( + { class: "P", properties: [null, { dataType: ["text"] }, { name: "n", dataType: ["int", 7] }, { name: "u" }] }, + "P", + ); + expect(definition.properties).toEqual([ + { name: "n", dataType: ["int"], reference: false, nested: [] }, + { name: "u", dataType: [], reference: false, nested: [] }, + ]); + expect(readWeaviateClass({ class: "Q", properties: "none" }, "Q").properties).toEqual([]); + }); + + test("a definition with no class name is refused, naming what was asked for", () => { + for (const value of [null, [], { class: 1 }, "Article"]) { + expect(() => readWeaviateClass(value, "Article")).toThrow( + new QueryError(`Weaviate's definition of "Article" holds no class name.`, "weaviate"), + ); + } + }); +}); + +describe("the schema", () => { + test("every class, in the server's order; none where it lists none", () => { + expect(readWeaviateSchema({ classes: [{ class: "B" }, { class: "A" }] }).map((entry) => entry.name)).toEqual([ + "B", + "A", + ]); + expect(readWeaviateSchema({ classes: null })).toEqual([]); + expect(readWeaviateSchema({})).toEqual([]); + expect(readWeaviateSchema("not an object")).toEqual([]); + }); + + test("a classes field that is not a list is refused; a nameless class is refused by its index", () => { + expect(() => readWeaviateSchema({ classes: {} })).toThrow("Weaviate's schema holds no classes list."); + expect(() => readWeaviateSchema({ classes: [{ class: "A" }, {}] })).toThrow( + `Weaviate's definition of "class 1" holds no class name.`, + ); + }); +}); + +describe("columns and indexes", () => { + test("$id, the properties typed by Weaviate's word, then the vectors with the dimension an object showed", () => { + const product = captured("Product"); + expect(weaviateColumns(product, new Map([["image", 8]]))).toEqual([ + { name: "$id", type: "uuid", nullable: false, isPrimary: true }, + { name: "name", type: "text", nullable: true, isPrimary: false }, + { name: "price", type: "number", nullable: true, isPrimary: false }, + { name: "sku", type: "uuid", nullable: true, isPrimary: false }, + { name: "$vector.image", type: "Vector(8, cosine, hnsw)", nullable: true, isPrimary: false }, + { name: "$vector.text", type: "Vector(?, dot, flat)", nullable: true, isPrimary: false }, + ]); + expect(weaviateIndexes(product)).toEqual([ + { name: "$vector.image", columns: ["$vector.image"], unique: false }, + { name: "$vector.text", columns: ["$vector.text"], unique: false }, + ]); + }); + + test("a cross-reference is `ref → Target`; a property with no type word is unknown", () => { + expect(propertyTypeText({ name: "r", dataType: ["Author", "Editor"], reference: true, nested: [] })).toBe( + "ref → Author | Editor", + ); + expect(propertyTypeText({ name: "u", dataType: [], reference: false, nested: [] })).toBe("unknown"); + expect(propertyTypeText({ name: "l", dataType: ["text[]"], reference: false, nested: [] })).toBe("text[]"); + }); + + test("the vector's column and type text", () => { + expect(vectorColumnName("")).toBe("$vector"); + expect(vectorColumnName("image")).toBe("$vector.image"); + expect(vectorTypeText(vector({ quantization: "pq" }), 16)).toBe("Vector(16, cosine, hnsw, pq)"); + expect(vectorTypeText(vector({ distance: null }), null)).toBe("Vector(?, distance not declared, hnsw)"); + }); + + test("a vector as the family's dense field: Weaviate's distances mapped, the rest other or opaque", () => { + expect(vectorField(vector({ name: "image" }), 8)).toEqual({ + name: "image", + kind: "dense", + dtype: "float32", + dimension: 8, + metric: "cosine", + nativeMetric: "cosine", + indexKind: "hnsw", + nativeType: "Vector(8, cosine, hnsw)", + }); + const metrics = ["dot", "l2-squared", "manhattan", "hamming", "jaccard"].map( + (distance) => vectorField(vector({ distance }), null).metric, + ); + expect(metrics).toEqual(["dot", "euclidean_squared", "manhattan", "hamming", "other"]); + expect(vectorField(vector({ distance: null }), null).metric).toBeNull(); + expect(vectorField(vector({ indexType: "flat" }), null).indexKind).toBe("flat"); + expect(vectorField(vector({ indexType: "dynamic" }), null).indexKind).toBe("opaque"); + }); +}); + +describe("the GraphQL selection and the facts", () => { + test("a geo coordinate, a phone number and an object property are selected with their fields", () => { + const geo = selectionOf({ name: "location", dataType: ["geoCoordinates"], reference: false, nested: [] }); + expect(geo).toEqual({ name: "location", fields: [{ name: "latitude" }, { name: "longitude" }] }); + const phone = selectionOf({ name: "phone", dataType: ["phoneNumber"], reference: false, nested: [] }); + expect(phone?.fields?.map((field) => field.name)).toEqual([ + "input", + "internationalFormatted", + "countryCode", + "national", + "nationalFormatted", + "valid", + "defaultCountry", + ]); + const nested = { + name: "meta", + dataType: ["object[]"], + reference: false, + nested: [ + { name: "a", dataType: ["text"], reference: false, nested: [] }, + { name: "r", dataType: ["Author"], reference: true, nested: [] }, + ], + }; + expect(selectionOf(nested)).toEqual({ name: "meta", fields: [{ name: "a" }] }); + }); + + test("a cross-reference, and an object with nothing to select, have no selection", () => { + expect(selectionOf({ name: "r", dataType: ["Author"], reference: true, nested: [] })).toBeUndefined(); + expect(selectionOf({ name: "o", dataType: ["object"], reference: false, nested: [] })).toBeUndefined(); + }); + + test("the facts: plain properties in order, the int properties, the references, every selection", () => { + const facts = weaviateCollectionFacts(captured("EdgeValues", "weaviate/reads.json")); + expect(facts.name).toBe("EdgeValues"); + expect(facts.plainProperties).toEqual(["label", "big", "bigs"]); + expect([...facts.intProperties]).toEqual(["big", "bigs"]); + expect([...facts.referenceProperties]).toEqual([]); + expect([...facts.selections.keys()]).toEqual(["label", "big", "bigs"]); + const article = weaviateCollectionFacts(captured("Article")); + expect(article.referenceProperties.size).toBeGreaterThan(0); + for (const name of article.referenceProperties) { + expect(article.plainProperties).not.toContain(name); + expect(article.selections.has(name)).toBe(false); + } + expect(article.selections.get("location")?.fields).toHaveLength(2); + }); + + test("the primitive words are Weaviate's own", () => { + for (const word of ["text", "int", "number", "boolean", "date", "uuid", "geoCoordinates", "phoneNumber", "blob"]) { + expect(WEAVIATE_PRIMITIVE_TYPES.has(word), word).toBe(true); + } + expect(WEAVIATE_PRIMITIVE_TYPES.has("Article")).toBe(false); + }); +}); diff --git a/tests/unit/db/weaviate/source.test.ts b/tests/unit/db/weaviate/source.test.ts new file mode 100644 index 0000000000..0cfc8333db --- /dev/null +++ b/tests/unit/db/weaviate/source.test.ts @@ -0,0 +1,187 @@ +/** + * A Weaviate collection's Source (#1566 spec 4.4, 6.2): two JSON parts, `Schema` the class definition unedited and + * `State` what the collection holds, the aliases pointing at it, then its shards and exact count for a single-tenant + * collection, or its tenant count and the first 1,024 tenants by name for a multi-tenant one, each part cut at the + * caller's bound through the shared helper. + */ +import { describe, expect, test } from "bun:test"; +import { applySourceBound } from "@/lib/db/object-kinds"; +import { readWeaviateClass } from "@/lib/db/providers/vector/weaviate/schema"; +import { + COUNT_NOT_READ, + PER_TENANT_COUNT, + weaviateSourceParts, + weaviateStateDocument, +} from "@/lib/db/providers/vector/weaviate/source"; +import { capturedText, renderedPart } from "../../../helpers/weaviate-surface"; + +const FILE = "weaviate/surface.json"; +const text = (path: string) => capturedText(FILE, "GET", path); +const definitionOf = (name: string) => readWeaviateClass(JSON.parse(text(`/v1/schema/${name}`)), name); +const ALIASES = JSON.parse(text("/v1/aliases")); + +describe("the State part", () => { + test("a single-tenant collection: its aliases, its shards with their statuses, its exact count", () => { + const state = weaviateStateDocument({ + definition: definitionOf("Article"), + aliases: ALIASES, + shards: JSON.parse(text("/v1/schema/Article/shards")), + tenants: null, + count: 500, + }); + expect(state).toEqual({ + multiTenant: false, + aliases: ["Articles"], + shards: [{ name: expect.any(String), status: "READY", vectorQueueSize: 0 }], + objectCount: 500, + objectCountKind: "exact, aggregate meta.count", + }); + expect(Object.keys(state)).toEqual(["multiTenant", "aliases", "shards", "objectCount", "objectCountKind"]); + }); + + test("a count not read says so, with no kind; a shard list that is not one lists none", () => { + const state = weaviateStateDocument({ + definition: definitionOf("Empty"), + aliases: ALIASES, + shards: { shards: [] }, + tenants: null, + count: null, + }); + expect(state).toEqual({ multiTenant: false, aliases: [], shards: [], objectCount: COUNT_NOT_READ }); + }); + + test("a shard entry keeps name and status only, its queue size where it reports one", () => { + const state = weaviateStateDocument({ + definition: definitionOf("Empty"), + aliases: null, + shards: [{ name: "s1", status: "READONLY", per_node_status: { node1: "READONLY" } }, "junk"], + tenants: null, + count: 0, + }); + expect(state.shards).toEqual([{ name: "s1", status: "READONLY" }]); + expect(state.objectCount).toBe(0); + }); + + test("only the aliases that point at this collection, by name", () => { + const aliases = { + aliases: [ + { alias: "Articles", class: "Article" }, + { alias: "Other", class: "Product" }, + { alias: 7, class: "Article" }, + "junk", + ], + }; + const state = weaviateStateDocument({ + definition: definitionOf("Article"), + aliases, + shards: [], + tenants: null, + count: 1, + }); + expect(state.aliases).toEqual(["Articles"]); + for (const none of [null, [], { aliases: "x" }]) { + expect( + weaviateStateDocument({ + definition: definitionOf("Article"), + aliases: none, + shards: [], + tenants: null, + count: 1, + }).aliases, + ).toEqual([]); + } + }); + + test("a multi-tenant collection: tenant count, tenants by name with their statuses, no per-tenant count", () => { + const state = weaviateStateDocument({ + definition: definitionOf("TenantNotesAuto"), + aliases: ALIASES, + shards: null, + tenants: [{ name: "umbrella", activityStatus: "COLD" }, { name: "acme" }, { activityStatus: "HOT" }, "junk"], + count: null, + }); + expect(state).toEqual({ + multiTenant: true, + autoTenantActivation: true, + aliases: [], + tenantCount: 2, + tenants: [ + { name: "acme", activityStatus: null }, + { name: "umbrella", activityStatus: "COLD" }, + ], + objectCount: PER_TENANT_COUNT, + }); + }); + + test("past 1,024 tenants the first 1,024 by name are listed, and the State says so", () => { + const tenants = Array.from({ length: 1_030 }, (_, index) => ({ + name: `t${String(1_030 - index).padStart(4, "0")}`, + activityStatus: "HOT", + })); + const state = weaviateStateDocument({ + definition: definitionOf("TenantNotes"), + aliases: ALIASES, + shards: null, + tenants, + count: null, + }); + expect(state.tenantCount).toBe(1_030); + const listed = state.tenants as { name: string }[]; + expect(listed).toHaveLength(1_024); + expect(listed[0].name).toBe("t0001"); + expect(listed.at(-1)?.name).toBe("t1024"); + expect(state.tenantsListed).toBe("the first 1024 of 1030 by name"); + }); + + test("a tenant answer that is not a list holds no tenant", () => { + const state = weaviateStateDocument({ + definition: definitionOf("TenantNotes"), + aliases: ALIASES, + shards: null, + tenants: { tenants: [] }, + count: null, + }); + expect(state).toMatchObject({ tenantCount: 0, tenants: [] }); + expect(state.tenantsListed).toBeUndefined(); + }); +}); + +describe("the parts", () => { + const input = { + definition: definitionOf("Article"), + aliases: ALIASES, + shards: JSON.parse(text("/v1/schema/Article/shards")), + tenants: null, + count: 500, + }; + + test("Schema is the definition as the server sent it, State the document; both complete JSON", () => { + const [schema, state] = weaviateSourceParts(input); + expect(schema).toEqual({ + id: "schema", + label: "Schema", + text: JSON.stringify(JSON.parse(text("/v1/schema/Article")), null, 2), + language: "json", + form: "complete", + origin: "rendered", + }); + expect(state).toEqual({ + id: "state", + label: "State", + text: JSON.stringify(weaviateStateDocument(input), null, 2), + language: "json", + form: "complete", + origin: "rendered", + }); + }); + + test("each part is cut at the caller's bound by the shared helper", () => { + const [schema, state] = weaviateSourceParts(input, 100).map(renderedPart); + const bounded = applySourceBound(JSON.stringify(input.definition.definition, null, 2), 100); + expect(schema.text).toBe(bounded.text); + expect(schema.truncated).toEqual(bounded.truncated); + expect(state.truncated).toBeDefined(); + const [whole] = weaviateSourceParts(input, 1_000_000).map(renderedPart); + expect(whole.truncated).toBeUndefined(); + }); +}); diff --git a/tests/unit/db/weaviate/versions.test.ts b/tests/unit/db/weaviate/versions.test.ts new file mode 100644 index 0000000000..6f25a63598 --- /dev/null +++ b/tests/unit/db/weaviate/versions.test.ts @@ -0,0 +1,155 @@ +/** + * The Weaviate version table (#1566 spec 3.3, doc 4.8): the version `GET /v1/meta` reports, the path each search + * starts on (REST from 1.39.7, near-vector from 1.39.8, GraphQL below and for a version that cannot be read), the + * sentence that names a version, and the warning below the 1.37 floor. The meta texts are the captured ones. + */ +import { describe, expect, test } from "bun:test"; +import { + belowFloorWarning, + initialPath, + REST_NEAR_VECTOR_SINCE, + REST_SEARCH_SINCE, + readWeaviateVersion, + serverHas, + versionText, + WEAVIATE_FLOOR, + WEAVIATE_TESTED_VERSIONS, + type WeaviateVersion, +} from "@/lib/db/providers/vector/weaviate/versions"; +import { capturedAnswer } from "../../../helpers/weaviate-wire"; + +const meta = (version: unknown) => + JSON.stringify({ grpcMaxMessageSize: 104_858_000, hostname: "http://[::]:8080", modules: {}, version }); +const at = (version: string): WeaviateVersion => readWeaviateVersion(meta(version)); +const NONE: WeaviateVersion = { reported: null, release: null }; + +describe("readWeaviateVersion", () => { + test.each([ + ["weaviate/surface.json", "1.40.2", [1, 40, 2]], + ["weaviate-nographql/surface.json", "1.40.2", [1, 40, 2]], + ["weaviate-1-38/surface.json", "1.38.22", [1, 38, 22]], + ["weaviate-1-37/surface.json", "1.37.4", [1, 37, 4]], + ] as const)("the captured meta of %s reports %s", (file, reported, release) => { + expect(readWeaviateVersion(capturedAnswer(file, "GET /v1/meta").text)).toEqual({ reported, release: [...release] }); + }); + + test.each([ + ["2.0.0", [2, 0, 0]], + ["1.100.12", [1, 100, 12]], + ["v1.39.7", [1, 39, 7]], + ["999999.0.999999", [999_999, 0, 999_999]], + ] as const)("a plain %s is read as its three numbers", (version, release) => { + expect(at(version)).toEqual({ reported: version, release: [...release] }); + }); + + test.each(["1.41.0-rc.1", "1.40", "1.40.2.1", "01.40.2", "1.040.2", "1000000.0.0", "V1.40.2", "latest"])( + "%s is reported and is no release", + (version) => { + expect(at(version)).toEqual({ reported: version, release: null }); + }, + ); + + test("a version that is not a short plain token is never repeated", () => { + expect(at("1.40.2 (key password)")).toEqual(NONE); + expect(at("x".repeat(33))).toEqual(NONE); + expect(at(`1.${"0".repeat(31)}`)).toEqual({ reported: null, release: null }); + expect(at("-1.40.2")).toEqual(NONE); + expect(at("")).toEqual(NONE); + expect(at("x".repeat(32))).toEqual({ reported: "x".repeat(32), release: null }); + }); + + test.each([ + ["no version field", JSON.stringify({ hostname: "http://[::]:8080" })], + ["a version that is not a string", meta(1.4)], + ["a body that is an array", '["1.40.2"]'], + ["a body that is null", "null"], + ["a body that is a string", '"1.40.2"'], + ["a body that is not JSON", "proxy"], + ["an empty body", ""], + ])("%s reports none", (_what, text) => { + expect(readWeaviateVersion(text)).toEqual(NONE); + }); +}); + +describe("serverHas", () => { + test("compares part by part, as numbers", () => { + expect(serverHas(at("1.39.7"), [1, 39, 7])).toBe(true); + expect(serverHas(at("1.39.6"), [1, 39, 7])).toBe(false); + expect(serverHas(at("1.40.0"), [1, 39, 7])).toBe(true); + expect(serverHas(at("1.38.100"), [1, 39, 7])).toBe(false); + expect(serverHas(at("2.0.0"), [1, 39, 7])).toBe(true); + expect(serverHas(at("0.99.99"), [1, 0, 0])).toBe(false); + expect(serverHas(at("1.100.0"), [1, 99, 0])).toBe(true); + }); + + test("a version that cannot be read is older than every release", () => { + expect(serverHas(NONE, [0, 0, 0])).toBe(false); + expect(serverHas(at("1.41.0-rc.1"), [0, 0, 0])).toBe(false); + }); +}); + +describe("initialPath: the table of spec 3.3", () => { + test("the thresholds and the floor are the measured releases", () => { + expect(REST_SEARCH_SINCE).toEqual([1, 39, 7]); + expect(REST_NEAR_VECTOR_SINCE).toEqual([1, 39, 8]); + expect(WEAVIATE_FLOOR).toEqual([1, 37, 0]); + expect(WEAVIATE_TESTED_VERSIONS).toEqual(["1.40.2", "1.38.22", "1.37.4"]); + expect(Object.isFrozen(WEAVIATE_TESTED_VERSIONS)).toBe(true); + }); + + test.each([ + ["1.37.4", "graphql", "graphql"], + ["1.37.17", "graphql", "graphql"], + ["1.38.22", "graphql", "graphql"], + ["1.39.0", "graphql", "graphql"], + ["1.39.6", "graphql", "graphql"], + ["1.39.7", "rest", "graphql"], + ["1.39.8", "rest", "rest"], + ["1.39.13", "rest", "rest"], + ["1.40.0", "rest", "rest"], + ["1.40.2", "rest", "rest"], + ["2.0.0", "rest", "rest"], + ] as const)("%s starts other searches on %s and near-vector on %s", (version, other, nearVector) => { + expect(initialPath(at(version), "other")).toBe(other); + expect(initialPath(at(version), "near-vector")).toBe(nearVector); + }); + + test("a version that cannot be read takes GraphQL", () => { + for (const version of [NONE, at("1.41.0-rc.1")]) { + expect(initialPath(version, "other")).toBe("graphql"); + expect(initialPath(version, "near-vector")).toBe("graphql"); + } + }); +}); + +describe("versionText", () => { + test("a release is its three numbers, a v prefix dropped", () => { + expect(versionText(at("1.40.2"))).toBe("1.40.2"); + expect(versionText(at("v1.39.7"))).toBe("1.39.7"); + }); + + test("a reported version that is no release is repeated and named as such", () => { + expect(versionText(at("1.41.0-rc.1"))).toBe("1.41.0-rc.1, which is not a plain release number"); + }); + + test("no version is named without repeating anything", () => { + expect(versionText(NONE)).toBe("a version it did not report"); + expect(versionText(at("1.40.2 (key password)"))).toBe("a version it did not report"); + }); +}); + +describe("belowFloorWarning (spec 3.1)", () => { + test("a release below 1.37 is warned of, naming it and the floor", () => { + expect(belowFloorWarning(at("1.36.9"))).toBe( + "This Weaviate server is 1.36.9, older than 1.37, the oldest line Studio supports; nothing below it is tested.", + ); + expect(belowFloorWarning(at("0.22.0"))).toStartWith("This Weaviate server is 0.22.0, older than 1.37"); + }); + + test("the floor and later, and a version that cannot be read, carry no warning", () => { + for (const version of ["1.37.0", "1.37.4", "1.40.2", "2.0.0"]) + expect(belowFloorWarning(at(version))).toBeUndefined(); + expect(belowFloorWarning(NONE)).toBeUndefined(); + expect(belowFloorWarning(at("1.36.0-rc.1"))).toBeUndefined(); + }); +}); diff --git a/tests/unit/e2e-project-servers.test.ts b/tests/unit/e2e-project-servers.test.ts index fbeb473779..6f38b66397 100644 --- a/tests/unit/e2e-project-servers.test.ts +++ b/tests/unit/e2e-project-servers.test.ts @@ -21,6 +21,7 @@ const SECOND_SERVER_SPECS = [ "neo4j-provider.spec.ts", "milvus-provider.spec.ts", "qdrant-provider.spec.ts", + "weaviate-provider.spec.ts", "influxdb-providers.spec.ts", "oxia-provider.spec.ts", "databend-provider.spec.ts", diff --git a/tests/unit/editor/dialect-editors.test.ts b/tests/unit/editor/dialect-editors.test.ts index 3e9395ec09..2209b0be1a 100644 --- a/tests/unit/editor/dialect-editors.test.ts +++ b/tests/unit/editor/dialect-editors.test.ts @@ -5,6 +5,7 @@ import { formatConsole } from "@/lib/db/console/format"; import { MTC_CONSOLE_DIALECT, MTC_CONSOLE_ROUTES } from "@/lib/db/providers/industrial/mtconnect/routes"; import { MILVUS_CONSOLE, MILVUS_ROUTES } from "@/lib/db/providers/vector/milvus/routes"; import { QDRANT_CONSOLE, QDRANT_ROUTES as QDRANT_ROUTES_REAL } from "@/lib/db/providers/vector/qdrant/routes"; +import { WEAVIATE_CONSOLE, WEAVIATE_ROUTES } from "@/lib/db/providers/vector/weaviate/routes"; import { DIALECT_EDITORS, formatterForLanguage, registerDialectConsoles } from "@/lib/editor/dialect-editors"; import { SHIPPED_DATABASE_TYPES } from "@/lib/db/compatibility"; import { resolveSqlGrammar } from "@/lib/sql/grammar"; @@ -21,6 +22,7 @@ const EDITOR_LANGUAGES: readonly EditorLanguage[] = [ "graph-cypher", "milvus", "qdrant", + "weaviate", "influxql", "oxia", "s3", @@ -54,6 +56,7 @@ describe("DIALECT_EDITORS", () => { "snmp", "sparkplug", "sql", + "weaviate", ]); }); @@ -79,6 +82,7 @@ describe("DIALECT_EDITORS", () => { cypher: "graph-cypher", milvus: "milvus", qdrant: "qdrant", + weaviate: "weaviate", influxql: "influxql", oxia: "oxia", s3: "s3", @@ -88,7 +92,7 @@ describe("DIALECT_EDITORS", () => { }); }); - test("only the SQL tab, the eight JSON tabs and the Milvus and Qdrant consoles have a formatter", () => { + test("only the SQL tab, the eight JSON tabs and the Milvus, Qdrant and Weaviate consoles have a formatter", () => { const formatted = Object.entries(DIALECT_EDITORS) .filter(([, editor]) => editor.format !== undefined) .map(([type]) => type) @@ -106,6 +110,7 @@ describe("DIALECT_EDITORS", () => { "snmp", "sparkplug", "sql", + "weaviate", ]); }); @@ -182,11 +187,11 @@ describe("formatterForLanguage", () => { }); describe("the console field", () => { - test("the three console records carry their console languages, and no other record carries one", () => { + test("the four console records carry their console languages, and no other record carries one", () => { const carrying = Object.entries(DIALECT_EDITORS) .filter(([, editor]) => editor.console !== undefined) .map(([tabType]) => tabType); - expect(carrying).toEqual(["milvus", "qdrant", "mtconnect"]); + expect(carrying).toEqual(["milvus", "qdrant", "weaviate", "mtconnect"]); // MTConnect's routes are DERIVED from the table its guard runs, so the identity checked here is // that the record carries that derived table and not a second hand-written one (#1722). expect(DIALECT_EDITORS.mtconnect.console?.spec).toBe(MTC_CONSOLE_DIALECT); @@ -198,6 +203,14 @@ describe("the console field", () => { expect(DIALECT_EDITORS.milvus.console?.routes).toBe(MILVUS_ROUTES); expect(DIALECT_EDITORS.qdrant.console?.spec).toBe(QDRANT_CONSOLE); expect(DIALECT_EDITORS.qdrant.console?.routes).toBe(QDRANT_ROUTES_REAL); + expect(DIALECT_EDITORS.weaviate.console?.spec).toBe(WEAVIATE_CONSOLE); + expect(DIALECT_EDITORS.weaviate.console?.routes).toBe(WEAVIATE_ROUTES); + }); + + test("a weaviate tab formats through formatConsole bound to WEAVIATE_CONSOLE", () => { + const text = 'POST /v1/search/Article/bm25\n{"query":"vector","limit":5}'; + expect(DIALECT_EDITORS.weaviate.format?.(text)).toBe(formatConsole(WEAVIATE_CONSOLE, text)); + expect(formatterForLanguage("weaviate")?.(text)).toBe(formatConsole(WEAVIATE_CONSOLE, text)); }); test("a milvus tab formats through formatConsole bound to MILVUS_CONSOLE", () => { @@ -244,10 +257,10 @@ describe("registerDialectConsoles", () => { expect(registered.map((language) => language.id)).toEqual(["first-console", "second-console"]); }); - test("registers the three console languages for the shipped records, once each", () => { + test("registers the four console languages for the shipped records, once each", () => { const { monaco, registered } = recordingMonaco(); registerDialectConsoles(monaco); registerDialectConsoles(monaco); - expect(registered.map((language) => language.id)).toEqual(["milvus", "qdrant", "mtconnect"]); + expect(registered.map((language) => language.id)).toEqual(["milvus", "qdrant", "weaviate", "mtconnect"]); }); }); diff --git a/tests/unit/lib/catalog-copy-engine-count.test.ts b/tests/unit/lib/catalog-copy-engine-count.test.ts index 84fbe0bc30..13a43d63e8 100644 --- a/tests/unit/lib/catalog-copy-engine-count.test.ts +++ b/tests/unit/lib/catalog-copy-engine-count.test.ts @@ -117,6 +117,8 @@ const NUMERAL_WORDS: Record = { "forty-one": 41, "forty-two": 42, "forty-three": 43, + "forty-four": 44, + "forty-five": 45, }; /** diff --git a/tests/unit/lib/db-ui-config.test.ts b/tests/unit/lib/db-ui-config.test.ts index 56f43b64ee..8dcb6ccf3c 100644 --- a/tests/unit/lib/db-ui-config.test.ts +++ b/tests/unit/lib/db-ui-config.test.ts @@ -108,6 +108,7 @@ const ALL_TYPES: DatabaseType[] = [ "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", @@ -554,11 +555,13 @@ describe("db-ui-config", () => { * authentication is refused, and its provider refuses a non-empty `config.user` naming the field. RabbitMQ has no * database: virtual hosts are discovered, and its provider refuses a non-empty `config.database` naming the field. * Apache Spark has no user name either: every request uses one fixed Spark Connect user id, and its provider - * refuses a non-empty `config.user` naming the field (Apache Spark). + * refuses a non-empty `config.user` naming the field (Apache Spark). Weaviate has no user name either: an API + * key and an OIDC access token are both a bearer token in the password, and its provider refuses a non-empty + * `config.user` naming the field (#1566 spec 6.1). * Listed by name, so the read stays visible. */ const READ_ONLY_TO_REFUSE: Readonly> = { - user: ["qdrant", "influxdb3", "oxia", "kubernetes", "spark"], + user: ["qdrant", "weaviate", "influxdb3", "oxia", "kubernetes", "spark"], database: ["rabbitmq"], }; @@ -828,6 +831,27 @@ describe("declared connection-field copy (#1085)", () => { expect(qdrant.credentialWarnings).toBe(CREDENTIAL_WARNINGS.qdrant); }); + test("weaviate declares its port, no Database box, no User field, API key or token, the hints and the Host box addresses (#1566 spec 6.1)", () => { + const weaviate = getDBConfig("weaviate"); + expect(weaviate).toMatchObject({ + label: "Weaviate", + color: "text-hue-zinc", + defaultPort: "8080", + showConnectionStringToggle: false, + connectionFields: ["host", "port", "password"], + }); + expect(weaviate.showSshTunnel).toBeUndefined(); + expect(offersSshTunnel("weaviate")).toBe(true); + expect(takesConnectionField("weaviate", "user")).toBe(false); + expect(takesConnectionField("weaviate", "database")).toBe(false); + expect(weaviate.fieldLabels).toEqual({ password: "API key or token" }); + expect(Object.keys(weaviate.fieldHints ?? {})).toEqual(["host", "password"]); + expect(weaviate.fieldHints?.host).toContain("never Weaviate's gRPC port 50051"); + expect(weaviate.fieldHints?.password).toContain("an SSL mode other than disable"); + expect(hostUriSchemes("weaviate")).toEqual(["http", "https"]); + expect(weaviate.credentialWarnings).toBe(CREDENTIAL_WARNINGS.weaviate); + }); + test("oxia declares its label, port, fields, labels, the five hints and the read-only hint (SB3-1.5)", () => { const oxia = getDBConfig("oxia"); expect(oxia.label).toBe("Oxia"); @@ -1050,7 +1074,7 @@ describe("declared connection-field copy (#1085)", () => { } }); - test("only libsql, mongodb, oracle, db2, mssql, couchbase, trino, cassandra, prometheus, kafka, etcd, neo4j, milvus, qdrant, the two InfluxDB types, oxia, databend, bigquery, snowflake, spark, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect and modbus declare field copy, so every other engine draws every label and hint it drew before", () => { + test("only libsql, mongodb, oracle, db2, mssql, couchbase, trino, cassandra, prometheus, kafka, etcd, neo4j, milvus, qdrant, weaviate, the two InfluxDB types, oxia, databend, bigquery, snowflake, spark, s3, kubernetes, mqtt, firestore, rabbitmq, opcua, mtconnect and modbus declare field copy, so every other engine draws every label and hint it drew before", () => { const declared = Object.entries(DB_UI_CONFIG) .filter(([, config]) => config.fieldLabels !== undefined || config.fieldHints !== undefined) .map(([type]) => type); @@ -1070,6 +1094,7 @@ describe("declared connection-field copy (#1085)", () => { "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", @@ -1614,9 +1639,11 @@ describe("db-showcase", () => { // Behind Snowflake and ahead of libSQL: the open-source engine a data team runs its lakehouse SQL on, so only // libSQL, the embedded store and OPC UA move. "spark", + // Behind Spark and ahead of libSQL (#1566): the third vector database on the page, and the newest name. + "weaviate", "libsql", "libredb", - // Last (rank 36), behind the embedded store: an industrial address space is the least recognisable + // Last (rank 37), behind the embedded store: an industrial address space is the least recognisable // name on a page of databases, so no existing engine moves for it (#1677). "opcua", "mtconnect", @@ -1654,10 +1681,11 @@ describe("db-showcase", () => { }); describe("Host box addresses and credential warnings", () => { - test("only milvus, qdrant, the two InfluxDB types, databend, s3, kubernetes, rabbitmq and mtconnect declare hostAcceptsUri, so every other Host box takes a host alone", () => { + test("only milvus, qdrant, weaviate, the two InfluxDB types, databend, s3, kubernetes, rabbitmq and mtconnect declare hostAcceptsUri, so every other Host box takes a host alone", () => { expect(ALL_TYPES.filter((type) => hostUriSchemes(type).length > 0)).toEqual([ "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "databend", diff --git a/tests/unit/lib/db/connection-fingerprint.test.ts b/tests/unit/lib/db/connection-fingerprint.test.ts index 5fe6b1274b..92577a8ff0 100644 --- a/tests/unit/lib/db/connection-fingerprint.test.ts +++ b/tests/unit/lib/db/connection-fingerprint.test.ts @@ -69,7 +69,7 @@ describe("connectionFingerprint", () => { expect(await connectionFingerprint(vary({ serviceName: "XEPDB1" }))).not.toBe(base); expect(await connectionFingerprint(vary({ instanceName: "SQLEXPRESS" }))).not.toBe(base); // The tenth, which the four above were audited without and which a review of THAT audit found - // one field away: the bastion is the ROUTE, and `factory.ts:1251-1258` rewrites `host` and `port` + // one field away: the bastion is the ROUTE, and `factory.ts:1258-1265` rewrites `host` and `port` // to the tunnel's local endpoint before the provider is constructed, so the tunnel and not the // record decides which machine the sealed statement reaches. expect(await connectionFingerprint(vary({ sshTunnel: BASTION }))).not.toBe(base); @@ -95,7 +95,7 @@ describe("connectionFingerprint", () => { expect(ours).not.toBe(await connectionFingerprint(vary({ sshTunnel: { ...BASTION, port: 2222 } }))); expect(ours).not.toBe(await connectionFingerprint(vary({ sshTunnel: { ...BASTION, username: "mallory" } }))); // A DISABLED tunnel is not the same route as an enabled one to the same bastion, because - // `factory.ts:1251` branches on exactly that flag and only the enabled arm rewrites the endpoint. + // `factory.ts:1258` branches on exactly that flag and only the enabled arm rewrites the endpoint. expect(ours).not.toBe(await connectionFingerprint(vary({ sshTunnel: { ...BASTION, enabled: false } }))); // And the tunnel's SECRETS are out, on the rule the database password already follows: rotating // a key changes who may reach the bastion, never which machine it is. `hostKeyFingerprint` is diff --git a/tests/unit/lib/db/connection-form.test.ts b/tests/unit/lib/db/connection-form.test.ts index e4edbf2103..d3a89901d8 100644 --- a/tests/unit/lib/db/connection-form.test.ts +++ b/tests/unit/lib/db/connection-form.test.ts @@ -69,6 +69,7 @@ const PICKER_COVERAGE: Record = { neo4j: true, milvus: true, qdrant: true, + weaviate: true, influxdb: true, influxdb3: true, oxia: true, @@ -350,6 +351,7 @@ describe("CONNECTION_PICKER_ORDER", () => { "mtconnect", "modbus", "netconf", + "weaviate", ]); }); diff --git a/tests/unit/lib/db/credential-warnings.test.ts b/tests/unit/lib/db/credential-warnings.test.ts index 06e1f658b0..6d4e2cb8f9 100644 --- a/tests/unit/lib/db/credential-warnings.test.ts +++ b/tests/unit/lib/db/credential-warnings.test.ts @@ -26,10 +26,11 @@ const MANAGE_NO_EXP_URL_SAFE = "e30.eyJhY2Nlc3MiOiJtIiwic3ViIjoieHg_Pz8_Pz4-In0. type Credential = { user?: string; password?: string }; describe("CREDENTIAL_WARNINGS", () => { - test("milvus, qdrant, influxdb, influxdb3, oxia, databend, s3 and rabbitmq are the shipped types that declare credential warnings (vector-family spec 3.12, InfluxDB spec E12, SB3-1.5, Databend design 7.2)", () => { + test("milvus, qdrant, weaviate, influxdb, influxdb3, oxia, databend, s3 and rabbitmq are the shipped types that declare credential warnings (vector-family spec 3.12, InfluxDB spec E12, SB3-1.5, Databend design 7.2)", () => { expect(Object.keys(CREDENTIAL_WARNINGS)).toEqual([ "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", @@ -39,6 +40,7 @@ describe("CREDENTIAL_WARNINGS", () => { ]); expect(CREDENTIAL_WARNINGS.milvus?.map((entry) => entry.kind)).toEqual(["pair", "no-secret"]); expect(CREDENTIAL_WARNINGS.qdrant?.map((entry) => entry.kind)).toEqual(["jwt", "no-secret"]); + expect(CREDENTIAL_WARNINGS.weaviate?.map((entry) => entry.kind)).toEqual(["no-secret"]); expect(CREDENTIAL_WARNINGS.oxia?.map((entry) => entry.kind)).toEqual(["jwt"]); expect(CREDENTIAL_WARNINGS.s3?.map((entry) => entry.kind)).toEqual(["pair", "pair"]); expect(CREDENTIAL_WARNINGS.rabbitmq?.map((entry) => entry.kind)).toEqual(["pair"]); diff --git a/tests/unit/lib/table-count.test.ts b/tests/unit/lib/table-count.test.ts index b36a1df1c5..ffea32e671 100644 --- a/tests/unit/lib/table-count.test.ts +++ b/tests/unit/lib/table-count.test.ts @@ -85,6 +85,7 @@ const EXPECTED_COUNT: Readonly> = Object.fre milvus: null, // A Qdrant console request (vector-family spec 6.7): the dialect's record withholds the action; a count is the documented count request. qdrant: null, + weaviate: null, // InfluxQL (InfluxDB spec I12): `offersCountQuery` answers false for the language, so no Count appears. influxdb: null, // DataFusion SQL with no container level (R16) and `double-always` quoting (R41): every segment double-quoted, no diff --git a/tests/unit/readme-numeral-names.test.ts b/tests/unit/readme-numeral-names.test.ts index bc106fa239..1f0353f5a2 100644 --- a/tests/unit/readme-numeral-names.test.ts +++ b/tests/unit/readme-numeral-names.test.ts @@ -50,15 +50,15 @@ const ENGINE_NAMES = EXTERNAL_DATABASE_TYPES.map((type) => DB_UI_CONFIG[type].la * digits. Every other file writes it out. */ const READMES: ReadonlyArray<{ file: string; now: string; before: string }> = [ - { file: "README.md", now: "Forty-one", before: "Forty" }, - { file: "README_zh.md", now: "四十一种引擎", before: "四十种引擎" }, - { file: "README_ja.md", now: "41のエンジン", before: "40のエンジン" }, - { file: "README_es.md", now: "Cuarenta y uno", before: "Cuarenta" }, - { file: "README_pt.md", now: "Quarenta e um", before: "Quarenta" }, - { file: "README_ru.md", now: "Сорок один", before: "Сорок" }, - { file: "README_hi.md", now: "इकतालीस engines", before: "चालीस engines" }, - { file: "README_ur.md", now: "اکتالیس engines", before: "چالیس engines" }, - { file: "README_ko.md", now: "41개의 엔진", before: "40개의 엔진" }, + { file: "README.md", now: "Forty-two", before: "Forty-one" }, + { file: "README_zh.md", now: "四十二种引擎", before: "四十一种引擎" }, + { file: "README_ja.md", now: "42のエンジン", before: "41のエンジン" }, + { file: "README_es.md", now: "Cuarenta y dos", before: "Cuarenta y uno" }, + { file: "README_pt.md", now: "Quarenta e dois", before: "Quarenta e um" }, + { file: "README_ru.md", now: "Сорок две", before: "Сорок один" }, + { file: "README_hi.md", now: "बयालीस engines", before: "इकतालीस engines" }, + { file: "README_ur.md", now: "بیالیس engines", before: "اکتالیس engines" }, + { file: "README_ko.md", now: "42개의 엔진", before: "41개의 엔진" }, ]; /** The engines a line names, which is what a numeral beside a list is claiming. */ diff --git a/tests/unit/schema-diff/migration-dialects.test.ts b/tests/unit/schema-diff/migration-dialects.test.ts index 7d1209e062..f05726ea90 100644 --- a/tests/unit/schema-diff/migration-dialects.test.ts +++ b/tests/unit/schema-diff/migration-dialects.test.ts @@ -41,6 +41,7 @@ const COLUMN_GRAMMAR: Record = { neo4j: null, milvus: null, qdrant: null, + weaviate: null, influxdb: null, influxdb3: null, oxia: null, diff --git a/tests/unit/schema-diff/migration-generator.test.ts b/tests/unit/schema-diff/migration-generator.test.ts index b2f042434f..e2cf8d3726 100644 --- a/tests/unit/schema-diff/migration-generator.test.ts +++ b/tests/unit/schema-diff/migration-generator.test.ts @@ -1110,6 +1110,7 @@ describe("generateMigrationSQL: SQLite's grammar declares a foreign key only ins neo4j: "engine-has-no-foreign-key", milvus: "engine-has-no-foreign-key", qdrant: "engine-has-no-foreign-key", + weaviate: "engine-has-no-foreign-key", influxdb: "engine-has-no-foreign-key", influxdb3: "engine-has-no-foreign-key", oxia: "engine-has-no-foreign-key", @@ -1253,6 +1254,7 @@ const MODIFIED_COLUMN_COVERAGE: Record< // Not a table store either (vector-family spec 6.3): a collection holds points whose payloads are schemaless, and // the columns the object browser shows are its vectors, its payload indexes and a sample of its payload keys. qdrant: { label: "Qdrant", reason: "payloads are schemaless" }, + weaviate: { label: "Weaviate", reason: "declared through Weaviate's own schema API" }, // Not a table store either: a measurement's tags and fields come from the points written to it. influxdb: { label: "InfluxDB (InfluxQL)", reason: "created by the points written to it" }, // A table's tags and fields come from the line protocol written to it, and the 3.x SQL takes no DDL. @@ -1640,6 +1642,7 @@ describe("generateMigrationSQL: dialects that cannot modify a column", () => { "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", @@ -1717,6 +1720,7 @@ const TRANSACTION_WRAPPER_COVERAGE: Record { "neo4j", "milvus", "qdrant", + "weaviate", "influxdb", "influxdb3", "oxia", diff --git a/tests/unit/security-check.test.ts b/tests/unit/security-check.test.ts index 99260922a3..6cf64f9ce8 100644 --- a/tests/unit/security-check.test.ts +++ b/tests/unit/security-check.test.ts @@ -68,9 +68,8 @@ describe("parseTables and findControlTable", () => { expect(table?.rows).toHaveLength(PROGRAMME_CONTROL_IDS.length); }); - test("the programme ends with the Oxia read-only client, the DuckDB extension and external-access controls, the S3 controls, the Kubernetes request allowlist, the RabbitMQ read path, the Apache Spark session and answer bounds, then the governance sealed credentials and query event capture", () => { + test("the programme ends with the Oxia read-only client, the DuckDB extension and external-access controls, the S3 controls, the Kubernetes request allowlist, the RabbitMQ read path, the Apache Spark session and answer bounds, then the governance sealed credentials and query event capture, then the Weaviate console", () => { expect(PROGRAMME_CONTROL_IDS.slice(-10)).toEqual([ - "3.15", "3.16", "3.17", "3.18", @@ -80,8 +79,9 @@ describe("parseTables and findControlTable", () => { "3.22", "3.23", "3.24", + "3.25", ]); - expect(PROGRAMME_CONTROL_IDS).toHaveLength(47); + expect(PROGRAMME_CONTROL_IDS).toHaveLength(48); }); test("ignores a table that is not the control table", () => { diff --git a/tests/unit/sql/grammar.test.ts b/tests/unit/sql/grammar.test.ts index a5c368a55d..b466755c25 100644 --- a/tests/unit/sql/grammar.test.ts +++ b/tests/unit/sql/grammar.test.ts @@ -433,6 +433,7 @@ const GRAMMAR_COVERAGE: Record = { milvus: "default", // A Qdrant console request, not SQL (vector-family spec 6.4): no SQL grammar is established for it, and none is read. qdrant: "default", + weaviate: "default", // InfluxQL, not SQL: the provider's own lexer reads it, so no SQL grammar is established for it, and none is read. influxdb: "default", // Five facts probed on InfluxDB 3.12.0 Core through `POST /api/v3/query_sql`, the route the provider @@ -763,6 +764,7 @@ const SQL_TEXT_COVERAGE: Record = { // A Qdrant console request is a request line and one JSON body, not SQL text: its strings escape with a // backslash and `//` opens a comment, which a SQL span reader cannot follow (vector-family spec 6.4). qdrant: false, + weaviate: false, // An InfluxQL statement is not SQL text: its strings escape with a backslash, `/.../` is a regex where the parser // asks for one, and a `--` comment ends at a lone `\r`, none of which a SQL span reader follows (SPEC 5.7). influxdb: false, diff --git a/tests/unit/theme-accent-contrast.test.ts b/tests/unit/theme-accent-contrast.test.ts index b1ba9a6d1a..2bf8dcc205 100644 --- a/tests/unit/theme-accent-contrast.test.ts +++ b/tests/unit/theme-accent-contrast.test.ts @@ -255,6 +255,11 @@ const HUES: ReadonlyArray<{ hue: string; light: string; lightAlt: string }> = [ // was, light 0.0166 and dark 0.0100, which none of the other three do. Putting `gray-800` in // this slot instead fails "the light set is no tighter than the dark set it is modelled on". { hue: "mauve", light: "mauve-700", lightAlt: "mauve-900" }, + // Weaviate's identity (#1566): every base hue, every `-alt` step and seven greys were an engine's, so the palette + // gains `zinc`, which the Modbus note above measured as clearing every test. MEASURED against the declared set: + // `zinc-900` in light and `zinc-400` in dark leave both closest identity pairs where they were (0.0205 light, + // 0.0076 dark); `zinc-800` tightens the light set to 0.0110 against `stone`. + { hue: "zinc", light: "zinc-900", lightAlt: "zinc-950" }, ]; /** diff --git a/vscode-extension/src/webview/vscode-bridge.css b/vscode-extension/src/webview/vscode-bridge.css index b4d2288b2a..42ae219762 100644 --- a/vscode-extension/src/webview/vscode-bridge.css +++ b/vscode-extension/src/webview/vscode-bridge.css @@ -165,6 +165,7 @@ --studio-hue-slate-alt: var(--vscode-descriptionForeground); --studio-hue-taupe: var(--vscode-descriptionForeground); --studio-hue-mauve: var(--vscode-descriptionForeground); + --studio-hue-zinc: var(--vscode-descriptionForeground); --font-geist-sans: var(--vscode-font-family); --font-geist-mono: var(--vscode-editor-font-family); --radius: 0.5rem; diff --git a/vscode-extension/test/unit/editor/editor-language.test.ts b/vscode-extension/test/unit/editor/editor-language.test.ts index 0295995838..873eb9e9e4 100644 --- a/vscode-extension/test/unit/editor/editor-language.test.ts +++ b/vscode-extension/test/unit/editor/editor-language.test.ts @@ -13,6 +13,7 @@ const EVERY_LANGUAGE = { "graph-cypher": true, milvus: true, qdrant: true, + weaviate: true, influxql: true, oxia: true, s3: true, diff --git a/vscode-extension/test/unit/webview/stylesheet.test.ts b/vscode-extension/test/unit/webview/stylesheet.test.ts index 967992f633..d818056537 100644 --- a/vscode-extension/test/unit/webview/stylesheet.test.ts +++ b/vscode-extension/test/unit/webview/stylesheet.test.ts @@ -106,6 +106,7 @@ const HUE_FAMILIES: Record = { mist: "--vscode-descriptionForeground", taupe: "--vscode-descriptionForeground", mauve: "--vscode-descriptionForeground", + zinc: "--vscode-descriptionForeground", }; describe("the VS Code theming bridge", () => {