Elixir Ecto:범위 데이터 유형

3987 단어 ectoelixir
PostgreSQL 9.2 이래로 특정한 조작부호와 함수로 한 값의 범위를 저장하고 조회할 수 있다.이것은 매우 좋은 특성이다. 예를 들어 전자상거래 응용 프로그램에 있어서 하나의 필드 price_range으로 min_price을 대체할 수 있다. max_price은 하나의 가격 범위를 나타낸다.

Ecto에서 범위 데이터 유형 사용


가격 범위의 표시 방법은 다음과 같다.
[0, 45.67] 
[30.04, 98.50]
[100, 500]

우리는 범위 조작부호로 한 값의 범위를 조회할 수 있다
2.5 

Postgresql은 다음과 같은 범위 유형을 지원합니다.
104591710 정수 방위 104591810
104591710 104591410 - 큰 정수 범위 104591810
104591710 104591410 - 10진수 범위(부동) 104591810
104591710 104591410 - 시간대가 없는 타임 스탬프 범위 104591810
104591710 104591410 - 시간대 타임스탬프 범위 104591810
104591710 104591410 - 날짜 범위 104591810
Ecto 자체는 각 데이터베이스를 호환하기 위해 Postgresql 특유의 Range 데이터 형식을 지원하지 않지만, Ecto는 우리에게 사용자 정의 데이터 형식을 제공하는 방법을 제공했다.다음은 int4range 유형을 만들고 밑바닥은 Postgrex 어댑터의 int8range 구조를 사용했습니다.
defmodule App.NumRange do  
  @behaviour Ecto.Type
  def type, do: :numrange
  def cast([lower, upper]) do
    {:ok, [lower, upper]}
  end
  def cast(_), do: :error
  def load(%Postgrex.Range{lower: lower, upper: nil}) do
    {lower, _} = lower |> to_float
    {:ok, [lower, nil]}
  end
  def load(%Postgrex.Range{lower: lower, upper: upper}) do
    {lower, _} = lower |> to_float
    {upper, _} = upper |> to_float
    {:ok, [lower, upper]}
  end
  def dump([lower, upper]) do
    {:ok, %Postgrex.Range{lower: lower, upper: upper, upper_inclusive: false}}
  end
  def dump(_), do: :error
  defp to_float(value) do
   value |> Decimal.to_string |> Float.parse
  end
end 

모델과 이전 스크립트에서 이 사용자 정의 데이터 형식을 사용합니다
모델
defmodule App.Product do  
  use App.Web, :model
  schema "products" do
    field :price_range, App.NumRange
    timestamps
  end
end  

스크립트 마이그레이션
defmodule App.Repo.Migrations.Product do  
  use Ecto.Migration
  def change do
    create table(:products) do
      add :price_range, :numrange
      timestamps
    end
  end
end  

범위 조회
defmodule App.ProductQuery do  
  import Ecto.Query
  alias App.{Repo, Product}
  def within_price_range(price) do
    query =
      from p in Product,
      where: fragment("?::numeric  Repo.all
  end
end  

방위 경계에 관한 문제는 수학의 범위 기호와 같다.
  • numrange 하단 경계 포함
  • tsrange 하단 경계 제외
  • tstzrange 상위
  • 포함
  • daterange 상위
  • 제외

    예.

    #    
    create table products(id int, price_range numrange);
    #     
    INSERT INTO products VALUES(1, '[10.0, 100.0]')
    INSERT INTO products VALUES(1, '[200.0, 300.0]')
    INSERT INTO products VALUES(1, '[400.0, 500.0]')
    INSERT INTO products VALUES(1, '[600.0, 700.0]')
    #   
    SELECT * FROM products;
    +------+--------------------------------------------------------+
    |   id | price_range                                            |
    |------+--------------------------------------------------------|
    |    1 | NumericRange(Decimal('10.0'), Decimal('100.0'), '[]')  |
    |    1 | NumericRange(Decimal('200.0'), Decimal('300.0'), '[]') |
    |    1 | NumericRange(Decimal('400.0'), Decimal('500.0'), '[]') |
    |    1 | NumericRange(Decimal('600.0'), Decimal('700.0'), '[]') |
    +------+--------------------------------------------------------+
    #   
    SELECT * FROM products WHERE price_range::numrange @> 99.0
    +------+-------------------------------------------------------+
    |   id | price_range                                           |
    |------+-------------------------------------------------------|
    |    1 | NumericRange(Decimal('10.0'), Decimal('100.0'), '[]') |
    +------+-------------------------------------------------------+

    참고 자료

  • Postgresql의 범위 데이터 유형에 대한 참고 범위 유형
  • Postgresql 범위 조작부호
  • 좋은 웹페이지 즐겨찾기