Ruby筛选场地时仅匹配数组首个物种元素的问题求助
问题:多物种场地筛选仅匹配数组首位物种
我通过下拉框筛选包含特定物种的场地表格,部分场地存在多个物种。但筛选Horse时,只有该物种处于数组首位的场地能被找到,非首位的场地无法被筛选展示。
原查询代码
@species = params[:species].presence @default_species = @species.blank? ? 'All Species' : Species.find_cached_by_short_name(@species)&.long_name || @species @prems = StatevetPrem.unmatched.search(@search, @page, @lines_per_page, { order: @sort }) @prems = @prems.where(state: @state) if @state if @species prem_ids = StatevetDoc. unmatched. select(:holdings_match). where(default_species: @species). limit(@lines_per_page). collect { |doc| doc.holdings_match.values }. flatten. uniq[0,999] @prems = @prems.where(id: prem_ids) end
问题原因
代码中通过where(default_species: @species)筛选文档,但default_species字段仅存储了场地的首个物种,因此无法匹配到其他位置包含目标物种的场地。真正存储多物种信息的是holdings_match字段,需要针对该字段做包含查询。
修复方案
根据holdings_match的字段类型选择对应查询方式:
情况1:holdings_match是PostgreSQL JSONB字段
直接在数据库层面查询JSON结构中是否包含目标物种,避免先过滤default_species:
if @species # 查询holdings_match的所有值中是否包含目标物种 prem_ids = StatevetDoc.unmatched .where("jsonb_path_exists(holdings_match, '$.* ? (@ == ?)', ?)", @species) .pluck('jsonb_object_values(holdings_match)') .flatten .uniq .first(999) @prems = @prems.where(id: prem_ids) end
情况2:holdings_match是Rails序列化的数组/哈希
如果是序列化的数组,用包含查询匹配:
if @species prem_ids = StatevetDoc.unmatched .where("holdings_match @> ?", [@species].to_json) .collect { |doc| doc.holdings_match.values } .flatten .uniq .first(999) @prems = @prems.where(id: prem_ids) end
关键调整说明
- 移除了
where(default_species: @species)的限制,不再只匹配首位物种 - 直接针对
holdings_match字段做包含查询,确保所有包含目标物种的场地都能被检索到 - 如果
holdings_match结构特殊(比如嵌套更深),可以调整JSON路径查询语句适配你的数据结构
内容的提问来源于stack exchange,提问作者Solitary Coder
相关产品推荐
相关产品推荐

