Ecto/Absinthe query sort by field

I’m trying to build my own app by extrapolating from the Pragmatic Studio’s unpacked course material. They have a query for returning a list of “places” from the database in ascending order:

query do 
  @desc "Get a list of places"
  field :places, list_of(:place) do 
    arg :limit, :integer 
    arg :order, type: :sort_order, default_value: :asc 
    arg :filter, :place_filter 
    resolve &Resolvers.Vacation.places/3
  end
...
end

In my case I want to sort by the time an “article” was inserted. My schema is

schema "articles" do 
  field :body, :string 
  field :title, :string 
  belongs_to :user, Accounts.User
  timestamps() 
end

I’ve defined the article “object” in MyApp_Web/schema/schema.ex as

object :article do 
  field :id, non_null(:id)
  field :body, non_null(:string)
  field :title, non_null(:string)
  field :user, non_null(:user), resolve: dataloader(Accounts)
  field :inserted_at, non_null(:naive_datetime)
end

How do I structure the query to return a list of articles sorted by the inserted_at field?

When I try

query do 
  field :articles, list_of(article) do 
    arg(:user_id, non_null(:id)
    arg(:order_by, :inserted_at)
    resolve(&Resolvers.Article.articles/3)
  end
end

I get told

In Order_by, :inserted_at is not defined in your schema.

but when I look in Graphiql the generated docs show insertedAt: NaiveDateTime! for the Article type.

Managed to sort this by just handling it in the resolver helper function.

Hi @stevensonmt. Could you please share how you managed to solve this?

Oh, geez. I have abandoned this project long ago due to my magpie mentality. My resolver function calls out to a helper function and the helper function includes the order_by call.
My app is organized as

lib
  |_blog
       |_article.ex
  |_blog_web
           |_resolvers
                     |_article.ex
           |_schema
                  |_schema.ex

Obviously I’m not showing all the files uninvolved with this query.
In the schema.ex file I have:

query do
  field :articles_by_author, list_of(:article) do 
    arg(:user_id, non_null(:id))
    arg(:limit, :integer)
    resolve(&Resolvers.Article.articles_by_author/3)

and the Resolvers.Article.articles_by_author/3 is defined as

def articles_by_author(_, args, _) do
  args 
    |> Map.put_new(:limit, 10)
    |> Article.list_all_articles_by_author!()
end

and then the Article.list_all_articles_by_author!() is the following:

def list_all_authors_by_author!(%{user_id: user_id, limit: limit|) do 
  try do
    {:ok, Article 
          |> where([a], ^user_id == a.user_id)
          |> order_by(desc: :inserted_at)
          |> order_by(desc: :id)
          |> limit(^limit)
          |> Repo.all()}
  rescue
    Ecto.QueryError -> {:error, message: "Sorry, something went wrong with that search by author."}

Sorry for any formatting errors or typos above. I make no claims that this is the correct way to handle this, btw. I’m fumbling in the dark in most cases.

1 Like

Thank you for sharing!

+1 for the phrase “magpie mentality”

1 Like