代码之家  ›  专栏  ›  技术社区  ›  Sigu Magwa

为提供重复项的字符串自定义自动递增字段

  •  0
  • Sigu Magwa  · 技术社区  · 6 年前

    我目前正在开发一个应用程序,该应用程序要求系统中注册的每个学生在注册时都有一个唯一的注册号,每个注册都自动递增。对于2019年注册的第一名学生,注册号应为“01/19”,对于第890名学生,注册号应为“890/19”。

    注册数据上传自 kobo data collection 因此,工具会在非常短的时间间隔内到达我的终点,因为接近200次提交可以完成一次。

    我意识到,在1000份记录中,有近27个重复的登记号码。这就是我如何实现注册号生成逻辑的方法

    def registration_changeset(student, attrs) do
        student |> changeset(attrs) |> Accounts.add_registration_number()
     end
    

    然后,accounts上下文具有以下用于添加注册号的代码

    def add_registration_number(changeset) do
      struct = changeset.data.__struct__
      registration_number =
      case struct |> last() |> Repo.one() do
        nil -> _create_new_registration_number()
        resource -> _increment_registration(resource.registration_number)
      end
    
      put_change(changeset, :registration_number, registration_number)
    end
    

    我打赌最后一个被创建的学生在上述情况下拥有最新的注册号。

    有没有更好的方法来实现这一点?

    2 回复  |  直到 6 年前
        1
  •  1
  •   Aleksei Matiushkin    6 年前

    这里需要一些同步代码:)

    创建一个专用的过程,它将服务于单一目的:产生数字。 GenServer.handle_call/3 无论您需要什么,进程邮箱都是完美的队列,而OTP会为您做一切。

    defmodule MyApp.RegNumHelper do
      @moduledoc false
    
      use GenServer
    
      def start_link(opts),
        do: GenServer.start_link(__MODULE__, opts, name: name)
    
      def add_registration_number(changeset),
        do: GenServer.call(__MODULE__, {:reg_num, changeset})
    
    
      @impl true
      def init(opts), do: {:ok, opts}
    
      @impl true
      def handle_call({:reg_num, changeset}, _from, state) do
        # your logic assigning changeset
        {:reply, changeset, state}
      end
    end
    

    这种方法还有另一个优点:由于进程已经是有状态的,所以实际上不需要每次都查询数据库。只需在进程启动时查询并将当前号码保存到 state .

        2
  •  0
  •   JustAnotherSoul    6 年前

    最简单的解决方案是,您可以让自动递增的ID成为注册号的第一部分,并将两位数的年份单独存储为一个字段。然后,在模型中,您只需要有一个方法“get_registration_number”,它构成了这两个方法。这样可以解决重复的问题。

    不利的一面是,你会在2019年最后一个学生是890/19,然后在2020年第一个学生是891/20,而不是01/20。但是您的示例似乎也不能很好地处理这个案例,并且它是隐含的,但不清楚这是一个需求。

    如果是这样,您可以创建一个自动递增的列(比如id_num),而不是让id作为第一部分,然后当年份更改时,将该列的下一个值重置为1。如果你想成为偏执狂,你可以说“id_num”列和“2位数字”列一起构成一个唯一的键。

    TL;DR:处理这个问题的最简单方法是让数据库处理它。