通过ecto存储jsonb数据

时间:2018-04-28 13:35:38

标签: postgresql elixir ecto jsonb

我试图通过ecto将jsonb数据传递到postgres。我希望能够获取有效的JSON字符串,将其添加为graphql参数,并在我的表中查看json。

迁移

defmodule MyApp.CreateJsonTable do
  use Ecto.Migration

  def change do
    create table(:geodata) do
      add(:json, :map)

      timestamps(type: :utc_datetime)
    end
  end
end

我的理解是你需要为JSONB定义Poison的结构,然后在插入时解码为。

defmodule Geodatajson do
  use MyApp, :model

  embedded_schema do
    field(:latitude, :float)
    field(:longitude, :float)
  end
end

现在的模型:

defmodule MyApp.Geodata do
  use MyApp, :model

  alias MyApp.Repo
  alias MyApp.Geodata

  schema "geodata" do
    embeds_one(:json, Geodatajson)

    timestamps()
  end

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:json])
  end

  def add_geodata(str) do
    json = str |> Poison.decode!(as: Geodatajson)
    data = %Geodata{json: json}
    Repo.insert(data)
  end
end

我尝试传递这样的数据:

iex> MyApp.Geodata.add_geodata("{\"latitude\": 1.23, \"longitude\": 4.56}")

但是JSONB没有被解码:

{:ok,
 %MyApp.Geodata{
   __meta__: #Ecto.Schema.Metadata<:loaded, "geodata">,
   id: 26,
   inserted_at: ~N[2018-04-28 13:28:42.346382],
   json: %Geodatajson{
     id: "3b22ef94-92eb-4c64-8174-9ce1cb88e8c5",
     latitude: nil,
     longitude: nil
   },
   updated_at: ~N[2018-04-28 13:28:42.346392]
 }}

如何将这些数据导入postgres?

1 个答案:

答案 0 :(得分:0)

Poison&#39; // available ingredients val ingredients = Seq("tomatoes", "cheese", "ham", "mushrooms", "pepper", "salt") // predicates def isVegetarian(ingredient: String): Boolean = ingredient != "ham" def isSpicy(ingredient: String): Boolean = ingredient == "pepper" def isSalty(ingredient: String): Boolean = ingredient == "salt" // to negate another predicate def not(predicate: (String) => Boolean)(ingr: String): Boolean = !predicate(ingr) // sequences of conditions for different pizzas: val vegeterianSpicyPizza: Seq[(String) => Boolean] = Seq(isSpicy, isVegetarian) val carnivoreSaltyNoSpices: Seq[(String) => Boolean] = Seq(not(isSpicy), isSalty) // main function: builds a list of ingredients for specified conditions! def buildIngredients(recipe: Seq[(String) => Boolean]): Seq[String] = { ingredients.filter(ingredient => recipe.exists(_(ingredient))) } println("veg spicy: " + buildIngredients(vegeterianSpicyPizza)) // veg spicy: List(tomatoes, cheese, mushrooms, pepper, salt) println("carn salty: " + buildIngredients(carnivoreSaltyNoSpices)) // carn salty: List(tomatoes, cheese, ham, mushrooms, salt) 要求您传递结构实例,而不仅仅是模块的名称。

as:

应该是:

json = str |> Poison.decode!(as: Geodatajson)