# Link several entities to another entity

**URL:** <https://community.fibery.io/t/link-several-entities-to-another-entity/6015>\
**Category:** Get Help\
**Created:** [March 25, 2024, 1:39am UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015 "2024-03-25T01:39:18Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 1:39am UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/1 "2024-03-25T01:39:18Z")

</div>

Hi, I recently opened a [thread](https://community.fibery.io/t/entity-key-for-gitlab-integration/6010/4) on using Public Id integration with gitlab and I’ve been studying the documentation about [relation auto-linking](https://the.fibery.io/@public/User_Guide/Guide/Set-Relations-Automatically-(Auto-Linking)-50)

And I came to the conclusion that the existing solution does not suit me, because my commits have the following structure

```auto
fix: fix incorrect behaviour

META: task/2, bug/3

```

as MR can close a bug or several tasks in parallel. Due to the fact that I didn’t find the `Description` field with Gitlab MR (there is only `Name`). I was forced to use the script below to get all the related entities with MR. it’s fragile and redundant, but it works. Could you please advise if there is any other way to accomplish this task?

what’s interesting:

1. Is there any way to set global variables? I used another database for storage and reading  
` const token = await fibery.getEntityById('Runa/Env', 'd27260a0-e9f3-11ee-9f13-81b4ace4cd35', ['Value'])`
2. How do I get the MP description otherwise? I only got it by querying gitlab.

```auto
const fibery = context.getService('fibery');
const syncIdRegex = /^.*?_(.*?)_(.*?)_/;
const metaRegex = /META:\s*([^\n]+)/
const mrIdRegex = /(\d+)(?!.*\d)/
const entityRegex = /(\w+)\/(\d+)/;

for (const entity of args.currentEntities) {
    const { ['Sync Id']: syncId, ['GitLab Link']: gitlabLink } = entity

    const projectId = syncId.match(syncIdRegex)[1];
    const mrId = gitlabLink.match(mrIdRegex)[1]

    const http = context.getService('http');

    const token = await fibery.getEntityById('Runa/Env', 'd27260a0-e9f3-11ee-9f13-81b4ace4cd35', ['Value'])

    const { description } = JSON.parse(
        await http.getAsync(`https://gitlab.com/api/v4/projects/${projectId}/merge_requests/${mrId}`, {
            headers: {
                'Content-type': 'application/json',
                'PRIVATE-TOKEN': token.Value
            }
        })
    );

    if (metaRegex.test(description)) {
        const meta = description.match(metaRegex)[1]

        const items = meta.split(/,\s*/)

        for (const item of items) {
            const [_, type, id] = item.match(entityRegex);

            switch (type) {
                case 'task':
                case 'bug':
                    const alias = type[0].toUpperCase() + type.slice(1)
                    const [related] = await fibery.executeSingleCommand({
                        "command": "fibery.entity/query",
                        "args": {
                            "query": {
                                "q/from": `Runa/${alias}`,
                                "q/select": [
                                    'fibery/id',
                                    'fibery/public-id',
                                ],
                                'q/where': ['=', 'fibery/public-id', "$id"],
                                "q/limit": 1
                            },
                            "params": {
                                "$id": id,
                            }
                        }
                    });

                    if (related) {
                        await fibery.addCollectionItem(entity.type, entity.id, `${alias}s`, related['fibery/id']);
                    }

                    break;
                default:
                    console.log(`Sorry, incorrect entity type - ${type}.`);
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 11:16am UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/2 "2024-03-25T11:16:08Z")

</div>

> [@ravecat](#):
>
> Due to the fact that I didn’t find the `Description` field with Gitlab MR (there is only `Name`).

The Description field for Gitlab merge requests should be included in the sync.

And given that it is, you can probably achieve what you need by using a `ReplaceRegex([Description (Snippet)],....)` function to extract the task and bug ids (assuming that the description does not exceed the limit for what’s included in a snippet (1000 chars).

---

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 11:42am UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/3 "2024-03-25T11:42:59Z")

</div>

@Chr1sG Thanks for the reply, I have a few questions.

My commit contains the following description

```auto
fix: fix incorrect behaviour

META: task/2, bug/3

```

and yes, I see body part inside MR entity

 ![image](https://us1.discourse-cdn.com/flex020/uploads/fibery/original/2X/b/b3a9c7b78b795a71d21a158b76ceee68c37d25e4.png)

> [@Chr1sG](#):
>
> The Description field for Gitlab merge requests should be included in the sync.

but his presentation is very strange, maybe I’m doing something wrong.

```auto
const fibery = context.getService('fibery');

for (const entity of args.currentEntities) {
    const ent = await fibery.getEntityById(entity.type, entity.id, ['Description']);

    console.log(ent)
}

```

return

```auto
{
  Id: '11db5b76-edb5-41bc-8525-03a228ebedce',
  Description: {
    Secret: 'b060dacb-1653-4d04-b4c1-0a133e6e4033',
    Id: '7068bdfe-8c72-402b-bd28-3be29835a678'
  }
}

```

> [@Chr1sG](#):
>
> And given that it is, you can probably achieve what you need by using a `ReplaceRegex([Description (Snippet)],....)` function to extract the task and bug ids

I didn’t understand the context in which to apply this, could you give an example or link to the documentation

Thank you.

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 11:46am UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/4 "2024-03-25T11:46:32Z")

</div>

> [@ravecat](#):
>
> > [@Chr1sG](#):
> >
> > And given that it is, you can probably achieve what you need by using a `ReplaceRegex([Description (Snippet)],....)` function to extract the task and bug ids
> 
> I didn’t understand the context in which to apply this, could you give an example or link to the documentation

I meant that you can create a formula field to extract the task id, and a separate one to extract the bug id.  
(no need to use scripts)

But having said that, it still is challenging to autolink if you need to link to multiple tasks (or multiple bugs) 😕

---

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 12:05pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/5 "2024-03-25T12:05:58Z")

</div>

@Chr1sG why such a strange representation of the block`Description`? If it was in understandable text, I wouldn’t need to API to gitlab

```auto
{
  Id: '11db5b76-edb5-41bc-8525-03a228ebedce',
  Description: {
    Secret: 'b060dacb-1653-4d04-b4c1-0a133e6e4033',
    Id: '7068bdfe-8c72-402b-bd28-3be29835a678'
  }
}

```

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 12:25pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/6 "2024-03-25T12:25:43Z")

</div>

> [@ravecat](#):
>
> why such a strange representation of the block`Description`?

Because [rich text fields are not like other fields](https://the.fibery.io/@public/User_Guide/Guide/Field-API-263/anchor=Rich-text-Field--a2a8947a-579b-4e7b-b9d1-a8ab7c2a9b4a).

Basically, you need to use the `getDocumentContent` function.  
See [here](https://the.fibery.io/@public/User_Guide/Guide/Scripts-in-Automations-54/anchor=Fibery-service-workspace-functions--86ec1778-15d4-42dc-a533-a57ec38bc855).

---

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 2:55pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/7 "2024-03-25T14:55:04Z")

</div>

@Chr1sG thanks for the tip with `getDocumentContent` it simplified the script

```auto
const fibery = context.getService('fibery');

const metaRegex = /META:\s*((?:\w+\/\d+(?:,\s*)?)+)/g
const entitiesRegex = /\w+\/\d+/g;

for (const entity of args.currentEntities) {
    const { ['Description']: { secret } } = await fibery.getEntityById(entity.type, entity.id, ['Description']);

    const description = await fibery.getDocumentContent(secret)

    if (metaRegex.test(description)) {
        const [meta] = description.match(metaRegex)

        const items = meta.match(entitiesRegex)

        for (const item of items) {
            const [type, id] = item.split("/");

            switch (type) {
                case 'task':
                case 'bug':
                    const alias = type[0].toUpperCase() + type.slice(1)
                    const [related] = await fibery.executeSingleCommand({
                        "command": "fibery.entity/query",
                        "args": {
                            "query": {
                                "q/from": `Runa/${alias}`,
                                "q/select": [
                                    'fibery/id',
                                    'fibery/public-id',
                                ],
                                'q/where': ['=', 'fibery/public-id', "$id"],
                                "q/limit": 1
                            },
                            "params": {
                                "$id": id,
                            }
                        }
                    });

                    if (related) {
                        await fibery.addCollectionItem(entity.type, entity.id, `${alias}s`, related['fibery/id']);
                    }

                    break;
                default:
                    console.log(`Sorry, incorrect entity type - ${type}.`);
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 3:02pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/8 "2024-03-25T15:02:58Z")

</div>

Looks good.

FWIW you might find using a graphQl query a bit simpler/easier than using the `executeSingleComman`d method.

---

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 3:32pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/9 "2024-03-25T15:32:27Z")

</div>

To be honest, I didn’t understand how to use graphql in the context of automation, the examples in the documentation didn’t make it clear. maybe I was looking in the wrong place

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 4:04pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/10 "2024-03-25T16:04:58Z")

</div>

You can replace the `executeSingleCommand` with something like this instead:

```auto
const response = await fibery.graphql('Runa', 'query getBug($searchId:String){findBugs(publicId:{is:$searchId}){id}}',{'searchId':id});

```

You will get a response like this:

```auto
{
  data: {
    findBugs: [{ id: '7034d130-2984-4c9f-bdaa-390a3b2f60f4' }]
  }
}

```

which you can then easily use later in your `addCollectionItem` function call:

`const bug = response.data.findBugs[0].id`

---

<div class="post-metadata">

**Author:** ![ravecat](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/ravecat/32/9071_2.png) [@ravecat](https://community.fibery.io/u/ravecat)\
**Post date:** [March 25, 2024, 4:25pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/11 "2024-03-25T16:25:48Z")

</div>

Yep, looks cleaner, but, as unterstand, I need implement branch for Task, Bug, etc entity

And also what is `getBug`? Is predefined function fo entity?

Thank you for your responses

---

<div class="post-metadata">

**Author:** ![Chr1sG](https://sea2.discourse-cdn.com/flex020/user_avatar/community.fibery.io/chr1sg/32/3941_2.png) [@Chr1sG](https://community.fibery.io/u/Chr1sG)\
**Post date:** [March 25, 2024, 4:32pm UTC](https://community.fibery.io/t/link-several-entities-to-another-entity/6015/12 "2024-03-25T16:32:56Z")

</div>

> [@ravecat](#):
>
> I need implement branch for Task, Bug, etc entity

Yeah, it is db specific, but `addCollectionItem` is db-specific too, so no real difference performance wise. It would need maintaining if you think the types are likely to change over time, but that scenario would also require you to update your script to specify them.

> [@ravecat](#):
>
> And also what is `getBug`? Is predefined function fo entity?

No, it’s just a query name, you could choose anything.
