【问题标题】:Elixir : Mnesia : What is the most concise way to update a set of value in an element?Elixir : Mnesia : 更新元素中一组值的最简洁方法是什么?
【发布时间】:2020-11-12 20:02:04
【问题描述】:

问题

学习使用Mnesia 和Elixir,我创建了一个具有多种功能(例如读、写...)的表。其中之一是在不更改其余数据的情况下更新一组字段(大小从 1 到 count - 1),并将 mnesia 事务中的逻辑限制为最小。

在搜索过程中,我碰巧找到了这个:Erlang : Mnesia : Updating a single field value in a row(代码如下)。这是同一个问题,但对于 Erlang,而不是 Elixir。

代码

据我了解,它在 Erlang 中工作,因为 read 返回一个直接设置在记录中的元组,这允许我们将特定数据保存在写入操作中,因为它们被命名。

update_a(Tab, Key, Value) ->
  fun() ->
    [P] = mnesia:wread({Tab, Key}),
    mnesia:write(P#pixel{a=Value})
  end.

对于 Elixir,即使 Records 存在,它也只是一个元组,您只能更改索引中的数据,并将完整的元组返回给写入操作。

Table: {table_name, id, data1, data2, data3, data4}
changes = [{2, new_val_for_data1}, {4, new_val_for_data3}]

def handle_call({:update_and_read, table, {id, changes}}, _, state) do
  {:atomic, new_object} =
    :mnesia.transaction(fn ->
      object =
        :mnesia.wread({table, id})
        |> List.first()

      ret =
        Enum.reduce(changes, object, fn {index, value}, acc ->
          acc |> Tuple.delete_at(index) |> Tuple.insert_at(index, value)
        end)

      :mnesia.write(object)
      ret
    end)

  {:reply, {:ok, new_object}, state}
end

问题

是否可以在 Elixir 中使用更短的函数(理想情况下,像 Erlang 中的那样只有 2 行)?

【问题讨论】:

    标签: erlang elixir mnesia


    【解决方案1】:

    好吧,您可以在一些初步步骤中使用Record(例如在您的应用中定义记录。)

    defmodule Pixel do
      require Record
      Record.defrecord(:table_name, id: nil, data1: nil, data2: nil)
    end
    

    在你想要更新表格的模块中

    import Pixel
    
    def handle_call({:update_and_read, table, {id, changes}}, _, state) do
      # changes = [data2: new_val_for_data1, ...]
      {:atomic, result} =
        :mnesia.transaction(fn ->
          case :mnesia.wread({table, id}) do
            [object] -> 
              :mnesia.write(pixel(object, changes))
              {:ok, object}
            [] -> :error
          end
        end)
    
      {:reply, result, state}
    end
    

    另一种可能是通过

    changes = %{2 => new_val_for_data1, 4 => new_val_for_data3}
    object
    |> Tuple.to_list()
    |> Enum.with_index()
    |> Enum.map(fn {value, idx} -> Map.get(changes, idx, value) end)
    |> List.to_tuple()
    

    另一种可能性是声明一个宏,该宏接受一个元组,表示一个表格行,以及一个{idx, new_value} 元组列表,并就地更改相应的元素。

    【讨论】:

      猜你喜欢
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 2011-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多