How to access value of key in from where vs get_by?

excuse my ignorance, but I am stumped on what I expect is a simple and common thing :<

In Phoenix 1.4-dev I am trying to access the value of a key in a struct

when I do get_by! I can access key simply with struct.key

iex(62)> website = Repo.get_by!(Website, domain: "countrywebsite.com")
%WwwWebsiteCom.Web.Websites.Website{
  __meta__: #Ecto.Schema.Metadata<:loaded, "websites_websites">,
  blogs: #Ecto.Association.NotLoaded<association :blogs is not loaded>,
  description: "country website domain",
  domain: "countrywebsite.com",
  id: 2,
  inserted_at: ~N[2018-09-22 06:05:58.447615],
  title: "Country Website",
  updated_at: ~N[2018-09-22 06:05:58.447624],
  user: #Ecto.Association.NotLoaded<association :user is not loaded>,
  user_id: 1
}
iex(63)> website.id
2

but when I run a similar where from, the struct is inside a list and its not obvious how to access the key

iex(64)> website = Repo.all(from d in Website, where: like(d.domain, "countrywebsite.com"))
[
  %WwwWebsiteCom.Web.Websites.Website{
    __meta__: #Ecto.Schema.Metadata<:loaded, "websites_websites">,
    blogs: #Ecto.Association.NotLoaded<association :blogs is not loaded>,
    description: "Country Website",
    domain: "countrywebsite.com",
    id: 2,
    inserted_at: ~N[2018-09-22 06:05:58.447615],
    title: "Country Website",
    updated_at: ~N[2018-09-22 06:05:58.447624],
    user: #Ecto.Association.NotLoaded<association :user is not loaded>,
    user_id: 1
  }
]
iex(65)> website.id
** (ArgumentError) you attempted to apply :id on [%WwwCountryCom.Web.Websites.Website

is there a way to flatten or strip the list? convert the list or extract the struct from the list?

Repo.get_by

Returns a single result

Repo.all

Returns a list of results

To get just one result you want to use Repo.one

1 Like

bingo, THANKS @praveenpera

as a follow-up, what would the approach be with a different where from query, that did need to return a list? how would I access the values of keys in a list of structs? Enum.map?

1 Like

Depends on the situation but usually ya Enum.map will work

Or you could use a select clause to only query the values you care about.

thank you sir !

scholar and a gentlemen

1 Like

One more thing Repo.one will raise if the query returns more than one result so depending on the situation you might want to use first, or something similar in the query to return just one result.

Post |> first |> Repo.one

query |> first(:inserted_at) |> Repo.one

You can use pattern matching

[struct] = website
struct.id
#or even more
[%{ id: id }] = website
id
1 Like

thankyou both :grinning:

1 Like