Picky Search Options

ruby / picky / api

A few examples of what search options are there Picky.

We’re going to look at a simple example and how to search it with Picky 4.0!

The Copy & Paste Example

(This is the same example as in the last post)

The example is simple. We have an index of 4 persons (you might recognize the two famous ones). Each person has a first and a last name. Then we use a Search object on the index to search on it.

Go ahead, copy it into TextMate or similar!

require 'picky'

Person = Struct.new :id, :first, :last

data = Picky::Index.new :people do
  category :first
  category :last
end

data.replace Person.new(1, 'Donald', 'Knuth')
data.replace Person.new(2, 'Niklaus', 'Wirth')
data.replace Person.new(3, 'Donald', 'Worth')
data.replace Person.new(4, 'Peter', 'Niklaus')

people = Picky::Search.new data

results = people.search 'donald'

p results.ids
p results.allocations

This returns ids [3, 1] and the allocations [ [:people, 0.0, 2, [ [:first, "donald", "donald"] ], [3, 1]] ]. That might look a little funny, so let me explain: :people is the index name where it was found. 0.0 is the total weight. 2 is the total number of ids in this “allocation” (combination of categories). [:first, "donald", "donald"] is the category the query word was found in, together with the token and the original.

All clear?

Try searching for “Niklaus”:

results = people.search 'niklaus'

You should find ids [2, 4] and two allocations now, first in the first name, then in the last name.

Cool. Are there some options to fudge the search?

Sure!

boost

To move an allocation up in the ranking, we used weights (see last post).

Picky knows a trick that almost no search engine knows. It can boost combinations!

Look for:

results = people.search 'Donald Knuth'

Looking at the allocations, we see that Picky tells us that Donald was found in a first name, and Knuth in a last name:

[[:people, 0.693, 1, [[:first, "donald", "donald"], [:last, "knuth", "knuth"]], [1]]]

That’s pretty useful to know what was found where.

As people usually look for the first name, then the last name, we want to give this more boost.

Replace this:

people = Picky::Search.new data

with this

people = Picky::Search.new data do
  boost [:first, :last] => +3
end

Now try again:

results = people.search 'Donald Knuth'

A whole 3 points more! Try it the other way around:

results = people.search 'Knuth Donald'

We don’t get the boost. This is incredibly useful: If you look at how people search and then support them this way, they will find relevant results even easier!

max_allocations

Sometimes you only want the best allocation to appear in the results.

results = people.search 'Niklaus'

This finds two ids and two allocations, once in the first name, once in the last name.

Replace:

people = Picky::Search.new data do
  max_allocations 1
end

Now Picky only calculates 1 allocation. Try

results = people.search 'Niklaus'

Only the best allocation is found.

ignore_unassigned_tokens

Did Donald Knuth ever have the nickname “Popeye”? Try this:

results = people.search 'Donald Popeye Knuth'

Not really. But what if we want to find him even if one token cannot be assigned to a category?

people = Picky::Search.new data do
  ignore_unassigned_tokens
end

Try again:

results = people.search 'Donald Popeye Knuth'

Voilà!

This is incredibly useful for an advertisement search. Say in the ads index you only index the city where a person lives. If someone looks for Florian Hanke Melbourne, you can show the person relevant ads from Melbourne.

terminate_early

Search for niklaus, and tell Picky you only want 1 id:

results = people.search 'Niklaus', 1

Yes, Picky only calculates 1 id, but still calculates and returns all valid allocations. if you only really need the ids (the Picky interface needs the allocations), then this is unnecessary and could be faster.

Replace:

people = Picky::Search.new data do
  terminate_early
end

Try again:

results = people.search 'Niklaus', 1

Hey presto! Just one allocation.

This code

people = Picky::Search.new data do
  terminate_early +2
end

will tell Picky to calculate all necessary allocations, plus 2 following ones, for good measure.

ignore

Try this:

results = people.search 'Niklaus'

You’ll get results in first and last name. If you only wanted results from the first name, you’d search for this:

results = people.search 'first:Niklaus'

Cool. But let’s say: You, the search engine designer, don’t want anybody to find anything in a last name, for any reason. Using first: will select only first. But you might only want to remove the last category. Do this:

people = Picky::Search.new data do
  ignore :last
end

Try again:

results = people.search 'Niklaus'

Niklaus is not found in the last name again.

You can give it even more:

people = Picky::Search.new data do
  ignore :first, :last
end

But that is pretty silly in this example. Picky won’t find anything anymore!

Conclusion

And that’s the options the Picky Search object has. As you’ve seen in the last post, some searching is defined on the indexes, but some options are exclusive to the search side, and are only defined there.

It’s best to play a bit to unlock their versatility and power :)

Next Why I don't use round brackets

Share


Previous

Comments?