如何用Ecto查询嵌套map中status为accepted的Event记录?是否需原生SQL?
嘿,刚好对Ecto的这类嵌套字段查询熟得很,完全不需要写原生SQL,给你几种简便的实现方式,根据你的fields字段类型来选就行:
情况1:
fields是PostgreSQL的JSONB字段(最常见场景) 如果你的Event表中fields字段定义的是JSONB类型(这是Elixir/Ecto生态里存储嵌套map的常规操作),有三种直观的写法:
写法1:最简洁的Ecto 3.10+语法
从Ecto 3.10版本开始,支持直接用Map的Access语法来查询JSONB嵌套字段,代码超清爽:
from e in Event, where: e.fields["status"] == "accepted"
Ecto会自动把这个语法转换成对应的PostgreSQL JSONB查询语句,完全不用你操心底层细节。
写法2:用fragment配合JSONB操作符
如果你用的是旧版Ecto,或者想更明确控制SQL逻辑,可以用fragment搭配PostgreSQL的->>操作符(用来提取字符串类型的嵌套字段值):
from e in Event, where: fragment("?->>'status' = ?", e.fields, "accepted")
写法3:用PostgreSQL内置函数(可读性更强)
还有一种更具语义化的写法,调用PostgreSQL的jsonb_extract_path_text函数:
from e in Event, where: fragment("jsonb_extract_path_text(?, ?) = ?", e.fields, "status", "accepted")
情况2:
fields是Ecto嵌入式Schema 如果你是用Ecto的嵌入式Schema来定义fields的结构(比如提前定义了EventFields嵌入式模型):
# 嵌入式Schema定义 defmodule EventFields do use Ecto.Schema embedded_schema do field :status, :string field :other_field, :string end end # 主Event Schema关联 defmodule Event do use Ecto.Schema schema "events" do field :external_id, :integer field :type, :string embeds_one :fields, EventFields end end
那查询起来更直接,直接通过嵌入式字段的属性来过滤:
from e in Event, where: e.fields.status == "accepted"
总结一下:不管哪种情况,都不用写原生SQL,用Ecto自带的查询语法就能轻松搞定嵌套字段的过滤需求~
内容的提问来源于stack exchange,提问作者ugotchi
相关产品推荐
相关产品推荐

