我正在做一个项目,有CUE模型,可以访问和搜索多个角色,如客人和管理员.基于能力类中编写的一些逻辑,使用CanCanCan gem进行授权.当搜索发生时,使用Pagy/MeiliSearch组合来进行全文搜索和分页.我现在面临的问题是,当我作为客人搜索时,我可以看到客人应该看到的正确项目,当我作为管理员搜索时,我可以看到管理员应该看到的正确项目,但Pagy gem计数是错误的.这是我的代码:

class SearchesController < ApplicationController
  INCLUDES = %i[medium speakers].freeze

  include Pagy::Backend

  authorize_resource class: false

  def search
    filter = ''
    filter = "speaker_ids IN [#{params[:speaker]}]" if params[:speaker].present?

    search_results = Cue.accessible_by(current_ability).includes(INCLUDES).pagy_search(params[:query], filter:)
    @pagy, @search_results = pagy_meilisearch(search_results)
  end
end

如果有一些访客无法访问的提示,搜索将不会在@search_results中返回它们,但@pagy对象会将它们计入.这向用户显示不正确的计数,并且还显示少于所需的Pagy::DEFAULT[:items].我试了很多办法,但都没有成功.我能想到的唯一事情(我不想走这条路)是将过滤逻辑本身添加到filter字符串中,并将所需的参数添加到索引中.但这会很复杂,而且会增加索引的大小.你有什么 idea 吗?

推荐答案

感谢@Abdelrahman-Haider的提示,这很有用.

基本上,除非我们在MeiliSearch索引本身内部实现过滤逻辑,否则我们无法解决这个问题.因此,我所做的是使用Cancan功能提取过滤条件,并手动将其转换为MeiliSearch过滤字符串.

要获取特定型号在特定控制器操作上的扫描能力条件,我们可以执行以下操作:

cue_conditions = current_ability.model_adapter(Cue, :show).conditions

然后,我们可以将cue_conditions传递给另一个方法,将它们转换为MeiliSearch筛选字符串,如下所示:

def ability_conditions_to_meilisearch_filter(condition)
  condition.map do |key, value|
    case value
    when Array then "#{key} IN [#{value.join(',')}]"
    when NilClass then "#{key} NOT EXISTS"
    when TrueClass, FalseClass then "#{key} = #{value}"
    when Hash then hash_condition_to_filter(key, value)
    else "#{key} = '#{value}'"
    end
  end.join(' AND ')
end

def hash_condition_to_filter(key, value)
  case value.keys[0]
  when :gt then "#{key} > #{value[:gt]}"
  when :gte then "#{key} >= #{value[:gte]}"
  when :lt then "#{key} < #{value[:lt]}"
  when :lte then "#{key} <= #{value[:lte]}"
  when :to then "#{key} #{value[:to].first} TO #{key} #{value[:to].last}"
  end
end

ability_conditions_to_meilisearch_filter方法实现不是最好的实现,但它目前满足了我的需求,我将在以后try 改进它.

请注意,您需要向您的MeiliSearch索引添加所需的属性.

我希望这会有帮助,因为我在互联网上没有找到任何相关的东西:)如果你想支持,我向meilisearch-rails GitHub repo:https://github.com/meilisearch/meilisearch-rails/issues/255提交了一个功能请求.

最后,感谢@abdelrahman-haider和poe.com的帮助:3

Ruby-on-rails相关问答推荐

Rails:嵌套命名空间产生一个奇怪的部分路径,导致MissingTemplate错误

Rails 7.1中的覆盖脚手架控制器

本地主机的上衣配置

安装特定版本的Ruby时出现问题(OpenSSL问题)

在Ruby on Rails中获取堆栈级别太深错误(&Q)

GO AES GCM加密在解密时出错&S

将两个日期之间的差值转换为Ruby中的iso8601持续时间(如果需要,还可以使用Rails)

使用ActiveSupport::TimeWithZone将UTC转换为用户定义的时区

Rails引擎importmap Uncaught ReferenceError:未定义tinymce

如何从 Rails7.2 中的控制器获取名称空间?

Rails 7 中的预编译

刺激不添加侦听器以搜索表单输入

使用brew 软件安装了 elasticsearch,但找不到配置文件

骨干model.destroy()即使工作正常也会调用错误回调函数?

未定义的方法 attr_accessible

Rails 3 返回 HTTP 406 Not Acceptable?

Dotenv 多行变量

如何为 Rails 迁移定义布尔字段

Rails:在 link_to 中保留 GET 查询字符串参数

如何删除删除选项表单 activeAdmin?