Understanding how to query arrays in Azure Cosmos DB
source link: https://devblogs.microsoft.com/cosmosdb/understanding-how-to-query-arrays-in-azure-cosmos-db/?WT_mc_id=DOP-MVP-4025064
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Understanding how to query arrays in Azure Cosmos DB
December 17th, 2020
This blog is the final part of a series of blogs where we’ll demystify commonly confused concepts for developers learning how to query data using the SQL (core) API in Azure Cosmos DB. Today, we’ll walk through tips and tricks for querying arrays.
In case you missed them, here are the earlier two blogs in the series:
Using an example, we’ll show how to use these concepts when querying arrays:
- Accessing a specific array element
- Iterating over arrays
- JOINs
- Subqueries
Example Scenario:
Nick is a developer that created an app that stores shopping lists. His app is incredibly popular around the holidays and has soared to 1 million active users!
He has a Cosmos container that has the shopping lists modeled as JSON documents. Here’s an example document:
{ "id": "Tim", "city": "Seattle", "gifts": [ { "recipient": "Andrew", "gift": "blanket" }, { "recipient": "Deborah", "gift": "board game" }, { "recipient": "Chris", "gift": "coffee maker" } ] }
The remainder of the blog will focus on ways to query arrays, starting with the simplest (and least expressive) and concluding with the more advanced concepts.
Accessing a specific array position
The simplest way to query an array is to specify a specific position in the array. For example, the below query finds all shopping lists that have a recipient named Andrew in the first position within the gifts array.
Query:
SELECT * FROM c WHERE c.gifts[0].recipient = "Andrew"
This query is very simple to understand and inexpensive to run. However, filtering based on a specific array element isn’t enough for many scenarios.
Iterating over arrays
Azure Cosmos DB provides support for iterating over arrays by using the IN keyword in the FROM source. This is best illustrated with an example.
Query:
SELECT * FROM c IN t.gifts
This query will return the data from the gifts array for all items in the container. The t in t.gifts was arbitrary. We could have used any letter or word (except for c) to reference the item.
Results:
[ { "recipient": "Andrew", "gift": "blanket" }, { "recipient": "Deborah", "gift": "board game" }, { "recipient": "Chris", "gift": "coffee maker" }, … ]
This concept is especially useful if you need to filter on properties within the array.
For example, this query returns all gifts where the recipient is Andrew.
Query:
SELECT * FROM c IN t.gifts WHERE c.recipient = "Andrew"
However, once you’ve opted to iterate over an array by using the IN keyword in the FROM source, it isn’t possible to project or filter on any properties outside of that array. This limitation is solved by using JOINs.
JOINs
JOINs in Azure Cosmos DB are different from JOINs in relational databases. All JOINs in Cosmos DB are scoped within a single item. JOINs are a cross product between different sections of a single item.
For example, here’s a query that JOINs the gifts array with the rest of the item.
Query:
SELECT c.id, t AS gift FROM c JOIN t IN c.gifts
Results:
[ { "id": "Tim", "gift": { "recipient": "Andrew", "gift": "blanket" } }, { "id": "Tim", "gift": { "recipient": "Deborah", "gift": "board game" } }, … ]
In this case, the query returns all possible combinations for the id property and gifts array within each item. Using JOINs, you can construct more complex array queries, including queries that filter or project properties outside of the array.
Here’s an example query that adds on a filter for city, a property outside of the gifts array.
Query:
SELECT c.id, t AS gifts FROM c JOIN t IN c.gifts WHERE t.recipient = "Andrew" AND c.city = "Seattle"
Subqueries
A subquery is a query nested within another query. Azure Cosmos DB supports correlated subqueries. Correlated subqueries have the following uses when querying arrays:
Optimize JOIN expressions
We can optimize most queries with JOINs and filters by rewriting them to include a subquery. This optimization is recommended if you use JOIN on a large array that later has a filter. By using a subquery, the filter is applied before the JOIN, instead of afterwards. For example, the query in the prior example could be rewritten.
Query:
SELECT c.id, gifts FROM c JOIN (SELECT VALUE t FROM t IN c.gifts WHERE t.recipient = 'Andrew') AS gifts WHERE c.city = "Seattle"
EXISTS expression
The EXISTS expression, takes a subquery and returns true if the subquery returns at least one result. Because EXISTS take a subquery, it is more expressive than using ARRAY_CONTAINS, which is restricted to equality comparisons.
EXISTS stands out most from other array concepts because it can be used in the SELECT clause.
Query:
SELECT c.id, EXISTS(SELECT VALUE t FROM t IN c.gifts WHERE t.gift = "Coffee Maker") AS GivingCoffeeMaker FROM c WHERE c.city = "Seattle"
The above query returns all shopping lists from Seattle. It projects both the id value and a value that indicates whether that shopping list contains a coffee maker.
[ { "id": "Tim", "GivingCoffeeMaker": false }, { "id": "Thomas", "GivingCoffeeMaker": true } … ]
ARRAY projection
You can use the ARRAY expression to project the results of a query as an array. Using the ARRAY expression, in combination with a JOIN, makes it easy construct arrays in the query’s output. In this example, we’ll create a ShoppingList array in the query projection.
Query:
SELECT c.id, ARRAY(SELECT VALUE t.gift FROM t in c.gifts) as ShoppingList FROM c
Results:
[ { "id": "Tim", "ShoppingList": [ "blanket", "board game", "coffee maker" ] }, { "id": "Matt", "ShoppingList": [ "pillow", "gift card", "computer keyboard" ] } … ]
Here are more resources to learn about querying arrays in Azure Cosmos DB:
Tim Sander
Program Manager, Azure Cosmos DB
Follow
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK