dimitarvp

dimitarvp

How to express composite primary key? And how to populate virtual field on Repo.get?

Hello all,
I am casually working on, as a hobbyist project, every now and then, a WordPress read-only Elixir viewer. I am working my way through several dumped WP databases and making Ecto schema modules out of their tables.

I stumbled upon this one today:

mysql> desc wp_wfBlockedIPLog;
+-------------+------------------+------+-----+------------------+-------+
| Field       | Type             | Null | Key | Default          | Extra |
+-------------+------------------+------+-----+------------------+-------+
| IP          | binary(16)       | NO   | PRI |                  |       |
| countryCode | varchar(2)       | NO   |     | NULL             |       |
| blockCount  | int(10) unsigned | NO   |     | 0                |       |
| unixday     | int(10) unsigned | NO   | PRI | NULL             |       |
+-------------+------------------+------+-----+------------------+-------+
4 rows in set (0.01 sec)

Primary question

How can I express a primary key – through the @primary_key attribute, I imagine – for this module?

So far my first try (without the double primary key) is:

defmodule WP.WfBlockedIpLog do
  use Ecto.Schema

  @primary_key {:id, :binary_id, autogenerate: false, source: :IP}
  schema "wp_wfBlockedIPLog" do
    field :block_count, :integer, source: :blockCount
    field :country_code, :string, source: :countryCode
    field :unixday, :integer
    field :date, :date, virtual: true # <- Note this for the secondary question.
  end
end

Example of a loaded Ecto.Schema:

  %WP.WfBlockedIpLog{
    __meta__: #Ecto.Schema.Metadata<:loaded, "wp_wfBlockedIPLog">,
    block_count: 5,
    country_code: "UA",
    date: nil,
    id: "00000000-0000-0000-0000-ffff2573bf43",
    unixday: 17030
  }

The above module gives me a string UUID which I am not very happy with. Is there a way to make the ID a true binary?


Secondary question

I realized after inspecting the dumped WP databases that unixday above is basically a date:

17_030
|> Kernel.*(24*60*60)
|> DateTime.from_unix!()
|> DateTime.to_date()

Is there a way to have the date virtual field above be filled at Repo.get, transparently? Or is there a way to do it at all? What alternative approaches would you recommend?

Thank you.

Marked As Solved

fuelen

fuelen

Hello,

  1. try just string instead of binary_id
  2. obvious solution for me is to have simple helper that will fill virtual fields on demand
def load_virtual_fields(query) do
  select_merge(query, [log], %{date: type(fragment("to_timestamp(? * 24*60*60)", log.unixday), :date)})
end
# ...
WfBlockedIpLog
|> load_virtual_fields()
|> ...
|> Repo.get()

Also Liked

Matsa59

Matsa59

It’s not possible to define multiple primary key. But you can set @primary_key to false and then define the option primary_key to true on your fields IP and unixday. Everything is well explains in the doc @fuelen sent, at the bottom.

In your case it will be


defmodule WP.WfBlockedIpLog do
  use Ecto.Schema

  @primary_key false
  schema "wp_wfBlockedIPLog" do
    field :ip, :binary, primary_key: true
    field :unixday, :integer, primary_key: true

    field :block_count, :integer, source: :blockCount
    field :country_code, :string, source: :countryCode
   
    field :date, :date, virtual: true # <- Note this for the secondary question.
  end
end

(Write with my phone so may contains some errors).

akashv

akashv

You can set multiple fields as primary key.

Matsa59

Matsa59

What do you mean?

You can use ˋget_byand for preloads define your own function that use customjoin`.

Where Next?

Popular in Questions Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New

Other popular topics Top

albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement