<p>First, based on your example code I don't think you actually need to loop on the entries – you could simply group them on the brand name, and then loop on the keys for the grouped array (the keys would be your brand names):</p>

<pre><code>{% set brands = allEntries|group('brand')|keys %}

{% for brand in brands %}
     &lt;option value="{{ brand }}"&gt;{{ brand }}&lt;/option&gt;
{% endfor %}
</code></pre>

<p>So that's a slight optimization, but you'd still be pulling ~18k entries to print ~140 brand names and I'm not sure the above wouldn't still crash your server – so ideally you should probably use a different strategy altogether.</p>

<p>If you're comfortable w/ writing a little PHP, I'd suggest you <a href="http://pluginfactory.io" rel="nofollow noreferrer">scaffold a custom plugin</a> – make sure that the <em>Variables</em> component is included, and add something like the below to the <code>variables/YourPluginHandleVariable.php</code> class:</p>

<pre><code>public function getBrands()
{
    $query = craft()-&gt;db-&gt;createCommand();
    $query-&gt;selectDistinct('field_brand');
    $query-&gt;from('content');
    return array_filter($query-&gt;queryColumn());
}
</code></pre>

<p>In your template, you'd use this like so:</p>

<pre><code>{% set brands = craft.yourPluginHandle.getBrands() %}

{% for brand in brands %}
     &lt;option value="{{ brand }}"&gt;{{ brand }}&lt;/option&gt;
{% endfor %}
</code></pre>

<p>Be sure to replace <code>yourPluginHandle</code> and <code>YourPluginHandleVariable</code> with the actual handle for your plugin.</p>

<p>Note that I haven't actually tested the above w/ as many as +18k rows, so even a distinct select query might not be performant enough. Of course, you can always <a href="https://craftcms.com/docs/templating/cache" rel="nofollow noreferrer">cache</a> the result.</p>

CC BY-SA 3.0
2017-09-26T00:37:02.950Z
I had a feeling a plugin would be the way to go with that volume of entries. This is exactly the guidance I was looking for. Thanks so much!
MikeeBee
CC BY-SA 3.0
2017-09-26T00:38:28.220Z
Awesome. If you get the chance, a report back on the performance would be interesting (if it even works, as I said I've not tested this w/ the volume of entries you have) :)
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2017-10-05T02:42:01.753Z
This worked great. Took around 3.5 seconds to go through 18438 entries. I'm very happy, thank you!
MikeeBee
CC BY-SA 3.0
2017-10-05T07:00:18.480Z
That's good to hear, 3.5 secs is still *a lot* though, if this happens every pageload...
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2017-10-05T21:26:00.850Z
Yeah it's still a lot for a page load generally, but compared to the minute plus it was taking, this is a great improvement! And as you say, I can cache the result. These entries will only change every few months.
MikeeBee
CC BY-SA 3.0
2017-10-05T21:34:30.967Z
Cool, and thanks for the follow-up! If the entries only change every few months, I'd say you're OK :) For the caching part, since you're dealing with such a huge number of elements you might want to check out my [CacheFlag](https://github.com/mmikkel/CacheFlag-Craft) plugin – it may prove useful over the native `{% cache %}` tag in your case.
Mats Mikkel Rummelhoff
CC BY-SA 3.0
2017-09-25T11:19:39.860Z
2017-09-25T11:19:39.860Z
Mats Mikkel Rummelhoff
<p>I have imported data with 18000+ entries. It's a list of product models with brands associated to each. The product model is being used as the title and the brand field is plain text.</p>

<p>There are approximately 140 brands which I need to output as a dropdown.</p>

<p>I can't output this many entries and then try and group (and order them) on the template as it crashes the page.</p>

<p>This is code that would work if it didn't crash the page (and would take minutes to load the page even if it didn't).</p>

<pre><code>{% set allEntries = craft.entries.section('solarWaterHeaterModels').order('brand asc').limit(null).find() %}

