Skip to content

Latest commit

 

History

History
137 lines (84 loc) · 11.1 KB

query-runtime.md

File metadata and controls

137 lines (84 loc) · 11.1 KB

User Manual — Back to User Manual


Query Runtime: How It Works Behind the Scenes

The Query Playground and Interactive Shell share a common query runtime that is bundled directly into the extension. This page explains how the runtime works, what powers the autocompletion and schema awareness, and introduces the open-source packages that make it all possible.

Table of Contents

No External Tools Required

Before v0.8, the extension's scratchpad feature required a locally installed shell executable on your machine. That external dependency has been completely removed. The query runtime is now bundled into the extension itself.

This means:

  • Zero installation: Just install the extension. No additional tools, no PATH configuration, no version mismatches.
  • Works with Entra ID: The runtime reuses the connection you already established when connecting to your cluster. If you authenticated with Microsoft Entra ID, the Query Playground and Interactive Shell work automatically, with no extra credential configuration.
  • Cross-platform: Works identically on Windows, macOS, and Linux.

How Queries Are Executed

When you run a query in the Query Playground or Interactive Shell, the extension:

  1. Reuses the existing connection: The runtime uses the database connection you already established when you connected to the cluster in the tree view. No new connection is created, and no credentials need to be re-entered.
  2. Evaluates in a sandboxed context: Your code runs in an isolated JavaScript context with access to the db object, BSON constructors (ObjectId, ISODate, etc.), and standard JavaScript globals.
  3. Runs in a worker thread: Each execution happens in a separate worker thread, so a slow or infinite query cannot freeze VS Code. Queries have no extension-side time limit: stop a long-running query with Cancel or Ctrl+C, or add .maxTimeMS() to let the database enforce a limit.
  4. Returns structured results: Results are normalized into a consistent format with metadata (document count, execution time, cursor state), then displayed in the results panel or terminal.

The Query Playground uses fresh context mode by default: each execution starts with a clean slate. The Interactive Shell uses persistent context mode: variables, functions, and state carry over between commands within a session.

Running Several Sessions at Once

You can keep multiple playgrounds and shells open at the same time. How they share worker threads differs between the two surfaces, and that difference is visible when one of them is busy.

Interactive Shell: one worker per terminal.

  • Each shell terminal gets its own dedicated worker thread. Opening two shells against the same cluster creates two independent workers.
  • A slow operation in one shell does not block another shell.
  • Each shell keeps its own session state, including the current database and any variables you defined.

Query Playground: one worker per cluster.

  • Playground workers are shared per cluster, so opening several playground tabs against the same server reuses one worker.
  • Only one run at a time is allowed per cluster. Runs are not queued: if a playground is already running against that cluster, the extension tells you "A playground is already running on this cluster. Wait for it to finish." and does nothing. Wait for the first run to finish, then run again.
  • Playgrounds connected to different clusters run fully independently, because each cluster gets its own worker.
  • A playground document is bound to one cluster and database at a time. You can rebind it: select the connection indicator (the CodeLens at the top of the file, or the status bar entry) and choose Connect to a different database….

The shell uses per-terminal workers because each session carries independent state that must not leak between terminals. Playground executions always name their target database explicitly and keep no state between runs, so sharing one worker per cluster is safe and avoids the cost of an extra thread per tab.

How Autocompletion Works

Autocompletion across all query surfaces (Collection View, Query Playground, Interactive Shell) is powered by two data sources:

Field Names from Your Data

The extension samples documents from your collection and analyzes their structure to learn what fields exist and what types they hold. This analysis happens incrementally: as you query and browse data, the schema knowledge grows. Field names appear in completion suggestions with type annotations (e.g., name (String), age (Int32), tags (Array)).

Operators from Official Documentation

