Rails: effective search by first and last name

I am trying to create a β€œsearch box” that matches users by name.

The difficulty is that the user has both a first name and a last name. Each of them can have spaces in it (for example, "Jon / Bon Jovi" or "Neil Patrick / Harris"), and I wonder how the most effective way to ensure that the search is performed when combining both the first name and the last name field.

The list of users is quite large, so performance is a problem. I could just specify the "full name" in the user model, but I suspect that this is not the wisest move. My knowledge of multi-column columns is weak, but I suspect there is a way to do this using an index with "" in it?

Just to clarify, I don’t need a fuzzy match - an exact match is just fine ... I just need it to start when two fields are concatenated.

Greeting...

+3
source share
2 answers

You can create a new field in your database called full_namewith a regular index, and then use the callback to populate this when the record is saved / updated:

before_save :populate_full_name

protected

def populate_full_name
  self.full_name = "#{first_name} #{last_name}"
end
+4
source

If you can change the database , you can and should use the solution provided by gjb.

Here is a solution in which you do not need to modify the database. Just collect all the possible first / last name pairs that you can get from the search box. Some code:

# 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.

+2

All Articles