Skip to content

fix populate depth and infinite recursion for Collection Links#1459

Open
beasteers wants to merge 2 commits intoagentejo:nextfrom
beasteers:fix-populate-1
Open

fix populate depth and infinite recursion for Collection Links#1459
beasteers wants to merge 2 commits intoagentejo:nextfrom
beasteers:fix-populate-1

Conversation

@beasteers
Copy link

Fixes: #1450

What is this about?

When using ?populate=1, ?populate=2, etc. when querying a collection with collectionlink fields, the populate query value also doubles as a max depth parameter. However, the index is off by 1, meaning that ?populate=1 will populate 2 depths and ?populate=0 will not populate anything meaning that it is currently impossible to populate only a depth of 1.

The issue is most apparent when you have a cyclical relationship between two collections. When you enable populate, it will automatically fill A->B->A instead of just A->B

Before

  • ?populate=0 gives: {"a": {link}}
  • not possible: {"a": {"b": {link}}}
  • ?populate=1 gives: {"a": {"b": {"a": {link}}}}

After

  • ?populate=0 gives: {"a": {link}}
  • ?populate=1 gives: {"a": {"b": {link}}}
  • ?populate=2 gives: {"a": {"b": {"a": {link}}}}

What this PR does:

It updates the logic of the populate function so that the value that the user passes actually aligns with the depth that they want to populate

Additionally, this also fixes infinite recursion for cyclical collections when ?populate=-1 by tracking the _id and collection values when populating.

Example Outputs using this PR:

Relationships:

  • a1 -> b1 -> a1
  • a2 -> b1 -> a1
// /api/collections/get/A?populate=0
{
    "entries": [
        {
            "name": "a1",
            "b": {"_id": "60ff73c9da60345fd133d081", "link": "B"},
            "_id": "60ff73aeadc8f87a9f76d611"
        },
        {
            "name": "a2",
            "b": {"_id": "60ff73c9da60345fd133d081", "link": "B"},
            "_id": "60fffe418c5238608847fc93"
        }
    ]
}
// /api/collections/get/A?populate=1
{
    "entries": [
        {
            "name": "a1",
            "b": {
                "name": "b1",
                "a": {"_id": "60ff73aeadc8f87a9f76d611", "link": "A"},
                "_id": "60ff73c9da60345fd133d081",
                "_link": "B"
            },
            "_id": "60ff73aeadc8f87a9f76d611"
        },
        {
            "name": "a2",
            "b": {
                "name": "b1",
                "a": {"_id": "60ff73aeadc8f87a9f76d611", "link": "A"},
                "_id": "60ff73c9da60345fd133d081",
                "_link": "B"
            },
            "_id": "60fffe418c5238608847fc93"
        }
    ]
}
// /api/collections/get/A?populate=2
// /api/collections/get/A?populate=3
// /api/collections/get/A?populate=4   (etc.)
// /api/collections/get/A?populate=-1
{
    "entries": [
        {
            "name": "a1",
            "b": {
                "name": "b1",
                "a": {
                    "_id": "60ff73aeadc8f87a9f76d611",
                    "link": "A"
                },
                "_id": "60ff73c9da60345fd133d081",
                "_link": "B"
            },
            "_created": 1627354030,
            "_id": "60ff73aeadc8f87a9f76d611"
        },
        {
            "name": "a2",
            "b": {
                "name": "b1",
                "a": {
                    "name": "a1",
                    "b": {
                        "_id": "60ff73c9da60345fd133d081",
                        "link": "B"
                    },
                    "_id": "60ff73aeadc8f87a9f76d611",
                    "_link": "A"
                },
                "_id": "60ff73c9da60345fd133d081",
                "_link": "B"
            },
            "_id": "60fffe418c5238608847fc93"
        }
    ],
}

Example Setup

Setup collections:

// POST /api/collections/createCollection
{
    "name": "A",
    "data": {
        "fields": [
            {"name": "name", "type": "text"},
            {"name": "b", "type": "collectionlink", "options": {"link": "B"}}
        ]
    }
}
// POST /api/collections/createCollection
{
    "name": "B",
    "data": {
        "fields": [
            {"name": "name", "type": "text"},
            {"name": "a", "type": "collectionlink", "options": {"link": "A"}}
        ]
    }
}

Setup entries:

// POST /api/collections/save/A
{ "data": [{"name": "a1"}, {"name": "a2"}] }
// get _id as _id_a1, _id_a2
// POST /api/collections/save/B
{ "data": [{"name": "b1"}, {"name": "b2"}] }
// get _id as _id_b1, _id_b2

// POST /api/collections/save/A
{ "data": [{"_id": _id_a1, "b": {"_id": _id_b1, "link": "B"}}, {"_id": _id_a2, "b": {"_id": _id_b1, "link": "B"}}] }

// POST /api/collections/save/B
{ "data": [{"_id": _id_b1, "a": {"_id": _id_a1, "link": "A"}, "b": null}, {"_id": _id_b2, "a": {"_id": _id_a1, "link": "A"}, "b": null}] }

sample docker-compose.yml

version: '2.4'

services:
  cockpit:
    container_name: cockpit
    build:
      context: "./"
    image: cockpit:dev
    volumes:
      - "./:/var/www/html"
    ports:
     - "8010:80"
    environment: {}
    restart: always

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

collection query populate depth is off by 1

1 participant