<p>You're manually iterating through all matrix blocks, then you iterate again through all tags in that block. So if multiple blocks include the same tag, of course you're going to see the tag multiple times.</p>
<p>To fix this, instead of manually looping through the matrix blocks, use a single <a href="https://craftcms.com/docs/4.x/tags.html#querying-tags" rel="nofollow noreferrer">tag query</a> to find all tags that are related to any of the matrix blocks on the current entry:</p>
<pre class="lang-twig prettyprint-override"><code>{% set matrixBlocks = entry.events.ids() %}

{% set tagsInMatrixBlocks = craft.tags()
    .group('topics')
    .relatedTo({
        field: 'topics',
        sourceElement: matrixBlocks,
    })
    .orderBy('title ASC')
    .all()
%}
</code></pre>
<p>Because this is a single query, you avoid duplicates. As a nice benefit, you can also sort the query however you'd like, in this case alphabetically. Note the use of <code>ids()</code> instead of <code>all()</code>. We don't need the full matrix blocks in this case, so we only retrieve a list of IDs from the database to improve performance. Then we use <code>relatedTo</code> to find all tags in the <code>topics</code> group (replace with the handle of your tags group) that are related to any of those matrix blocks; the specific form of the <code>relatedTo</code> parameter further limits the query to relations in the <code>topics</code> field where the matrix block is the <em>source</em> element, i.e. the element where the related tags are selected. See the <a href="https://craftcms.com/docs/4.x/relations.html" rel="nofollow noreferrer">documentation on relations</a> for more details and examples.</p>
<p>The tag query returns an array of <a href="https://docs.craftcms.com/api/v4/craft-elements-tag.html" rel="nofollow noreferrer">Tag objects</a>, you can iterate through the array and access all properties and custom fields on it:</p>
<pre class="lang-twig prettyprint-override"><code>{% for tag in tagsInMatrixBlocks %}
    {{ tag.title }}
{% endfor %}
</code></pre>

CC BY-SA 4.0
2023-04-03T19:52:16.907Z
Thank you! That all makes sense. Then how do I output that? Should it be: `{% for tag in tagsInMatrixBlocks %}{{ tag.title }}{% endfor %}` ?
univers0
CC BY-SA 4.0
2023-04-04T08:23:51.457Z
@univers0 Yes, that's right. I've added a code example to my answer.
MoritzLost
CC BY-SA 4.0
2023-04-02T14:10:11.747Z
2023-04-04T08:23:25.860Z
2023-04-04T08:23:25.860Z
MoritzLost
<p>I have a matrix field that includes a tags field. The matrix includes a list of events, with each event using the tag field to determine topics. I'd like to output a list of each tag used, so I can filter the events by those tags. When I try to output the tags, I get every instance of the tag being used, rather than just a list of each unique tag. Where am I going wrong?</p>
<pre><code>{% for block in entry.events %}
    {% for tag in block.topics %}
            {{ tag.title }}
    {% endfor %}
{% endfor %}
</code></pre>

<matrix><tags>
Retrieve tags used in matrix field
# Retrieve tags used in matrix field

(Asked by: username_0 on 2023-03-31)

I have a matrix field that includes a tags field. The matrix includes a list of events, with each event using the tag field to determine topics. I'd like to output a list of each tag used, so I can filter the events by those tags. When I try to output the tags, I get every instance of the tag being used, rather than just a list of each unique tag. Where am I going wrong?
{% for block in entry.events %}
    {% for tag in block.topics %}
            {{ tag.title }}
    {% endfor %}
{% endfor %}

**Tags:** matrix, tags


---

## 1 answers

### Answer by username_1 on 2023-04-02. Score: 2

You're manually iterating through all matrix blocks, then you iterate again through all tags in that block. So if multiple blocks include the same tag, of course you're going to see the tag multiple times.
To fix this, instead of manually looping through the matrix blocks, use a single tag query to find all tags that are related to any of the matrix blocks on the current entry:
{% set matrixBlocks = entry.events.ids() %}

{% set tagsInMatrixBlocks = craft.tags()
    .group('topics')
    .relatedTo({
        field: 'topics',
        sourceElement: matrixBlocks,
    })
    .orderBy('title ASC')
    .all()
%}

Because this is a single query, you avoid duplicates. As a nice benefit, you can also sort the query however you'd like, in this case alphabetically. Note the use of ids() instead of all(). We don't need the full matrix blocks in this case, so we only retrieve a list of IDs from the database to improve performance. Then we use relatedTo to find all tags in the topics group (replace with the handle of your tags group) that are related to any of those matrix blocks; the specific form of the relatedTo parameter further limits the query to relations in the topics field where the matrix block is the source element, i.e. the element where the related tags are selected. See the documentation on relations for more details and examples.
The tag query returns an array of Tag objects, you can iterate through the array and access all properties and custom fields on it:
{% for tag in tagsInMatrixBlocks %}
    {{ tag.title }}
{% endfor %}

> **Comments:**
> **username_0**: Thank you! That all makes sense. Then how do I output that? Should it be: `{% for tag in tagsInMatrixBlocks %}{{ tag.title }}{% endfor %}` ?  
> **username_1**: @username_0 Yes, that's right. I've added a code example to my answer.  

---

