Azure / data-api-builder

Data API builder provides modern REST and GraphQL endpoints to your Azure Databases and on-prem stores.
https://aka.ms/dab/docs
MIT License
854 stars 177 forks source link

DAB Engine : Cannot query items with embedded data model type #1266

Closed sajeetharan closed 7 months ago

sajeetharan commented 1 year ago

I am trying to update the getting started docs for azure cosmos db with embedded data model type and facing this issue.

Sample Document:

{
    "id": "1000",
    "title": "Foundation",
    "authors": [
        {
            "id": "1",
            "first_name": "Isaac",
            "middle_name": "",
            "last_name": "Asimov"
        },
        {
            "id": "2",
            "first_name": "Lewis",
            "middle_name": "",
            "last_name": "Carroll"
        }
    ],
    "_rid": "67ZCAPXHLxoBAAAAAAAAAA==",
    "_self": "dbs/67ZCAA==/colls/67ZCAPXHLxo=/docs/67ZCAPXHLxoBAAAAAAAAAA==/",
    "_etag": "\"3e05c8f7-0000-0700-0000-63fb760b0000\"",
    "_attachments": "attachments/",
    "_ts": 1677424139
}

and here is the schema.gql

type Book @model {
  id: ID
  title: String
  Authors: [Author]
}

type Author {
  id: ID
  first_name: String
  middle_name: String
  last_name: String
}

and config.file

{
  "$schema": "dab.draft.schema.json",
  "data-source": {
    "database-type": "cosmosdb_nosql",
    "options": {
      "database": "PlaygroundDB",
      "schema": "schema.gql"
    },
    "connection-string": " "
  },
  "runtime": {
    "rest": {
      "path": "/api"
    },
    "graphql": {
      "allow-introspection": true,
      "path": "/graphql"
    },
    "host": {
      "mode": "development",
      "cors": {
        "origins": [],
        "allow-credentials": false
      },
      "authentication": {
        "provider": "StaticWebApps"
      }
    }
  },
  "entities": {
    "Book": {
      "source": "books",
      "rest": false,
      "graphql": true,
      "permissions": [
        {
          "role": "anonymous",
          "actions": [
            "*"
          ]
        }
      ]
    }
  }
}

when I tried to query the books and its authors, authors is being returned as null.

query{ books { items{ id, title Authors { id, first_name, last_name } } } }

Result:

 {
  "data": {
    "books": {
      "items": [
        {
          "id": "1000",
          "title": "Foundation",
          "Authors": null
        },
        {
          "id": "1001",
          "title": "Foundation and Empire",
          "Authors": null
        },
        {
          "id": "1002",
          "title": "Second Foundation",
          "Authors": null
        },
        {
          "id": "1008",
          "title": "Nightwings",
          "Authors": null
        }
      ]
    }
  }
}
mbhaskar commented 1 year ago

Having Authors -> authors mapping somewhere is what we need Generally when we annotate the other object (in this case Author) as a @model, it creates the mapping with graphql model name to cosmos model name. But in this case as this is not a model, we don't annotate it, and there is no mapping created in the config so engine is generating the cosmos sql query as select c.id, c.title, c.Authors from c 

So as a workaround, having the json field name match exactly with the graphql object name would get it working.

 {
    "id": "1002",
    "title": "Second Foundation",
    "Authors": [{
        "id": "1",
        "first_name": "Isaac",
        "middle_name": "",
        "last_name": "Asimov"
    }]
 }

authors->Authors

This could be called a limitation for now, I will also explore a solution

aaronpowell commented 1 year ago

In this case though we shouldn't need the @model directive for the Author type as that type isn't one that we want to store outside of the Book type in our container (and we don't want queries or mutations for).

Is the problem really that the type in GraphQL doesn't match the type that we have in the JSON document, as it's authors not Authors?

@sajeetharan can you try changing the case of the field on the document as see if that fixes the problem?

Maybe it's worth adding a directive like @storeAs('...') so that you can specific a "mapping" between the field in GraphQL and the field in the Cosmos document, allowing you to change casing when it's returned to the client.

sourabh1007 commented 7 months ago

@sajeetharan I tried this scenario and it worked fine when in schema file Authors was defined as author.

Below schema would work for your scenario

type Book @model {
  id: ID
  title: String
  authors: [Author] // Notice small case 'a' in authors
}

type Author {
  id: ID
  first_name: String
  middle_name: String
  last_name: String
}
sajeetharan commented 7 months ago

changing the case of the field worked for this! closing it for now!