You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Rails中基于Searchkick的关联书籍用户查询问题

解决Rails中Searchkick结合User/Book模型的三类查询需求

咱先把基础配置捋顺,确保你的模型关联和Searchkick索引设置正确,这是后续查询的前提:

模型关联设置

首先确认User和Book的关联已经正确定义:

# app/models/user.rb
class User < ApplicationRecord
  has_many :books, dependent: :destroy
  searchkick # 已启用Searchkick,接下来补充索引字段优化查询
end

# app/models/book.rb
class Book < ApplicationRecord
  belongs_to :user
end

Searchkick索引优化

为了让Searchkick能高效处理关联查询,需要在User模型的search_data方法里添加书籍相关字段,这样索引时会把这些数据同步到Elasticsearch:

# app/models/user.rb
def search_data
  {
    # 保留你原有的用户字段,比如name、email等
    name: name,
    email: email,
    # 添加书籍相关字段用于后续查询
    books_count: books.count,
    books_types: books.pluck(:type) # 提取所有关联书籍的类型数组
  }
end

修改完search_data后,记得重新索引用户数据,让新字段生效:

rails c
User.reindex

查询1:查询无关联Book的用户

有两种可行方案,按需选择:

方案1:用Searchkick高效查询(推荐大数据量使用

利用我们刚才索引的books_count字段,直接过滤数量为0的用户:

# 返回无关联书籍的用户集合,load: true会把结果转为ActiveRecord对象
User.search where: { books_count: 0 }, load: true

如果你的索引里直接存了完整的books关联数据,也可以用exists判断:

User.search where: { books: { exists: false } }, load: true

方案2:用ActiveRecord原生查询(适合小数据量或临时场景)

通过左外连接+空判断实现:

User.left_outer_joins(:books).where(books: { id: nil }).distinct

查询2:查询至少关联一本Book的用户

同样提供两种方案:

方案1:Searchkick查询(推荐大数据量使用

基于索引的books_count字段过滤数量大于0的用户:

User.search where: { books_count: { gt: 0 } }, load: true

或者用exists判断关联是否存在:

User.search where: { books: { exists: true } }, load: true

方案2:ActiveRecord原生查询

通过内连接自动过滤掉无关联的用户,distinct避免重复结果:

User.joins(:books).distinct

查询3:查询至少关联一本类型为‘Arts’的Book的用户

这个需求依赖我们索引的books_types字段,两种方案如下:

方案1:Searchkick查询(推荐

直接匹配类型数组中包含‘Arts’的用户:

User.search where: { books_types: 'Arts' }, load: true

默认情况下Searchkick会做分词和大小写兼容处理,如果你需要精确匹配,可以在索引配置里调整分词规则。

方案2:ActiveRecord原生查询

通过内连接+类型条件实现:

User.joins(:books).where(books: { type: 'Arts' }).distinct

内容的提问来源于stack exchange,提问作者Hamza Iftikhar

火山引擎 最新活动