azureazure-cosmosdbazure-cosmosdb-sqlapi

Filter document based on properties in child object in CosmosDb SQL


I want to get any document with test url in ui template

Ex: Input

    {
        "id": "id1",,
        "EntityType": "metadata",
        "UITemplates": {
            "p1": [
                {
                    "DisplayText": "UiDefinition.json",
                    "UrlString": "https://1-test",
                    "SubType": "Custom"
                },
                {
                    "DisplayText": "createuidefinition",
                    "UrlString": "https://2-prod",
                    "SubType": "Custom"
                }
            ],
            "d3": [
                {
                    "DisplayText": "UiDefinition.json",
                    "UrlString": "https://11-test",
                    "SubType": "Custom"
                },
                {
                    "DisplayText": "createuidefinition",
                    "UrlString": "https://22-test",
                    "SubType": "Custom"
                }
            ]
        }
    }

Output: The list of id that the doc has "test" in the UrlString

[{"id", "id1"}]

The point that block me is how to get the properties from the listinguitemplates into a array, and I can use ArrayContains or self-join later to just filter it out.

Self-join but need to know the properties name under listinguitemplate beforehand

Tried to flatten but return empty
SELECT c
FROM c
JOIN p IN (
    SELECT VALUE item
    FROM item IN (
        SELECT VALUE t
        FROM t IN c.UITemplates
    )
)
If can know the fixed field of properties before
SELECT c.id, t.UrlString
FROM c
JOIN t IN c.UITemplates.p1

Result
[
    {
        "id": "id1",
        "UrlString": "https://1-test"
    },
    {
        "id": "id1",
        "UrlString": "https://2-prod"
    }
]

https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/join#self-join-with-a-single-item

https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/array-contains

Can anyone shed some lights for me, thanks


Solution

  • Find that there is an sql function to map object properties into array Since in operator only work on array, not the object properties, so need to transform properties into array first

    SELECT DISTINCT c.id
    FROM c
    JOIN t in (SELECT VALUE ObjectToArray(c.UITemplates))
    JOIN p in t.v
    WHERE CONTAINS(p.UrlString, "test")