{% set allEntriesByBrand = allEntries|group('brand') %}

{% for brand, entriesInBrand in allEntriesByBrand %}

    {% for entry in entriesInBrand %}
        {% if loop.index == 1 %}
            &lt;option value="{{ entry.brand }}"&gt;{{ entry.brand }}&lt;/option&gt;
        {% endif %}
    {% endfor %}

{% endfor %}
</code></pre>

<p>Can anyone offer some guidance on how to approach this please?</p>

<p>Many thanks</p>

<group><eager-loading>
Grouping a large number of entries
# Grouping a large number of entries

(Asked by: username_0 on 2017-09-25)

I have imported data with 18000+ entries. It's a list of product models with brands associated to each. The product model is being used as the title and the brand field is plain text.
There are approximately 140 brands which I need to output as a dropdown.
I can't output this many entries and then try and group (and order them) on the template as it crashes the page.
This is code that would work if it didn't crash the page (and would take minutes to load the page even if it didn't).
{% set allEntries = craft.entries.section('solarWaterHeaterModels').order('brand asc').limit(null).find() %}

{% set allEntriesByBrand = allEntries|group('brand') %}

{% for brand, entriesInBrand in allEntriesByBrand %}

    {% for entry in entriesInBrand %}
        {% if loop.index == 1 %}
            {{ entry.brand }}
        {% endif %}
    {% endfor %}

{% endfor %}

Can anyone offer some guidance on how to approach this please?
Many thanks

**Tags:** group, eager-loading

---

## 1 answers

### Answer by username_1 on 2017-09-25. Score: 2 | Accepted answer

First, based on your example code I don't think you actually need to loop on the entries – you could simply group them on the brand name, and then loop on the keys for the grouped array (the keys would be your brand names):
{% set brands = allEntries|group('brand')|keys %}

{% for brand in brands %}
     {{ brand }}
{% endfor %}

So that's a slight optimization, but you'd still be pulling ~18k entries to print ~140 brand names and I'm not sure the above wouldn't still crash your server – so ideally you should probably use a different strategy altogether.
If you're comfortable w/ writing a little PHP, I'd suggest you scaffold a custom plugin – make sure that the Variables component is included, and add something like the below to the variables/YourPluginHandleVariable.php class:
public function getBrands()
{
    $query = craft()->db->createCommand();
    $query->selectDistinct('field_brand');
    $query->from('content');
    return array_filter($query->queryColumn());
}

In your template, you'd use this like so:
{% set brands = craft.yourPluginHandle.getBrands() %}

{% for brand in brands %}
     {{ brand }}
{% endfor %}

Be sure to replace yourPluginHandle and YourPluginHandleVariable with the actual handle for your plugin.
Note that I haven't actually tested the above w/ as many as +18k rows, so even a distinct select query might not be performant enough. Of course, you can always cache the result.

> **Comments:**
> **username_0**: I had a feeling a plugin would be the way to go with that volume of entries. This is exactly the guidance I was looking for. Thanks so much!  
> **username_1**: Awesome. If you get the chance, a report back on the performance would be interesting (if it even works, as I said I've not tested this w/ the volume of entries you have) :)  
> **username_0**: This worked great. Took around 3.5 seconds to go through 18438 entries. I'm very happy, thank you!  
> **username_1**: That's good to hear, 3.5 secs is still *a lot* though, if this happens every pageload...  
> **username_0**: Yeah it's still a lot for a page load generally, but compared to the minute plus it was taking, this is a great improvement! And as you say, I can cache the result. These entries will only change every few months.  
> **username_1**: Cool, and thanks for the follow-up! If the entries only change every few months, I'd say you're OK :) For the caching part, since you're dealing with such a huge number of elements you might want to check out my [CacheFlag](https://github.com/mmikkel/CacheFlag-Craft) plugin – it may prove useful over the native `{% cache %}` tag in your case.  

---

