Skip to content

Commit

Permalink
+ experimental only category preselection functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
floere committed Dec 30, 2011
1 parent 02a7462 commit 59b308b
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 31 deletions.
4 changes: 4 additions & 0 deletions history.textile
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
h2. Upcoming Version

h2. 4.0.5

* hanke: (server) Experimental release of @only@ option for searches. Does the same as @only:that_category@, but implicitly, in the search. E.g. @only :cat1, :cat2@.

h2. 4.0.4

* hanke: (server) Default amount of similar tokens is now set to 3 instead of 10 for phonetic similarities.
Expand Down
25 changes: 15 additions & 10 deletions server/lib/picky/query/indexes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,8 @@ def initialize *indexes
IndexesCheck.check_backends indexes

@indexes = indexes

map_categories
end
def map_categories
@mapper = Query::QualifierCategoryMapper.new
@indexes.each do |index|
index.each_category do |category|
@mapper.add category
end
end

@mapper = QualifierCategoryMapper.new indexes # TODO Move out?
end

# Ignore the categories with these qualifiers.
Expand All @@ -51,6 +43,19 @@ def ignore *qualifiers
@ignored_categories += qualifiers.map { |qualifier| @mapper.map qualifier }.compact
@ignored_categories.uniq!
end

# Restrict categories to the given ones.
#
# Functionally equivalent as if indexes didn't
# have the categories at all.
#
# Note: Probably only makes sense when an index
# is used in multiple searches. If not, why even
# have the categories?
#
def only *qualifiers
@mapper.restrict_to *qualifiers
end

# Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
#
Expand Down
22 changes: 20 additions & 2 deletions server/lib/picky/query/qualifier_category_mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ module Query
class QualifierCategoryMapper # :nodoc:all

attr_reader :mapping

#
#
def initialize
def initialize indexes
@mapping = {}
indexes.each do |index|
index.each_category do |category|
add category
end
end
end

#
Expand All @@ -35,6 +40,19 @@ def map qualifier

@mapping[qualifier.intern]
end

# Restricts the given categories.
#
def restrict user_qualified
if @restricted
user_qualified ? @restricted & user_qualified : @restricted
else
user_qualified
end
end
def restrict_to *qualifiers
@restricted = qualifiers.map { |qualifier| map qualifier }.compact
end

end

Expand Down
15 changes: 11 additions & 4 deletions server/lib/picky/query/token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,20 @@ def symbolize!

# Translates this token's qualifiers into actual categories.
#
# Note:
# If this is not done, there is no mapping.
# Note: If this is not done, there is no mapping.
# Note: predefined is an Array of mapped categories.
#
# THINK Can this be improved somehow?
# TODO Rename @user_defined_categories. It could now also be predefined by the query.
#
def categorize mapper
@user_defined_categories = @qualifiers && @qualifiers.map do |qualifier|
@user_defined_categories ||= extract_predefined mapper
end
def extract_predefined mapper
user_qualified = categorize_with mapper, @qualifiers
mapper.restrict user_qualified
end
def categorize_with mapper, qualifiers
qualifiers && qualifiers.map do |qualifier|
mapper.map qualifier
end.compact
end
Expand Down
5 changes: 3 additions & 2 deletions server/lib/picky/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Search
:boosts

delegate :ignore,
:only,
:to => :indexes

# Takes:
Expand All @@ -37,8 +38,8 @@ class Search
# [:title, :isbn] => +1
# end
#
def initialize *index_definitions
@indexes = Query::Indexes.new *index_definitions
def initialize *indexes
@indexes = Query::Indexes.new *indexes

instance_eval(&Proc.new) if block_given?

Expand Down
49 changes: 49 additions & 0 deletions server/spec/functional/only_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# encoding: utf-8
#
require 'spec_helper'

describe 'Search#only' do

it 'offers the option only' do
index = Picky::Index.new :only do
category :text1
category :text2
category :text3
end

index.add Struct.new(:id, :text1, :text2, :text3).new(1, 'text1', 'text2', 'text3')

try = Picky::Search.new index
try.search('text1').ids.should == [1]
try.search('text2').ids.should == [1]
try.search('text3').ids.should == [1]

try_again = Picky::Search.new index do
only :text1
end
try_again.search('text1').ids.should == [1]
try_again.search('text2').ids.should == []
try_again.search('text3').ids.should == []

