<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="107355" data-post-id="107355">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Eiji" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Eiji/120/36743_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Eiji
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p><a class="mention" href="/u/codball" rel="nofollow">@Codball</a>: Sorry for delay …</p>
<aside class="quote no-group" data-username="Codball" data-post="10" data-topic="18606">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/codball/48/12944_2.png" class="avatar"> Codball:</div>
<blockquote>
<p>I want to display it in a template like</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;%= stores &lt;- @stores do %&gt;
  &lt;%= stores.a %&gt;
  &lt;%= stores.b %&gt;
  &lt;%= stores.c %&gt;
&lt;% end %&gt;
</code></pre>
</blockquote>
</aside>
<p>First of all for that you do not need any arrays in <code>a</code>, <code>b</code> and <code>c</code> key. You only need to iterate by all records from database.</p>
<p>If for some reason you still want to have a nested struct then I guess that you would need something like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">%{
  "Colorado" =&gt; %{"Denver" =&gt; ["Eagle", "Jelly Beans", "Name"]},
  "Idaho" =&gt; %{"Boise" =&gt; ["Test"]}
}
</code></pre>
<p>To achieve that in pure <code>SQL</code> query we would need to use lateral joins and some <code>jsonb</code> functions. Here is example code:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Example do
  alias Ecto.Query
  alias Example.{Repo, Store}

  require Query

  def sample do
    query =
      Store
      |&gt; Query.from(as: :store1)
      |&gt; Query.join(
        :inner_lateral,
        [store1: store1],
        store2 in fragment(
          """
          select jsonb_object_agg(store2.city, store3.data) as data
              from stores store2
              inner join lateral (
                select array_agg(name) as data
                  from stores store3
                  where store2.state = store3.state and store2.city = store3.city
              ) store3 on true
              where store2.state = ?
          """,
          store1.state
        ),
        as: :store2
      )
      |&gt; Query.select(
        [store1: store1, store2: store2],
        fragment(
          "jsonb_object_agg(?, ?)",
          store1.state,
          store2.data
        )
      )

    Repo.one!(query)
  end
end
</code></pre>
<p>Here is alternative version for <code>inner join</code>:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Example do
  alias Ecto.Query
  alias Example.{Repo, Store}

  require Query

  def sample do
    store3_query =
      Store
      |&gt; Query.from(as: :store3)
      |&gt; Query.group_by([store3: store3], [store3.city, store3.state])
      |&gt; Query.select([store3: store3], %{
        city: store3.city,
        data: fragment("array_agg(?)", store3.name),
        state: store3.state
      })
      |&gt; Query.subquery()

    store2_query =
      Store
      |&gt; Query.from(as: :store2)
      |&gt; Query.group_by([store2: store2], store2.state)
      |&gt; Query.join(
        :inner,
        [store2: store2],
        store3 in ^store3_query,
        as: :store3,
        on: store2.city == store3.city and store2.state == store3.state
      )
      |&gt; Query.select(
        [store2: store2, store3: store3],
        %{data: fragment("jsonb_object_agg(?, ?)", store2.city, store3.data), state: store2.state}
      )
      |&gt; Query.subquery()

    query =
      Store
      |&gt; Query.from(as: :store1)
      |&gt; Query.join(
        :inner,
        [store1: store1],
        store2 in ^store2_query,
        as: :store2,
        on: store1.state == store2.state
      )
      |&gt; Query.select(
        [store1: store1, store2: store2],
        fragment(
          "jsonb_object_agg(?, ?)",
          store1.state,
          store2.data
        )
      )

    Repo.one!(query)
  end
end
</code></pre>
<p>I’m not sure, but it should be slower in benchmarks than first one, but at least looks much more nice.</p>
<p>Running <code>Example.sample</code> would return previously pasted sample output.</p>
<p>Here is special version if you do not want to do it on database level (due to <code>ecto</code> problems with <code>lateral joins</code> where we need to use big fragments blobs).</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defmodule Example do
  def sample(input), do: Enum.reduce(input, %{}, &amp;do_sample/2)

  defp do_sample(%{a: a, b: b, c: c}, acc),
    do: update_in(acc, [Access.key(a, %{}), Access.key(b, [])], &amp;[c | &amp;1 || []])
end

