ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.23k stars 745 forks source link

Order By Child-Parent-Child Yields "There can be only one input field named Child" #4657

Closed bbingCGI closed 2 years ago

bbingCGI commented 2 years ago

Is there an existing issue for this?

Describe the bug

Ordering requires a sequential narrative presently, such as "order by Last Name, then by First Name, then by Age". Because of this, if a query needs to order by parent and child properties where the child's properties are not back-to-back, the dreaded "There can only be one input field named Child" will appear.

Steps to reproduce

I've created a repository to pull down and demonstrate the following example.

  1. Ensure the root entity represented in the query has at least one child.
  2. Order by a child property, then parent property, then child.
  3. Attempt to execute the query

Sample query

query {
  people (order: {
    demographic: { gender: ASC }
    address: { state: ASC }
    demographic: { age: ASC }
  }) {
    lastName
    demographic {
      gender
      age
    }
    address {
      city
      state
    }
  }
}

Relevant log output

{
  "errors": [
    {
      "message": "There can be only one input field named `demographic`.",
      "locations": [
        {
          "line": 5,
          "column": 5
        }
      ],
      "path": [
        "people"
      ],
      "extensions": {
        "field": "demographic",
        "specifiedBy": "http://spec.graphql.org/October2021/#sec-Input-Object-Field-Uniqueness"
      }
    }
  ]
}

Additional Context?

Note that this only applies to order. Filters don't care about what order they are entered and can be grouped by child objects.

A possible workaround would be to use the array option like the where's and and or can use:

query {
  people (order: [
    { demographic: { gender: ASC } }
    { address: { state: ASC } }
    { demographic: { age: ASC } }
  ]) {
    lastName
    demographic {
      gender
      age
    }
    address {
      city
      state
    }
  }
}

Product

Hot Chocolate

Version

12.5.0

bbingCGI commented 2 years ago

Being as changing order from an object descriptor to an array, that would be a breaking change. Perhaps adding a operation like the and operation in the filter convention would keep it from breaking existing functionality. Something like by?

query {
  people (order: { by: [
    { demographic: { gender: ASC } }
    { address: { state: ASC } }
    { demographic: { age: ASC } }
  ]}) {
    lastName
    demographic {
      gender
      age
    }
    address {
      city
      state
    }
  }
}
PascalSenn commented 2 years ago

order is already an array, so you can do

query {
  people(
    order: [
      { demographic: { gender: ASC } }
      { address: { state: ASC } }
      { demographic: { age: ASC } }
    ]
  ) {
    lastName
    demographic {
      gender
      age
    }
    address {
      city
      state
    }
  }
}