搜索在存储数组的列中

时间:2017-09-04 07:49:02

标签: mysql sql ruby-on-rails ruby ruby-on-rails-4

在我的table_infos表中,有一列primary_skill_ids,它存储特定用户的一系列技能。我想列出所有具有某些特定技能的用户。 例子 -

user1 has primary_skill as ["1","3","5","9","4"]
user2 has primary_skill as ["1","7","9","4"]
user3 has primary_skill as ["1","4","11"]
user3 has primary_skill as ["7","9","4"]
user4 has primary_skill as ["1","7","9"]
user5 has primary_skill as ["7","9"]

现在我想进行一次搜索,例如让所有拥有任何或所有技能的用户为primary_skill_ids为[“1”,“4]

请帮我写一个rails查询来执行此操作。

我做了以下

     wildcard_search = "%#{params[:search_title]}%"
            # key skills and best in search
      @key_skills=[] 
     @key_skills.each do | sk |
     # here I am thinking of looping through the ids and do a where clause on column primary_skill_ids but dont know its good idea


            end

2 个答案:

答案 0 :(得分:3)

在字符串列中序列化关系数据违反了关系数据库的想法 - 即您具有指向其他表的外键列。在数据库中使用数组*或字符串类型进行关联是一个非常糟糕的主意:

  • 与包含整数或uiids的索引列相比,搜索字符串效率非常低。
  • 外键约束没有强制执行参照完整性。
  • 它不是ActiveRecord的工作方式 - 这意味着你将通过与框架作斗争来浪费时间。

相反,您想要创建many-to-many association through a join table

class User < ApplicationRecord
  has_many :user_skills
  has_many :skills, through: :user_skills
end

class Skill < ApplicationRecord
  has_many :user_skills
  has_many :users, through: :user_skills
end

class UserSkill < ApplicationRecord
  belongs_to :user
  belongs_to :skill
end

在此示例中,我们使用名为user_skills的表来连接两个模型:

create_table "user_skills", force: :cascade do |t|
  t.integer  "user_id"
  t.integer  "skill_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["skill_id"], name: "index_user_skills_on_skill_id", using: :btree
  t.index ["user_id"], name: "index_user_skills_on_user_id", using: :btree
end

然后,您可以使用集合助手设置UI控件:

# app/views/users/_form.html.erb
<%= form_for(@user) do |f| %>
  <%= f.collection_check_boxes :skill_ids, Skill.all, :id, :name %>
<% end %>

# app/controllers/users_controller.rb
class UsersController < ApplicationController
  # POST /users
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end

  # PUT|PATCH /users/:id
  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to @user
    else
      render :edit
    end
  end

  def user_params 
    params.require(:user)
          .permit(skill_ids: [])
  end
end

答案 1 :(得分:0)

PostgreSQL支持标准SQL数组和标准any操作语法:

因此,您可以使用类似

的SQL
where name ilike any (array['%val1%', '%val2%'])

使用Rails可以写成:

User.where('primary_skill ilike any (array[?])', ["1","4"] )

其他信息:

在您的情况下,您可以使用“ILIKE”或“LIKE”,但区别在于:

  • “ILIKE”不区分大小写
  • “LIKE”区分大小写。

使用通配符(%中的'%val1%')详细here