查询而不是遍历所有数据的更好方法

时间:2019-08-23 21:34:03

标签: ruby-on-rails activerecord

我有以下采用10位数字并搜索匹配项的方法:

  def self.get_agents_by_phone_number(phone_number)
        all_agents = Agent.all
        agents = Array.new
        all_agents.each do |a|
            if "1" + a.phone_number.scan(/\d/).join('').last(10) == phone_number
                agents << a
            end
        end
        return agents
  end

要注意的是,数据库中的phone_number字段尚未清除,并且可能采用几种不同的格式。这是一个示例:

2.5.3 :089 > Agent.all.pluck :phone_number
   (0.5ms)  SELECT "agents"."phone_number" FROM "agents"
 => ["1-214-496-5089", "193.539.7577", "557-095-1452", "(734) 535-5668", "(279) 691-4148", "(474) 777-3615", "137.158.9465", "(280) 680-8618", "296.094.7455", "1-500-079-7285", "1-246-171-1355", "1-444-626-9429", "(614) 603-6276", "594.170.4795", "1-535-859-1377", "676.706.4384", "256-312-4417", "1-592-904-2339", "174.912.8838", "677.137.7019", "319-013-7526", "(200) 790-1698", "576-106-0746", "(214) 042-9715", "(312) 188-5862", "1-823-392-9020", "663.331.4191", "237-101-0271", "1-836-465-1204", "394-499-0004", "713-068-1726", "1-223-484-7856"]

我在上面分享的方法有效,但感觉效率很低。在不接触数据库中数据的情况下,还有其他更好的方法吗?

2 个答案:

答案 0 :(得分:1)

那又怎么样:

#sample if incoming phone_num = "333.111.4444"
#You need to adjust it to possible ways and push to array.

options = Array.new
options << "1.333.111.4444"
options << "333.111.4444"
options << "1-333-111-4444"
options << "333-111-4444"
# and so on ...

# then query in where
Agent.where("phone_number IN (?)", options)

这比循环更好,只需要调整电话号码即可获得更好的性能。我不知道您的数据有多大,但是由于您要获取.all代理,因此它可能会很大:)

答案 1 :(得分:1)

我想您可以使用LIKE运算符,并在数字之间使用多个'%'通配符。

phone_number = '1234567890'

# split the number in groups
last4 = phone_number[-4..-1] # 7890
middle3 = phone_number[-7..-5] # 456
first3or4 = phone_number[0..-8] # 123

# build the pattern
pattern = "#{first3or4}%#{middle3}%#{last4}" # 123%456%7890

# use it for LIKE query 
Agent.where('phone_number LIKE ?', pattern)

使用所有这些通配符都不是快速查询。

https://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html#operator_like