Answers.Body: <p>Your issue is that as soon as you call <code>.find()</code>, your <a href="https://craftcms.com/docs/templating/elementcriteriamodel" rel="nofollow">ElementCriteriaModel</a> returns <em>an array of elements</em>. In other words, the ElementCriteriaModel is gone, and it's no longer possible to add parameters (i.e. <code>id()</code>) or call other methods that you'd otherwise be able to call on that object (i.e. <code>.first()</code>).</p>
  
  <p>On the other hand – like you say in your description; if you don't use <code>.find()</code> (keeping the ElementCriteriaModel around) you'll hit the database every time you use the <code>.id()</code> method.</p>
  
  <p>A workaround could be to loop over the categories and add them to an indexed array (using the category IDs as keys) and then pull your individual categories from that index instead of the original array.</p>
  
  <p>Important: One gotcha to note is that the <code>|merge</code> filter will actually renumber numeric keys, so you have to add an arbitrary character to the ID to retain the actual ID values (the example below uses an underscore prefix):</p>
  
  <pre><code>{# Get the categories #}
  {% set categories = craft.categories.group('products').limit(null).find() %}
  
  {# Create category index #}
  {% set categoryIndex = {} %}
  {% for category in categories %}
      {% set categoryIndex = categoryIndex|merge({('_'~category.id): category}) %}
  {% endfor %}
  
  {# Do your thing #}
  &lt;h1&gt;&lt;a href="{{ categoryIndex['_102'].url }}"&gt;{{ categoryIndex['_102'].title|raw }}&lt;/a&gt;&lt;/h1&gt;
  &lt;h2&gt;{{ categoryIndex['_126'].title|raw }}&lt;/h2&gt;
  </code></pre>
  
  <p>Note that when you want to pull a category from the index, <code>categoryIndex['_102']</code> and <code>categoryIndex._102</code> will both work – I just find that the former looks a bit cleaner, with the underscore in front of it (obviously you can use any character, it doesn't have to be an underscore).</p>
  
  <p><strong>Edit</strong></p>
  
  <p>As pointed out by @carlcs in the comments below, another approach to creating the index is to use the <a href="https://craftcms.com/docs/templating/filters#group" rel="nofollow"><code>group</code></a> filter. With this approach you'll avoid the underscore hack and the <code>for</code> loop. The gotcha here is that this filter will actually create an array of arrays, meaning you'll have to use <code>categoryIndex[102][0]</code> (note the <code>[0]</code> at the end) to access a specific category (you could also use <code>categoryIndex[102]|first</code>, of course):</p>
  
  <pre><code>{% set categories = craft.categories.group('products').limit(null).find() %}
  {% set categoryIndex = categories|group('id') %}
  
  &lt;h1&gt;&lt;a href="{{ categoryIndex[102][0].url }}"&gt;{{ categoryIndex[102][0].title|raw }}&lt;/a&gt;&lt;/h1&gt;
  &lt;h2&gt;{{ categoryIndex[126][0].title|raw }}&lt;/h2&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-08-11T07:48:46.753Z
Answers.Text: Good solution, I was just thinking that you might be able to achieve the same using the group filter, and It might even be possible to do so without this underscore hack that is required because of how merge works. `categories|group('id')`
Answers.UserDisplayName: carlcs
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-08-11T11:24:16.653Z
Answers.Text: Good idea, @carlcs – the `group` filter is definitely an option, too. I'll edit my answer to include it.
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-08-10T18:54:37.730Z
Answers.LastActivityDate: 2016-08-11T11:30:36.717Z
Answers.LastEditDate: 2016-08-11T11:30:36.717Z
Answers.UserDisplayName: Mats Mikkel Rummelhoff
Body: <p>I am working on a site that needs to both list all categories and also pull out individual categories by their id.</p>
  
  <p>I would like to query the DB once for all the categories (to improve performance), and then pull out which ones I want, but am struggling to find a solution.</p>
  
  <pre><code>{% set catNavigation = craft.categories.group('products').limit(null).find() %}
  
  &lt;h1&gt;&lt;a href="{{ catNavigation.id(102).first.url }}"&gt;{{ catNavigation.id(102).first.title|raw }}&lt;/a&gt;&lt;/h1&gt;
  &lt;h2&gt;{{ catNavigation.id(126).first.title|raw }}&lt;/h2&gt;
  </code></pre>
  
  <p>This is giving me an error.</p>
  
  <pre><code>Array to string conversion
  </code></pre>
  
  <p>So I guess I can't grab pieces of an element criteria model after using find.</p>
  
  <p>If I don't use find, then I query the DB multiple times.</p>
  
  <p>I thought about creating my own array of categories dynamically with twig, but that has not gone well.</p>
  
  <p>Is there a way to accomplish what I'm after? It's as if I need to search within an array of data that has already been returned from the DB. Hope that makes sense.</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-08-10T17:13:57.053Z
Comments.Text: If you've applied `.find()` (which you have), then you're no longer dealing with an Element Criteria Model. The `find` parses the ECM into an array of elements (in this case, an array of Category Models).
Comments.UserDisplayName: Lindsey D
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-08-10T17:28:04.483Z
Comments.Text: I see, is there a way to grab individual categories from that array. Or would trying to search through an array of category models negate any performance increase gained by reducing queries?
Comments.UserDisplayName: mjr
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-08-10T18:58:31.987Z
Comments.Text: Unless you have a _serious_ amount of categories, looping through them a few times will almost certainly be more performant than having an X amount of additional database queries. You can even make use of the [NM Break and Continue](https://github.com/marionnewlevant/craft-mnbreakandcontinue) plugin in order to break out of the `for` loop as soon as you have a match. If that doesn't float your boat, I added an answer with a different approach below – it requires looping through all the categories, but only once :)
Comments.UserDisplayName: Mats Mikkel Rummelhoff
Tags: <categories><elementcriteriamodel><performance>
Title: Query all categories once and get individual categories from array
ThreadText: # Query all categories once and get individual categories from array
  
  (Asked by: username_0 on 2016-08-10)
  
  I am working on a site that needs to both list all categories and also pull out individual categories by their id.
  
  I would like to query the DB once for all the categories (to improve performance), and then pull out which ones I want, but am struggling to find a solution.
  
  ```
  {% set catNavigation = craft.categories.group('products').limit(null).find() %}
  
  <h1><a href="{{ catNavigation.id(102).first.url }}">{{ catNavigation.id(102).first.title|raw }}</a></h1>
  <h2>{{ catNavigation.id(126).first.title|raw }}</h2>
  
  ```
  
  This is giving me an error.
  
  ```
  Array to string conversion
  
  ```
  
  So I guess I can't grab pieces of an element criteria model after using find.
  
  If I don't use find, then I query the DB multiple times.
  
  I thought about creating my own array of categories dynamically with twig, but that has not gone well.
  
  Is there a way to accomplish what I'm after? It's as if I need to search within an array of data that has already been returned from the DB. Hope that makes sense.
  
  **Tags:** categories, elementcriteriamodel, performance
  
  > **Comments:**
  > **username_1**: If you've applied `.find()` (which you have), then you're no longer dealing with an Element Criteria Model. The `find` parses the ECM into an array of elements (in this case, an array of Category Models).  
  > **username_0**: I see, is there a way to grab individual categories from that array. Or would trying to search through an array of category models negate any performance increase gained by reducing queries?  
  > **username_2**: Unless you have a _serious_ amount of categories, looping through them a few times will almost certainly be more performant than having an X amount of additional database queries. You can even make use of the [NM Break and Continue](https://github.com/marionnewlevant/craft-mnbreakandcontinue) plugin in order to break out of the `for` loop as soon as you have a match. If that doesn't float your boat, I added an answer with a different approach below – it requires looping through all the categories, but only once :)  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2016-08-10. Score: 4 | Accepted answer
  
  Your issue is that as soon as you call `.find()`, your [ElementCriteriaModel](https://craftcms.com/docs/templating/elementcriteriamodel) returns *an array of elements*. In other words, the ElementCriteriaModel is gone, and it's no longer possible to add parameters (i.e. `id()`) or call other methods that you'd otherwise be able to call on that object (i.e. `.first()`).
  
  On the other hand – like you say in your description; if you don't use `.find()` (keeping the ElementCriteriaModel around) you'll hit the database every time you use the `.id()` method.
  
  A workaround could be to loop over the categories and add them to an indexed array (using the category IDs as keys) and then pull your individual categories from that index instead of the original array.
  
  Important: One gotcha to note is that the `|merge` filter will actually renumber numeric keys, so you have to add an arbitrary character to the ID to retain the actual ID values (the example below uses an underscore prefix):
  
  ```
  {# Get the categories #}
  {% set categories = craft.categories.group('products').limit(null).find() %}
  
  {# Create category index #}
  {% set categoryIndex = {} %}
  {% for category in categories %}
      {% set categoryIndex = categoryIndex|merge({('_'~category.id): category}) %}
  {% endfor %}
  
  {# Do your thing #}
  <h1><a href="{{ categoryIndex['_102'].url }}">{{ categoryIndex['_102'].title|raw }}</a></h1>
  <h2>{{ categoryIndex['_126'].title|raw }}</h2>
  
  ```
  
  Note that when you want to pull a category from the index, `categoryIndex['_102']` and `categoryIndex._102` will both work – I just find that the former looks a bit cleaner, with the underscore in front of it (obviously you can use any character, it doesn't have to be an underscore).
  
  **Edit**
  
  As pointed out by @username_3 in the comments below, another approach to creating the index is to use the [`group`](https://craftcms.com/docs/templating/filters#group) filter. With this approach you'll avoid the underscore hack and the `for` loop. The gotcha here is that this filter will actually create an array of arrays, meaning you'll have to use `categoryIndex[102][0]` (note the `[0]` at the end) to access a specific category (you could also use `categoryIndex[102]|first`, of course):
  
  ```
  {% set categories = craft.categories.group('products').limit(null).find() %}
  {% set categoryIndex = categories|group('id') %}
  
  <h1><a href="{{ categoryIndex[102][0].url }}">{{ categoryIndex[102][0].title|raw }}</a></h1>
  <h2>{{ categoryIndex[126][0].title|raw }}</h2>
  
  ```
  
  > **Comments:**
  > **username_3**: Good solution, I was just thinking that you might be able to achieve the same using the group filter, and It might even be possible to do so without this underscore hack that is required because of how merge works. `categories|group('id')`  
  > **username_2**: Good idea, @username_3 – the `group` filter is definitely an option, too. I'll edit my answer to include it.  
  
  ---
  
  