optional case-insensitivity for searching
authorTony Cook <tony@develop-help.com>
Fri, 7 Jul 2017 01:57:18 +0000 (11:57 +1000)
committerTony Cook <tony@develop-help.com>
Fri, 7 Jul 2017 01:57:18 +0000 (11:57 +1000)
with some support work for future run-time selectable case-sensitivity

site/cgi-bin/modules/BSE/Index.pm
site/cgi-bin/modules/BSE/Index/BSE.pm
site/cgi-bin/modules/BSE/Search/BSE.pm
site/cgi-bin/modules/BSE/UI/Search.pm
site/docs/config.pod

index 75ee8fbddc424d4ba5f01d46ef0beb96c36188d7..fccc28ede5e61e4fe85ca2cc4ad7011398c8f000 100644 (file)
@@ -4,7 +4,7 @@ use Time::HiRes qw(time);
 use Constants qw(@SEARCH_EXCLUDE @SEARCH_INCLUDE);
 use BSE::TB::Articles;
 
-our $VERSION = "1.006";
+our $VERSION = "1.007";
 
 my %default_scores =
   (
@@ -46,12 +46,16 @@ sub indexer {
     my $indexer_class = $cfg->entry('search', 'indexer', 'BSE::Index::BSE');
     (my $indexer_file = $indexer_class . ".pm") =~ s!::!/!g;
     require $indexer_file;
+    my $case_sensitivity = $cfg->entry('search', 'case_sensitive', 'context');
+    $case_sensitivity =~ /^(none|context|controlled)$/
+      or die "[search].case_sensitive must be none, context or controlled\n";
 
     $self->{indexer} = $indexer_class->new
       (
        cfg => $cfg,
        scores => $self->{scores},
        verbose => $self->{verbose},
+       case => $case_sensitivity,
       );
   }
 
index 4a65afeafd60b975053de99622080d0c663ba534..7958644af89c5132bf772d0107876ed3d055224e 100644 (file)
@@ -5,7 +5,7 @@ use BSE::DB;
 use Constants qw($MAXPHRASE);
 use BSE::CfgInfo qw(cfg_data_dir);
 
-our $VERSION = "1.003";
+our $VERSION = "1.004";
 
 sub new {
   my ($class, %opts) = @_;
@@ -18,6 +18,9 @@ sub new {
   $self->{insertIndex} = $self->{dh}->stmt('insertIndex')
     or die "No insertIndex member in BSE::DB";
 
+  $self->{case} eq 'controlled'
+    and die "BSE built-in searcher doesn't support controlled search (yet)";
+
   my $priority = $self->{cfg}->entry("search", "index_priority", "speed");
   if ($priority eq "speed") {
     $self->{index} = {};
@@ -114,17 +117,22 @@ sub process {
     $end = $#words if $end > $#words;
     
     for my $phrase (map { "@words[$start..$_]" } $start..$end) {
-      if (lc $phrase ne $phrase && !$seen->{lc $phrase}++) {
-       my $temp = $self->{index}{lc $phrase};
-       if (exists $temp->{$id}) {
-         $weights->{lc $phrase} *= $self->{decay_multiplier};
-         $temp->{$id}[1] += $score * $weights->{lc $phrase};
-       }
-       else {
-         $weights->{lc $phrase} = 1.0;
-         $temp->{$id} = [ $sectionid, $score ];
+      if ($self->{case} eq 'context') {
+       if (lc $phrase ne $phrase && !$seen->{lc $phrase}++) {
+         my $temp = $self->{index}{lc $phrase};
+         if (exists $temp->{$id}) {
+           $weights->{lc $phrase} *= $self->{decay_multiplier};
+           $temp->{$id}[1] += $score * $weights->{lc $phrase};
+         }
+         else {
+           $weights->{lc $phrase} = 1.0;
+           $temp->{$id} = [ $sectionid, $score ];
+         }
+         $self->{index}{lc $phrase} = $temp;
        }
-       $self->{index}{lc $phrase} = $temp;
+      }
+      else {
+       $phrase = lc $phrase;
       }
       if (!$seen->{$phrase}++) {
        my $temp = $self->{index}{$phrase};
index 871173bd07506d2697f43973fe0af05e45bd112c..d759742bc13c9ce63e99e91af79ad32c12c9d768 100644 (file)
@@ -2,7 +2,7 @@ package BSE::Search::BSE;
 use strict;
 use Constants qw(:search);
 
-our $VERSION = "1.000";
+our $VERSION = "1.001";
 
 use base 'BSE::Search::Base';
 
@@ -53,11 +53,13 @@ sub get_term_matches {
 }
 
 sub search {
-  my ($self, $words, $section, $date, $terms, $match_all, $req) = @_;
+  my ($self, $words, $section, $date, $terms, $match_all, $req, $match_case) = @_;
 
   # canonical form
   $words =~ s/^\s+|\s+$//g;
 
+  $words = lc $words unless $match_case;
+
   # array of [ term, unquoted, required, weight ]
   my @terms;
   my @exclude;
index e0d5722f7a9324206441ad8c15a5b77d71f6344a..9b32c55842da2212ec329ec4afc725a039264892 100644 (file)
@@ -11,7 +11,7 @@ use BSE::Util::HTML qw':default popup_menu';
 use BSE::Util::Tags qw(tag_article);
 use BSE::Request;
 
-our $VERSION = "1.005";
+our $VERSION = "1.006";
 
 my %actions =
   (
@@ -41,8 +41,18 @@ sub req_search {
   my @terms; # terms as parsed by the search engine
   my $case_sensitive;
   if (defined $words && length $words) {
-    $case_sensitive = $words ne lc $words;
-    @results = getSearchResult($req, $words, $section, $date, \@terms, $match_all);
+    my $case = $cfg->entry('search', 'case_sensitive', 'context');
+    if ($case eq 'context') {
+      $case_sensitive = $words ne lc $words;
+    }
+    elsif ($case eq 'controlled') {
+      $case_sensitive = $cfg->param('c') || 0;
+    }
+    else {
+      $case_sensitive = 0;
+    }
+    @results = getSearchResult($req, $words, $section, $date, \@terms, $match_all,
+                              $case_sensitive);
   }
   else { 
     $words = ''; # so we don't return junk for the form default
@@ -324,14 +334,15 @@ sub tag_highlight_result {
 }
 
 sub getSearchResult {
-  my ($req, $words, $section, $date, $terms, $match_all) = @_;
+  my ($req, $words, $section, $date, $terms, $match_all, $match_case) = @_;
 
   my $cfg = $req->cfg;
   my $searcher_class = $cfg->entry('search', 'searcher', 'BSE::Search::BSE');
   (my $searcher_file = $searcher_class . '.pm') =~ s!::!/!g;;
   require $searcher_file;
-  my $searcher = $searcher_class->new(cfg => $cfg);
-  return $searcher->search($words, $section, $date, $terms, $match_all, $req);
+  my $case_sensitivity = $cfg->entry('search', 'case_sensitive', 'context');
+  my $searcher = $searcher_class->new(cfg => $cfg, case => $case_sensitivity);
+  return $searcher->search($words, $section, $date, $terms, $match_all, $req, $match_case);
 }
 
 my %gens;
index e4131f8fb61bbf25d8066dda252ab59edd1c8d82..6c0011fc0d09b9144b5833d9c3f33682c57881cd 100644 (file)
@@ -842,6 +842,31 @@ module be installed.
 Articles with a higher level than this are indexed as their ancestor.
 Default: C<$SEARCH_LEVEL> which defaults to 5.
 
+=item case_sensitive
+
+Level of case-sensitivity in the search engine.  This can be one of:
+
+=over
+
+=item *
+
+C<none> - no case-sensitive searches
+
+=item *
+
+C<context> - case-sensitive if there are any upper-case characters in
+the search string, case-insensitive otherwise.
+
+=item *
+
+C<controlled> - case-sensitive via a query parameter.  This is
+currently not supported by the built-in search engie.
+
+=back
+
+Renegerate your search indexes after changing this value.  Default:
+context.
+
 =back
 
 =head2 [search highlight]