Azure Cosmos DB vNext Emulator: Query and Observability Enhancements

Published: (December 13, 2025 at 10:28 AM EST)
4 min read
Source: Dev.to

Source: Dev.to

Query Improvements

This emulator release enables several query patterns that were previously unsupported. In this post, we’ll focus on the following enhancements to query capabilities:

  • Improved JOIN Operations – Support for nested JOINs across multiple array levels, cross‑product JOINs, and self‑JOINs on primitive arrays
  • Enhanced Operator Support – Support for string manipulation functions (CONCAT, LENGTH) and array operations (ARRAY_LENGTH, direct array indexing)
  • Better Subdocument Handling – Improved querying of deeply nested object properties and proper handling of missing properties

Let’s explore these with practical examples.

Improved JOINs

In Azure Cosmos DB, JOINs enable you to flatten and traverse data within documents, allowing you to work with nested and hierarchical data structures.

Below is a sample family dataset where each document represents a family with nested arrays. The dataset includes three families (Andersen, Wakefield, and Miller) with varying numbers of children and pets, demonstrating how JOINs handle different data structures.

[
    {
        "id": "AndersenFamily",
        "lastName": "Andersen",
        "parents": [
            {"firstName": "Thomas", "relationship": "father"},
            {"firstName": "Mary Kay", "relationship": "mother"}
        ],
        "children": [
            {
                "firstName": "Henriette",
                "grade": 5,
                "pets": [{"name": "Fluffy", "type": "Rabbit"}]
            }
        ],
        "tags": ["seattle", "active", "family-friendly"],
        "address": {"state": "WA", "city": "Seattle"}
    },
    {
        "id": "WakefieldFamily",
        "lastName": "Wakefield",
        "parents": [
            {"firstName": "Robin", "relationship": "mother"},
            {"firstName": "Ben", "relationship": "father"}
        ],
        "children": [
            {
                "firstName": "Jesse",
                "grade": 8,
                "pets": [
                    {"name": "Goofy", "type": "Dog"},
                    {"name": "Shadow", "type": "Horse"}
                ]
            },
            {"firstName": "Lisa", "grade": 1, "pets": []}
        ],
        "tags": ["newyork", "urban"],
        "address": {"state": "NY", "city": "New York"}
    },
    {
        "id": "MillerFamily",
        "lastName": "Miller",
        "parents": [{"firstName": "David", "relationship": "father"}],
        "children": [
            {
                "firstName": "Emma",
                "grade": 6,
                "pets": [{"name": "Whiskers", "type": "Cat"}]
            }
        ],
        "tags": ["boston", "academic"],
        "address": {"state": "MA", "city": "Boston"}
    }
]

Basic JOIN – Flattening Arrays

Generate a list of all children across families (e.g., for a school roster) by flattening the children array:

SELECT f.id, f.lastName, c.firstName, c.grade 
FROM f 
JOIN c IN f.children

Result: one row per child – Henriette (Andersen), Jesse & Lisa (Wakefield), Emma (Miller).

JOIN with Filter

Find children within a specific grade range (e.g., middle‑school students, grade ≥ 6):

SELECT f.id, f.lastName, c.firstName, c.grade 
FROM f 
JOIN c IN f.children 
WHERE c.grade >= 6

Result: Jesse (grade 8) and Emma (grade 6) only.

Nested JOIN – Traversing Hierarchical Data

Identify all pets and their owners by chaining JOINs through childrenpets:

SELECT f.id, c.firstName AS child, p.name AS pet, p.type 
FROM f 
JOIN c IN f.children 
JOIN p IN c.pets

Result:

  • Henriette – Fluffy (Rabbit)
  • Jesse – Goofy (Dog) & Shadow (Horse)
  • Emma – Whiskers (Cat)

(Lisa is omitted because her pets array is empty, demonstrating inner‑join behavior.)

Cross‑Product JOIN – Combining Independent Arrays

Pair each child with every family tag to analyze patterns or preferences:

SELECT f.id, c.firstName AS child, t AS tag 
FROM f 
JOIN c IN f.children 
JOIN t IN f.tags

Result:

  • Henriette appears three times (tags: “seattle”, “active”, “family‑friendly”)
  • Jesse & Lisa each appear twice (tags: “newyork”, “urban”)
  • Emma appears twice (tags: “boston”, “academic”).

JOIN on Primitive Arrays

Flatten simple value arrays such as tags:

SELECT f.id, f.lastName, t AS tag 
FROM f 
JOIN t IN f.tags

Result: each tag becomes its own row linked to the corresponding family.

Self‑JOIN – Finding Combinations

Discover which tags frequently appear together by joining the same array with different aliases:

SELECT f.id, t1 AS tag1, t2 AS tag2 
FROM f 
JOIN t1 IN f.tags 
JOIN t2 IN f.tags 
WHERE t1 < t2

Result:

  • Andersen family yields three unique pairs: (“active”, “seattle”), (“active”, “family‑friendly”), (“family‑friendly”, “seattle”)
  • Wakefield and Miller families each yield one pair from their two tags.

Complex Filters – Multi‑Level Conditions

Combine root‑level properties with deeply nested array elements. For example, find all rabbits owned by families located in Washington state:

SELECT f.id, f.lastName, c.firstName AS child, p.name AS pet, p.type 
FROM f 
JOIN c IN f.children 
JOIN p IN c.pets 
WHERE f.address.state = "WA" AND p.type = "Rabbit"

(Continue building queries as needed for your specific scenarios.)

Back to Blog

Related posts

Read more »