Access a key from changest

A partial unique index. See https://www.postgresql.org/docs/current/static/indexes-partial.html#INDEXES-PARTIAL-EX3 near the bottom. And https://hexdocs.pm/ecto/Ecto.Migration.html#index/3-partial-indexes for ecto.

is this supported via ecto migration?

I think so.

create index("table_name", [:asd], where: "asd = true", name: :asd_unique_bool_index, unique: true)
1 Like

Hm, i need to say: Thanks a lot. Will try this out. This way my question with access to changeset.asd is unnecessary. Did not know, that ecto supports partial index. You saved my day :slight_smile:
Was a bit angry, because the first answer was to check the documentation. I think noone asks questions here before checking the documentation, as it is the main source for informations. And I tried of cource fetch and get before. If it had worked I would not ask. So thank you for also providing some code and not giving me a link where to look :wink:

1 Like
create index("table_name", [:asd], where: "asd = true", name: :asd_unique_bool_index, unique: true)

is not matching index/3 one parameter too much.

Hm, can you try

create index("table_name", [:asd], [where: "asd = true", name: :asd_unique_bool_index, unique: true])

(added brackets around the third opts argument).

1 Like

Ah, are parts of the option. You are my hero :slight_smile:

Edit:

  def change do
    create index("table", [:asd], [where: "asd = true", name: :asd_unique_bool_index, unique: true])
  end

Still

** (FunctionClauseError) no function clause matching in Ecto.Migration.index/3 

:confused:

People not checking the docs before posting here does happen. Some just don’t know about the nice docs yet.

Your question was about how to check for a field value in a changeset. I did point you to the functions which let you check field values within a changeset. They’re just not as simple as changeset.some_field because a changeset does differenciate between incoming changes and the base data, so one would need to decide where exactly the key should be checked against – with Ecto.Changeset.get_field(changeset, :some_field) being the closest to checking a key on a map.

I hope that explains why even a link to the docs and pointing to some functions might actually be a useful answer. In the end there’s no point in duplicating the code examples of the documentation here.

I am a .net developer and was thrown into elixir. Handing over of the elixir backend frustrated me, because every question was answered with “check the docs”. I still lack in some fundamental approches of elixir. The backend was made by guys which made ruby on rails before, so they had already an understanding of pattern matching und functional programming. Sorry, did not want to be offensive. I am learning from the code. Docs are ok, but not handling edge cases which often appear in the real world.
Edit:
Do you have an idea, why

def change do
  create index(“table”, [:asd], [where: “asd = true”, name: :asd_unique_bool_index, unique: true])
end

is trhowing an error?

1 Like

Thats the point about docs:
create index(“products”, [:user_id], where: “price = 0”, name: :free_products_index)
Not working.
Edit:
made

execute("CREATE INDEX asd_constraint ON table(asd) WHERE asd = true") inside the change 

with add: asd.

Reading docs did not help in this case, had to use google.

Is there anything else in the stacktrace?

** (FunctionClauseError) no function clause matching in Ecto.Migration.index/3
    (ecto) lib/ecto/migration.ex:509: Ecto.Migration.index("table", [:asd], [where: "asd= true"])
    _build/dev/lib/biqx/priv/repo/migrations/20180418094158_add_partial_index_on_asd_to_table.exs:5: Biqx.Repo.Migrations.AddPartialIndexOnAsdTotTable.change/0
    (stdlib) timer.erl:197: :timer.tc/3
    (ecto) lib/ecto/migration/runner.ex:26: Ecto.Migration.Runner.run/6
    (ecto) lib/ecto/migrator.ex:127: Ecto.Migrator.attempt/6
    (ecto) lib/ecto/migrator.ex:73: anonymous fn/4 in Ecto.Migrator.do_up/4
    (ecto) lib/ecto/adapters/sql.ex:620: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3
    (db_connection) lib/db_connection.ex:1275: DBConnection.transaction_run/4
    (db_connection) lib/db_connection.ex:1199: DBConnection.run_begin/3
    (db_connection) lib/db_connection.ex:790: DBConnection.transaction/3
    (ecto) lib/ecto/migrator.ex:250: anonymous fn/4 in Ecto.Migrator.migrate/4
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (ecto) lib/mix/tasks/ecto.migrate.ex:84: anonymous fn/4 in Mix.Tasks.Ecto.Migrate.run/2
    (elixir) lib/enum.ex:645: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:645: Enum.each/2
    (mix) lib/mix/task.ex:300: Mix.Task.run_task/3
    (elixir) lib/enum.ex:645: Enum."-each/2-lists^foreach/1-0-"/2
    (elixir) lib/enum.ex:645: Enum.each/2
    (mix) lib/mix/task.ex:300: Mix.Task.run_task/3

But

execute(“CREATE INDEX asd_constraint ON table(asd) WHERE asd = true”)  

worked.
My mix .exs says {:phoenix_ecto, “~> 3.0”} so shoud fit. Looks like a bug to me. Or am I only allowed to change the index with no data inside the table? I have a migration which adds a dataset to the table. I moved the execute to the migration beore data gets inserted.

My mix .exs says {:phoenix_ecto, “~> 3.0”}

That’s not ecto, it’s a library of phoenix helpers to integrate with ecto. Like “return 404” if “Repo.get!” raises.

Or am I only allowed to change the index with no data inside the table? I have a migration which adds a dataset to the table. I moved the execute to the migration beore data gets inserted.

Judging by the error, it is raised before any changes to the database are done. For some reason your inputs don’t match what Ecto.Migration.index/3 expects, which are:

  • first parameter (table name) is a string or an atom
  • second parameter (column/ columns) is an atom or a list of atoms / strings
  • third parameter (opts) is a list

So index(“table”, [:asd], [where: “asd= true”]) should work …

You can see the version of ecto that you use in mix.lock.

You are right, phoenix_ecto is not ecto :wink: Ecto is 2.1.14. I use unique_index a lot like create unique_index(:table, [field1, :field2])
I try to update to 2.2.10 and check Migration.index again. Maybe it is a bug in 2.1.14.

There is no such version released on hex.pm. Latest in 2.1 was 2.1.6.

But as far as I can tell, table has to be an atom in that version.

1 Like

Right, it is 2.1.4 one 1 too much.

I think @NobbZ is right. Can you try using an atom for the table name?

create index(:table_name_here, [:asd], [where: “asd = true”, name: :asd_unique_bool_index, unique: true])

However, in ecto 2.2.10 it accepts a string as well.

1 Like

My solution with execute is already in prod stage. But will keep it in mind to use an atom instead of a string. Hate breaking changes in minor versions :wink:

Hi Sardoan, welcome to the forum and the community!

Please note that if someone’s post does not help solve your problem, or you’re pointed in a direction or path you’ve already gone down, simply say you’re still struggling or that you’ve already done as suggested and need further help :slight_smile:

Please also use Markdown to properly format your posts - there is some basic markdown info here: https://elixirforum.com/t/moderation-queue-section-info/12885

Please fix your previous posts in this thread with the correct formatting before making any further posts - thanks :023:

1 Like

Hi, thanks. Will do it now.

1 Like