About Ecto query keyword-based or pipe-based style

Hi everyone,
I try to compare which style is better.
compare the coding example:

  1. keywords query syntax
    import Ecto.Query
    from u in “users”, where: u.age > 18, select: u.name

  2. pipe-based syntax
    “users”
    |> where([u], u.age > 18)
    |> select([u], u.name)

i prefer to write pipe-based syntax style.
Even if I don’t need to do Query Composition.
but is it more readable? or I do not need to care about this.

Hope to get someone’s advise, thank you.

2 Likes

Personally (and that’s about all it is imho :slight_smile: ), I find the pipe-based approach more readable as I don’t have to visually parse the line into its three parts, and it makes editing (and keeping it tidy after editing) a bit easier.

I do wish we could avoid the binding ([u]) parameter more often, though. It works nicely for equality checks:

iex(workorders@nebula)13> "users" |> where(age: 18)
#Ecto.Query<from u in "users", where: u.age == 18>

But does not work when you want to do comparisons or for select/3 … so close!

4 Likes

I prefer from syntax because it’s closer to SQL.

You can do |> select([:foo, :bar, :baz]) so for simple cases, you don’t need the binding either.

3 Likes

Are there any docs about where bindings can be skipped? Defining the bindings is a complexity in composing queries, which would be quite nice to avoid.

2 Likes

Yes. https://hexdocs.pm/ecto/Ecto.Query.html#module-bindingless-operations

4 Likes

It’s not necessarily all or nothing. I find that I have a good time with a mix of these. Ideally I’m bundling up queries into descriptive functions so that I can pipeline descriptive functions together to form a bigger picture:

get_new_users()
|> get_access_log_data()
|> get_other_data()
2 Likes

You can find the documentation for bindingless queries in Ecto.Query documentation under bindingless operations. They are more suitable for dynamic purposes.

2 Likes