input = [
  %{a: "Idaho", b: "Boise", c: "Test"},
  %{a: "Colorado", b: "Denver", c: "Eagle"},
  %{a: "Colorado", b: "Denver", c: "Jelly Beans"},
  %{a: "Colorado", b: "Denver", c: "Name"}
]

Example.sample(input)
%{
  "Colorado" =&gt; %{"Denver" =&gt; ["Name", "Jelly Beans", "Eagle"]},
  "Idaho" =&gt; %{"Boise" =&gt; ["Test"]}
}
</code></pre>
<p>In order to use any of those function returns in template you would need to:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;%= for {state, cities} &lt;- @data do %&gt;
  &lt;%= for {city, names} &lt;- cities do %&gt;
    &lt;%= for name &lt;- names do %&gt;
      &lt;%= state %&gt;
      &lt;%= cite %&gt;
      &lt;%= name %&gt;
    &lt;% end %&gt;
  &lt;% end %&gt;
&lt;% end %&gt;
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="107355" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/converting-a-nested-keyword-list-into-a-keyword-map/18606/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-107355" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="107355"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-solved cat-solved" title="Marked as solution"></div>
  </section>
</div>
    <div class="postbit" id="107374" data-post-id="107374">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Codball" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Codball/120/12944_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Codball
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>For some reason, using the special version, <code>c: value</code> is coming back wrapped in some extra brackets, for me.</p>
<pre><code>[
  %{a: "Idaho", b: ["Boise"], c: ["Test"]},
  %{a: "Ohio", b: ["Cleveland"], c: ["different city"]},
  %{a: "Ohio", b: ["Columbus"], c: ["CMH", "Jelly Beans", "Nathan Caldwell"]}
]
</code></pre>
<p>Gets converted to</p>
<pre><code>%{
  "Idaho" =&gt; %{["Boise"] =&gt; [["Test"]]},
  "Ohio" =&gt; %{
    ["Cleveland"] =&gt; [["different city"]],
    ["Columbus"] =&gt; [["CMH", "Jelly Beans", "Nathan Caldwell"]]
  }
}
</code></pre>
<p>giving me the error <code>protocol Phoenix.Param not implemented for ["Test"].</code></p>
<p>when trying to create a link to: <code>&lt;%= link name, to: Routes.page_path(@conn, :show, name) %&gt;</code></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="107374" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/converting-a-nested-keyword-list-into-a-keyword-map/18606/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-107374" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="107374"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="107375" data-post-id="107375">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Eiji" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Eiji/120/36743_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Eiji
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It’s because your input have <code>List</code> where it should have <code>String</code>.</p>
<p>Example input which you show me and with witch my code works is:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">input = [
  %{a: "Idaho", b: "Boise", c: "Test"},
  %{a: "Colorado", b: "Denver", c: "Eagle"},
  %{a: "Colorado", b: "Denver", c: "Jelly Beans"},
  %{a: "Colorado", b: "Denver", c: "Name"}
]
</code></pre> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="107375" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/converting-a-nested-keyword-list-into-a-keyword-map/18606/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-107375" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="107375"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="107377" data-post-id="107377">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Codball" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Codball/120/12944_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Codball
                    <span class="op-star" title="Thread Starter">
                      <img alt="OP" class="op-star-icon" src="/assets/thread-icons/thread-icon-thread-starter-df91e872.png" />
                    </span>
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yeah I edited the query a bit to get it to return what I wanted like so:</p>
<pre><code>Store
    |&gt; Query.from(as: :store)
    |&gt; Query.group_by([store: store], [store.state, store.city])
    |&gt; Query.select([store: store], %{
        a: store.state,
        b: fragment("array_agg( DISTINCT ?)", store.city),
        c: fragment("array_agg(?)", store.name)
        })
    |&gt; Repo.all
</code></pre>
<p>is there a way to edit <code>do_sample/2</code> to remove the extra list bracket?</p>
<p><code>&lt;%= for [name] &lt;- names do %&gt;</code> works for an example of having only one store, but if there’s multiple stores nothing shows up.</p>
<p>fixed with: <code>&lt;%= for {city, [names]} &lt;- cities do %&gt;</code></p>
<p>Thank you so much for your help, I’ve learned a ton from everyone.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="107377" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/converting-a-nested-keyword-list-into-a-keyword-map/18606/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-107377" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="107377"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>