Ash FrameworkAF
Ash Framework3y ago
7 replies
Blibs

Keyset pagination with calculations

I have the following action in my resource:

    read :all_by_name_or_address do
      argument :text, :string, allow_nil?: false

      pagination keyset?: true, default_limit: 10, required?: true

      filter expr(
               fragment("? %> ?", normalized_full_address, ^arg(:text)) or
                 fragment("? %> ?", name, ^arg(:text))
             )

      prepare build(
                sort: [
                  similarity: {:desc, %{address: arg(:text), name: arg(:text)}},
                  updated_at: :desc
                ]
              )
    end


As you can see, that action uses a :similarity calculation during sort, the calculation is as follows:

  calculations do
    calculate :normalized_full_address_similarity,
              :float,
              expr(fragment("word_similarity(?, ?)", ^arg(:address), normalized_full_address)) do
      argument :address, :string, allow_nil?: false
    end

    calculate :name_similarity,
              :float,
              expr(fragment("word_similarity(?, ?)", ^arg(:name), name)) do
      argument :name, :string, allow_nil?: false
    end

    calculate :similarity,
              :float,
              expr(
                fragment(
                  "greatest(?, ?)",
                  normalized_full_address_similarity(address: arg(:address)),
                  name_similarity(name: arg(:name))
                )
              ) do
      argument :address, :string, allow_nil?: false
      argument :name, :string, allow_nil?: false
    end
  end


If I run the action, it will work for the first page:

{:ok, reply} = PredefinedSchool.all_by_name_or_address(%{text: "Johnson Alternative"}, page: [limit: 5])


But now, if I try to get the second page, it fails:

after_keyset = List.last(reply.results).__metadata__.keyset

PredefinedSchool.all_by_name_or_address(%{text: "Johnson Alternative"}, page: [limit: 5, after: after_keyset])
Was this page helpful?