我正在尝试创建一个按名称匹配用户的“搜索框”。
困难在于用户同时拥有名字和姓氏。每个都可以有空格(例如“Jon / Bon Jovi”,或“Neil Patrick / Harris”),我想知道确保搜索是在第一个名字的连接上进行搜索的最有效方法和姓氏领域。
用户列表非常大,因此性能受到关注。我可以在用户模型中抛出一个“全名”def,但我怀疑这并不是最明智的移动性能。我对多列rails索引的了解很少,但我怀疑有一种方法可以通过带有“”的索引来实现吗?
只是为了澄清,我不需要模糊匹配 - 完全匹配只是很好......我只需要它在两个字段的串联上运行。
干杯...
答案 0 :(得分:4)
您可以使用常规索引在数据库中创建名为full_name
的新字段,然后在保存/更新记录时使用回调填充此字段:
before_save :populate_full_name
protected
def populate_full_name
self.full_name = "#{first_name} #{last_name}"
end
答案 1 :(得分:2)
如果您可以修改数据库,您可以而且应该使用gjb提供的解决方案。
以下是不要求您更改数据库的解决方案。只需收集您可以从搜索框中获得的所有可能的名字/姓氏对。一些代码:
# this method returns an array of first/last name pairs given the string
# it returns nil when the string does not look like a proper name
# (i.e. "Foo Bar" or "Foo Bar Baz", but not "Foo" or "Foo "
def name_pairs(string)
return nil unless string =~ /^\w+(\s+\w+)+$/
words = string.split(/\s+/) # split on spaces
result = []
# in the line below: note that there is ... and .. in the ranges
1.upto(words.size-1) {|n| result << [words[0...n], words[n..-1]]}
result.collect {|f| f.collect {|nm| nm.join(" ")}}
end
此方法为您提供了一个包含两个元素数组的数组,您可以使用它来创建or
查询。以下是该方法的外观:
#> name_pairs("Jon Bon Jovi")
=> [["Jon", "Bon Jovi"], ["Jon", "Bon Jovi"]]
#> name_pairs("John Bongiovi")
=> [["John", "Bongiovi"]]
#> name_pairs("jonbonjovi")
=> nil
当然,这种方法并不完美(它不会将名称大写,但你可以在拆分后进行)并且在速度方面可能不是最优的,但它可以工作。您也可以重新打开String
并在那里添加方法,这样您就可以使用"Jon Bon Jovi".name_pairs
。