Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmos: Stop nesting results in an extra JSON object #25527

Closed
roji opened this issue Aug 15, 2021 · 5 comments · Fixed by #34044
Closed

Cosmos: Stop nesting results in an extra JSON object #25527

roji opened this issue Aug 15, 2021 · 5 comments · Fixed by #34044
Assignees
Labels
area-cosmos area-query breaking-change closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement

Comments

@roji
Copy link
Member

roji commented Aug 15, 2021

Our basic Cosmos query looks like this:

SELECT c FROM root c

This produces results such as the following:

[
    {
        "c": {
            "id": "...",
            "Foo": 1,
        }
    },
    {
        "c": {
            "id": "...",
            "Foo": 2,
        }
    }
]

Instead, we could generate the following simpler star-based query:

SELECT VALUE c FROM root c

Which produces:

[
    {
        "id": "...",
        "Foo": 1,
    },
    {
        "id": "...",
        "Foo": 2,
    }
]
@ajcvickers
Copy link
Member

Note: breaking change because it impacts raw queries.

@ajcvickers ajcvickers added this to the Backlog milestone Feb 29, 2024
@roji
Copy link
Member Author

roji commented Jun 17, 2024

This creates issues since subqueries need to project out the bare object, rather than an object wrapping the object (interferes with query). We could have different logic for top-level projections (which are processed by the shaper) and subquery projections (which aren't), but we really should just do the right thing.

@roji roji changed the title Cosmos: Select documents directly without the extra nesting Cosmos: Stop nesting results in an extra JSON object Jun 20, 2024
@roji
Copy link
Member Author

roji commented Jun 20, 2024

Example test for trivial scalar projection, NorthwindSelectQueryTestBase.Select_scalar:

public virtual Task Select_scalar(bool async)
    => AssertQuery(
        async,
        ss => ss.Set<Customer>().Select(c => c.City));

Currently-generated NoSQL:

SELECT c["City"]
FROM root c
WHERE (c["Discriminator"] = "Customer")

Cosmos results:

[
    {
        "City": "Berlin"
    },
    {
        "City": "México D.F."
    },
    {
        "City": "México D.F."
    },
    {
        "City": "London"
    },
    ...
]

Proposed NoSQL:

SELECT VALUE c["City"]
FROM root c
WHERE (c["Discriminator"] = "Customer")

Cosmos results:

[
    "Berlin",
    "México D.F.",
    "México D.F.",
    "London",
    ...
]

@roji
Copy link
Member Author

roji commented Jun 20, 2024

And the same thing for a structural type projected out of the database, NorthwindSelectQueryTestBase.Select_customer_identity:

public virtual Task Select_customer_identity(bool async)
    => AssertQuery(
        async,
        ss => ss.Set<Customer>().Select(c => c));

Currently-generated NoSQL:

SELECT c
FROM root c
WHERE (c["Discriminator"] = "Customer")

Cosmos results:

[
    {
        "c": {
            "id": "Customer|ALFKI",
            ...
        }
    },
    {
        "c": {
            "id": "Customer|ANATR",
            ...
    },
    ....
]

Proposed NoSQL:

SELECT VALUE c
FROM root c
WHERE (c["Discriminator"] = "Customer")

Cosmos results:

[
    {
        "id": "Customer|ALFKI",
        ...
    },
    {
        "id": "Customer|ANATR",
        ...
    },
    ...
]

roji added a commit to roji/efcore that referenced this issue Jun 20, 2024
roji added a commit to roji/efcore that referenced this issue Jul 5, 2024
ajcvickers pushed a commit to roji/efcore that referenced this issue Jul 7, 2024
Closes dotnet#25527

Reimplement via ProjectionExpression.IsValueProjection

Materializer changes.

Revert "Update dependencies from https://github.com/dotnet/runtime build 20240602.3 (dotnet#33880)"

This reverts commit c7f369c.
@roji roji modified the milestones: Backlog, 9.0.0 Jul 20, 2024
@roji roji removed the needs-design label Jul 20, 2024
@roji
Copy link
Member Author

roji commented Jul 20, 2024

Note: Cosmos automatically filters out undefined values. So if, for example, a list of strings is projected out, and we stop wrapping return values with objects (as is currently the case), then any undefined values will be filtered out. The wrapping with an object means that an empty object is returned instead, which allows us to know about the undefined result.

The undefined filtering behavior makes sense when you consider that JSON properties may or may not exist; for example, if you project out property Foo of all documents, and some documents don't have that property, then those documents would get naturally filtered out of the results. However, this is a bit more problematic in other cases where undefined is returned. For example, many functions return undefined when given a null argument, e.g. project out the first character of some property. This returns undefined where the property is null (not undefined!), and therefore would filter out those documents as well. This causes a behavioral divergence with the LINQ-to-Objects evaluation, where you'd get a NullReferenceExpression (but at least no silent dropping of data).

We discussed this with the Cosmos team and decided to keep the Cosmos "native" or expecetd behavior, i.e. to project out using VALUE despite the undefined filtering behavior. Wrapping with an object could be worse performance-wise, and is generally not the expected/natural way to query Cosmos.

roji added a commit to roji/efcore that referenced this issue Jul 20, 2024
Closes dotnet#25527

Co-Authored-By: Arthur Vickers <ajcvickers@hotmail.com>
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Jul 21, 2024
@roji roji closed this as completed in d41ba67 Jul 21, 2024
@ajcvickers ajcvickers modified the milestones: 9.0.0, 9.0.0-preview7 Aug 21, 2024
@ajcvickers ajcvickers removed their assignment Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-cosmos area-query breaking-change closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants