I wrote a query joining two tables
search_query =
from(
c in Chunk,
inner_join: r in Source,
on: c.source_id == r.id,
select: %{
id: c.id,
content_jsonpath: c.content_jsonpath,
rank: fragment("RANK() OVER (ORDER BY ?)", cosine_distance(c.embedding, ^vector)),
source_id: c.source_id,
content: fragment("jsonb_path_query(?, ?::jsonpath)", r.content, c.content_jsonpath)
},
order_by: [asc: cosine_distance(c.embedding, ^vector)],
limit: ^top_n
)
results =
Repo.all(search_query)
|> IO.inspect(label: "Semantic Search")
|> Enum.map(fn chunk ->
%ChunkSearchResult{}
|> ChunkSearchResult.changeset(chunk)
|> Ecto.Changeset.apply_changes()
end)
and I casted the results into ChunkSearchResult. This works, but I’m wondering if I’m doing this right. How do folks typically type their query results when a custom select: {} clause is used?
Here’s the ChunkSearchResult:
defmodule SightxrApi.Chunks.ChunkSearchResult do
use Ecto.Schema
import Ecto.Changeset
schema "chunks" do
field :source_id, :integer
field :content_jsonpath, :string
field :content, :string
field :rank, :integer
end
@doc false
def changeset(post, attrs) do
post
|> cast(attrs, [:source_id, :content_jsonpath, :content, :rank])
|> validate_required([:source_id, :content_jsonpath, :content, :rank])
end
end