Ecto: Allow schema :field to have an alias

Created on 6 Jan 2017  Â·  19Comments  Â·  Source: elixir-ecto/ecto

Hi,

I am fairly new to elixir and am currently working on developing a service application on phoenix.

It uses MongoDB as a backend and i am using mongo-ecto as the adapter to connect to the database.

The issue i am facing is that the fields in the MongoDB (as per normal practise) use short names. So, first_name is stored as fn, etc. Now, I want to access the field using proper names (read: first_name) throughout the code.

One approach that i could think of makes use of virtual fields like below:

defmodule User do
  use Blog.Web, :model

  schema “users” do
    field :fn, :string
    field :first_name, :string, virtual: true
  end

  def copy_from_alias(%{})
    # we copy values from alias
  end

  def copy_to_alias(%{})
    # we set value to aliases 
  end
end

We can also have the above code autogenerated via a macro like aliased_field.

However, with this i’ll need to explicitly call these methods whenever casting data to/from database.
Is there any way to avoid doing that ?

Also, i am not sure how to get it working with queries. For eg:

Repo.get_by(User, %{first_name: “Bharat”})

should check for fn when forming query and not first_name.

Is there any other approach that solves this problem ? I am willing to raise a PR for the same as i believe this to be a fairly regular use case (MongoDB, legacy databases, etc.) if i can get some pointers.

Any help is appreciated.

Intermediate

Most helpful comment

In master! Please give it a try and test it further!

All 19 comments

Two proposals:

  schema "users" do
    field :fn, :string, alias: :first_name
  end

or

  schema "users" do
    field :first_name, :string
  end

  mongo_adapter "users" do
     map_field :first_name, to: :fn
  end

@josevalim would be great to get your direction on how this could be implemented, we're happy to give it a try if there's an agreed upon spec.

@josevalim any comment here? This is an important issue for our team to migrate from Ruby/Mongoid to Elixir.

Out of curiosity, why is it 'normal practise' to use cryptic and meaningless field names in MongoDB?

@sevenseacat unlike other DBs which use position-dependent columns, MongoDB is a document database and the field (column) names are stored within the document (row). So you can significantly reduce the size of objects by using aliases:

{ my_long_field_name: "my value", my_other_field: "other value" }

becomes

{ f1: "my value", f2: "other value" }

A secondary reason for both schema and schema-less DBs is from time-to-time you may want to migrate or rename columns, and using aliases make it much easier to move things around without renaming the variable throughout your entire app.

Cheers for that. Now I have another reason to avoid Mongo apps...

@johnnyshields I believe this has been discussed in the past. Did you find any relevant information in previous discussions?

@josevalim I'm not aware of where these discussions were held. I've searched this repo for issues containing "alias" and I don't see it.

@johnnyshields let's give the :alias option a try then. This is a somewhat complex issue because it does not only touch insert/update/delete operations but also all queries.

@josevalim great, thanks. We'll start work on this soon.

Just wanted to make sure that you are aware of the discussion about aliases that is going on on the Elixir forum. I think this is mostly relevant because the Original Poster describes an alternative situation in which field aliases would be helpful, namely one in which Elixir+Ecto needs to use an already-existing database that uses CamelCase field names.

+1 on this.
In my case, my database has "ugly" column name conventions that I wouldn't like to inherit in my phoenix/ecto project. I got some columns like "some_random_prefix_convention_foo" that would be great if used only as "foo" on my model.

@hbobenicio there is a PR branch here https://github.com/elixir-ecto/ecto/pull/1998 ready to merge which we are using in our apps, please help push to get it merged.

In master! Please give it a try and test it further!

Is there a way to convert names between camel/snake case, without "source" on every field?

You could create a custom field macro that would compute the correct source and call the original field.

The macro works but we can possibly make it easier. What if we have a
source_mapper option that is given to schema/2 and it I invoked for every

field?

José Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D

Thanks @michalmuskala I'll give it a try

@josevalim a source_mapper option would be perfect!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

atsheehan picture atsheehan  Â·  4Comments

ZhengQingchen picture ZhengQingchen  Â·  4Comments

stavro picture stavro  Â·  4Comments

jonasschmidt picture jonasschmidt  Â·  4Comments

AndresOsinski picture AndresOsinski  Â·  5Comments