v8-archive icon indicating copy to clipboard operation
v8-archive copied to clipboard

Consuming relational fields through the API is messy

Open justrealmilk opened this issue 4 years ago • 8 comments

I've built a collection for a client who is obsessed with custom metadata. The best fit for them was to use a bunch of M2Ms. Retrieving this data through the API is hectic.

/_/items/portfolio?fields=*.*,content.portfolio_content_id.*.*,content.portfolio_content_id.files.directus_files_id.*,disciplines.portfolio_disciplines_id.name,discipline_code.portfolio_item_discipline_codes_id.code,purposes.portfolio_purposes_id.name,topics.portfolio_topics_id.name,type.portfolio_types_id.name,hardware.portfolio_hardware_id.name,software.portfolio_software_id.name

In order to prevent it from returning the root item 20 times, I needed to specify the tables (fields?) that I wanted it to return.

This results in a really bizarre data structure to work with on the front end.

How do I essentially flatten the request, removing several layers of unnecessary nested objects? Should I build a custom endpoint for this (how?)?

justrealmilk avatar Aug 12 '19 02:08 justrealmilk

Any thoughts @bjgajjar @hemratna @rijkvanzanten ?

benhaynes avatar Aug 12 '19 18:08 benhaynes

The best fit for them was to use a bunch of M2Ms.

This is hard to tell without more context on what schema you're going for. You can oftentimes get away with using checkboxes + custom values there for categories and the like.

Alternatively, you can give the GraphQL endpoint a shot, although I can't say anything about it's output (I'm personally not familiar with GraphQL).

rijkvanzanten avatar Aug 12 '19 18:08 rijkvanzanten

Hi, @justrealmilk give GraphQL a try. In the GraphQL you have to specify each key in the request.

hemratna avatar Aug 19 '19 06:08 hemratna

Hi, @justrealmilk give GraphQL a try. In the GraphQL you have to specify each key in the request.

@hemratna but is the response still full of nested objects?

justrealmilk avatar Aug 19 '19 06:08 justrealmilk

@hemratna but is the response still full of nested objects?

Yes, It will.

hemratna avatar Aug 19 '19 09:08 hemratna

@justrealmilk — IMO, if you request a lot of different fields with different depths, all of that should exist within one nested data object. Are you saying that each field request is being returned in its own object? Do you have some examples of output that we can see to better illustrate the problem you're facing?

benhaynes avatar Aug 27 '19 13:08 benhaynes

{
  "data": [
    {
      "sort": null,
      "name": "Mars Future Vision",
      "slug": "mars-future-vision",
      "date": "2018-06-18",
      "id": 1,
      "primary_discipline": { "id": 2, "name": "Interaction Design", "code": "04 IN" },
      "status": "published",
      "disciplines": [{ "portfolio_disciplines_id": { "id": 1, "name": "Concept design", "code": "03 CO" } }, { "portfolio_disciplines_id": { "id": 2, "name": "Interaction Design", "code": "04 IN" } }],
      "type": [{ "portfolio_types_id": { "name": "Commercial" } }],
      "hardware": [{ "portfolio_hardware_id": { "name": "Cintiq 22HD" } }],
      "purposes": [{ "portfolio_purposes_id": { "name": "Inspire" } }, { "portfolio_purposes_id": { "name": "Educate" } }],
      "software": [{ "portfolio_software_id": { "name": "SketchUp" } }],
      "topics": [{ "portfolio_topics_id": { "name": "Education" } }, { "portfolio_topics_id": { "name": "Space sciences" } }, { "portfolio_topics_id": { "name": "Futures" } }]
    },
    {
      "sort": null,
      "name": "Medical Robotics",
      "slug": "medical-robotics",
      "date": "2018-08-10",
      "id": 2,
      "primary_discipline": { "id": 1, "name": "Concept design", "code": "03 CO" },
      "status": "published",
      "disciplines": [{ "portfolio_disciplines_id": { "id": 2, "name": "Interaction Design", "code": "04 IN" } }],
      "type": [{ "portfolio_types_id": { "name": "Commercial" } }, { "portfolio_types_id": { "name": "Personal" } }],
      "hardware": [{ "portfolio_hardware_id": { "name": "Cintiq 22HD" } }],
      "purposes": [{ "portfolio_purposes_id": { "name": "Inspire" } }],
      "software": [{ "portfolio_software_id": { "name": "SketchUp" } }, { "portfolio_software_id": { "name": "3ds Max" } }],
      "topics": [{ "portfolio_topics_id": { "name": "Futures" } }]
    }
  ],
  "public": true
}

This a response to a very similar query to the OP's.

Requesting simply the disciplines field results in: "disciplines": [{ "portfolio_id": 2, "portfolio_disciplines_id": 2, "id": 4 }].

The good stuff is portfolio_disciplines_id. Even though the parent object is where portfolio_id lives, it's also returned. To get the actual data, you need to use an asterisk a la disciplines.* but this expands the objects for both of the aforementioned fields.

If you're still following my poor explanation, this means that the parent object is repeated in a child field because of the way the collection is set up with relations etc.

The solution? Super complicated and specific query parameters i.e. disciplines.portfolio_disciplines_id.*. This can be exhaustive when you have many similar fields 😅

justrealmilk avatar Aug 27 '19 22:08 justrealmilk

Are there any news on this? Querying a pretty simple m:n. relation already has at least one (for me) unnecessary level of nesting:

        // Recipe
        {
            "name": "breakfast",
            "ingredients": [
                {
                    "ingredient_id": {
                        "name": "eggs"
                    }
                },
                {
                    "ingredient_id": {
                        "name": "potatoes"
                    }
                }
            ],
        },

In this case to be able to have the API respond either in this way:

        // Recipe
        {
            "name": "breakfast",
            "ingredients": [
                "eggs",
                "potatoes"
            ],
        },

or at least:

        // Recipe
        {
            "name": "breakfast",
            "ingredients": [
                {
                    "name": "eggs"
                },
                {
                    "name": "potatoes"
                }
            ],
        },

tadeussenf avatar Dec 28 '21 16:12 tadeussenf