All supported DocumentDB API operators, stages, accumulators, BSON constructors, and system variables (over 300 in total) are available as completion items. Each entry includes a description, a code snippet, and a link to the official documentation page. The operator data is automatically sourced from the DocumentDB compatibility reference and the DocumentDB operator documentation, ensuring it stays up to date with the latest supported features.

The @documentdb-js Packages

The query runtime and autocompletion features are built on three open-source packages, developed as part of this extension and published under the @documentdb-js scope. Each package is standalone and can be used independently in other tooling.

@documentdb-js/shell-runtime

A sandboxed JavaScript evaluation engine for DocumentDB. It handles executing user code against a database, intercepting shell commands (help, exit, cls), transforming results into a consistent format, and generating help text.

The runtime supports two modes:

  • Fresh context: Each evaluation starts clean. Used by the Query Playground, where each script block is independent.
  • Persistent context: Variables, cursor state, and the database reference persist across evaluations. Used by the Interactive Shell, where you build up state command by command.

The runtime takes an existing database connection and wraps it for evaluation. It never opens or closes connections itself, which is why it works seamlessly with any authentication method the extension supports, including Entra ID.

📦 npm · Source

@documentdb-js/schema-analyzer

An incremental JSON Schema analyzer for DocumentDB and MongoDB API documents. It processes documents one at a time (or in batches) and produces an extended JSON Schema with statistical metadata:

  • Field occurrence counts: How often each field appears across sampled documents.
  • BSON type distributions: What types each field holds (String, Int32, ObjectId, Array, etc.), recognizing all 24 BSON types.
  • Value statistics: Min/max values for numbers, string lengths, and array sizes.
  • Known field extraction: A flat list of all known field paths with their types and occurrence probabilities, ready for autocompletion.

The analyzer uses version-based caching so derived data (like the field list) is only recomputed when new documents are added.

📦 npm · Source

@documentdb-js/operator-registry

A reference catalog of all operators supported by DocumentDB. It contains over 300 entries across query operators, update operators, expression operators, aggregation stages, accumulators, window operators, BSON type constructors, and system variables. Each entry includes:

  • Value: The operator name (e.g., $gt, $match, ObjectId).
  • Description: A human-readable explanation of what the operator does.
  • Code snippet: A ready-to-insert template for autocompletion.
  • Documentation link: A direct URL to the official DocumentDB documentation page.
  • Type metadata: Which BSON types the operator applies to, and filterable meta-tags for context-aware suggestions.

The operator data is automatically generated from the official DocumentDB documentation using a built-in scraper. A CI test validates that the package always matches the upstream documentation, so when DocumentDB adds or removes operators, the package is updated accordingly.

📦 npm · Source

Schema Sharing Across Features

The extension maintains a shared schema cache that accumulates knowledge about your collections as you work. When you browse documents in the Collection View, the schema analyzer processes those documents. That same schema data is then available to the Query Playground and Interactive Shell for autocompletion.

All schema analysis happens locally. The extension analyzes documents that are already being fetched for display. No additional requests are made to your database for schema purposes, and no document data is sent to external services. The schema information stays entirely within your VS Code instance.

This means:

  • Schema builds up over time: The more you interact with a collection, the richer the autocompletion becomes.
  • Shared across tabs: If you browse a collection in one tab and then open a playground for the same collection, the field suggestions are already there.
  • On-demand refresh: Use the Quick Scan action in the Collection View to sample a fresh batch of documents and update the schema immediately.

Security and Isolation

  • Sandboxed execution: User code runs in an isolated JavaScript context, not in the extension's main process. It has access only to the db object and standard globals, not to VS Code APIs, the file system, or network resources beyond the database connection.
  • Worker thread isolation: Each execution runs in a dedicated worker thread. If code enters an infinite loop or consumes excessive resources, the worker is terminated without affecting VS Code.
  • Connection reuse only: The runtime never creates new connections or stores credentials. It uses the connection you already established, which means your credentials are managed entirely by VS Code's secure storage.

Related: Query Playground | Interactive Shell