try_again.only :text2, :text3
try_again.search('text1').ids.should == []
try_again.search('text2').ids.should == [1]
try_again.search('text3').ids.should == [1]

try_again.search('text1:text1').ids.should == []
try_again.search('text2:text2').ids.should == [1]
try_again.search('text3:text3').ids.should == [1]

try_again.search('text1,text2,text3:text1').ids.should == []
try_again.search('text1,text2:text1').ids.should == []
try_again.search('text1,text3:text1').ids.should == []

try_again.search('text1,text2,text3:text2').ids.should == [1]
try_again.search('text1,text2:text2').ids.should == [1]
try_again.search('text1,text3:text2').ids.should == []

try_again.search('text1,text2,text3:text3').ids.should == [1]
try_again.search('text1,text2:text3').ids.should == []
try_again.search('text1,text3:text3').ids.should == [1]
end
end
6 changes: 2 additions & 4 deletions server/spec/lib/query/indexes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
end

3.times do |i|
n = i + 1
name = :"index#{n}"
indexed = :"indexed#{n}"
let(name) { stub name, :internal_indexed => stub(indexed) }
name = :"index#{i+1}"
let(name) { Picky::Index.new(name) }
end

let(:indexes) do
Expand Down
16 changes: 8 additions & 8 deletions server/spec/lib/query/qualifier_category_mapper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

describe Picky::Query::QualifierCategoryMapper do

let(:mapper) { described_class.new }
before(:each) do
@category1 = stub(:category1, :qualifiers => ['t1', 'tt1', 'ttt1'])
@category2 = stub(:category2, :qualifiers => [:t2, :tt2, :ttt2])
@category3 = stub(:category3, :qualifiers => [:t3, :tt3, :ttt3])
mapper.add @category1
mapper.add @category2
mapper.add @category3
let(:index) do
categories = Picky::Index.new :categories
@category1 = categories.category :category1, :qualifiers => ['t1', 'tt1', 'ttt1']
@category2 = categories.category :category2, :qualifiers => [:t2, :tt2, :ttt2]
@category3 = categories.category :category3, :qualifiers => [:t3, :tt3, :ttt3]
categories
end
let(:indexes) { [index] }
let(:mapper) { described_class.new indexes }

def self.it_should_map(qualifier, expected)
it "should map #{qualifier} to #{expected}" do
Expand Down
58 changes: 58 additions & 0 deletions server/spec/lib/query/token_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,64 @@
described_class.processed('similar~', 'Similar~').should_not == described_class.processed('similar', 'Similar')
end
end

describe 'categorize' do
let(:mapper) do
categories = Picky::Index.new :categories
@category1 = categories.category :category1
@category2 = categories.category :category2
@category3 = categories.category :category3
Picky::Query::QualifierCategoryMapper.new [categories]
end
context 'with qualifiers' do
let(:token) { described_class.processed 'category1:qualifier', 'category1:Qualifier' }
context 'unrestricted' do
it 'categorizes correctly' do
token.categorize(mapper).should == [@category1]
end
end
context 'restricted' do
before(:each) do
mapper.restrict_to :category1
end
it 'categorizes correctly' do
token.categorize(mapper).should == [@category1]
end
end
context 'restricted' do
before(:each) do
mapper.restrict_to :category2, :category3
end
it 'categorizes correctly' do
token.categorize(mapper).should == []
end
end
end
context 'without qualifiers' do
let(:token) { described_class.processed 'noqualifier', 'NoQualifier' }
context 'unrestricted' do
it 'categorizes correctly' do
token.categorize(mapper).should == nil
end
end
context 'restricted' do
before(:each) do
mapper.restrict_to :category1
end
it 'categorizes correctly' do
token.categorize(mapper).should == [@category1]
end
end
context 'restricted' do
before(:each) do
mapper.restrict_to :category2, :category3
end
it 'categorizes correctly' do
token.categorize(mapper).should == [@category2, @category3]
end
end
end
end

describe 'similar_tokens_for' do
let(:token) { described_class.processed 'similar~', 'Similar~' }
Expand Down
2 changes: 1 addition & 1 deletion version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Picky
VERSION = '4.0.4'
VERSION = '4.0.5'
end

0 comments on commit 59b308b

Please sign in to comment.