Gossamer Forum
Home : Products : DBMan : Customization :

DBMan Boolean MOD

Quote Reply
DBMan Boolean MOD
OK. Apparently there has been some requests for the boolean MOD I developed earlier this year. And, seeing as my website was wiped a couple months ago, I shall endeavour to post the necessary componants of the modification here.

There are essentially two different ways to perform boolean searching in DBMan. I preferred the first, which entailed writing a completely independant script to search the database file and return the results by itself. This was extremely effective, though it should be considered a seperate script entirely, as the only thing it has in common with DBMan is the database file, a few html routines, and the way the output results look. The second works, but is a bit on the "klunky" side. I'll post them both below.


--------
METHOD 1
--------

1) Create a new CGI file, named BOOLEAN.CGI and place it in your DBMAN directory.

2) Input the following code into it:

#!/usr/bin/perl

require "html.pl";

# define some global variables

$fields = 12; # Number if fields in each record
$filename="default.db"; # The database flattext filename
$results=1000; # Max number of results to display
my $font_color='Font face="Vernada,Arial,Helvetica" Size=2 Color="#003399';
my $font = 'Font face="Vernada,Arial,Helvetica" Size=2';
&parse_form;
$searchstring=$FORM{'searchstring');
# We don't want to search for the word 'and' or 'or'. Let's remove them.
$searchstring =~ s/ and / /gi;
$searchstring =~ s/ or / /gi;

&open_file('FILE1","",$filename);
&html_print_headers;
########
# Copy the first print qq section from html_view_success here
########
&html_print_headers;
print qq|
<html>
<head>
<title>title</title>
</head>
You searched for $searchstring:<BR>
|;
&track_kwords;
$counter=0;
while (($line=&read_file("FILE1")) && ($counter < $results)) {
# split the fields at the | pipe character
@tabledata = split(/\s*\|\s*/,$line,$fields);
&check_record;
if($found == 1) {
$counter++;
&print_record;
}
}
close(FILE1);
print "</UL>\n";

if($counter == 0) {
print "<BR><B>Sorry, no matches were found.</B><BR>\n";
}
}
######
# Copy the code from a regular search results' footer and paste here
######
print qq|
</body>
</html>
|;

sub print_record {

######
# Copy the code from sub html_record here. This will require a good
# deal of modifying. Replace $rec{'whatever'} with $whatever (as defined
# in sub check_record, below) for every record data you want
# listed. Unfortunately as the two scripts don't work exactly in tandum,
# you cannot call sub html_record directly from here.
######

print qq|
$linktitle<BR>
$linkdescription<BR>
$linkphone<BR>
<HR>
|;
}


sub check_record {
# get the data from the record read from the file. $tabledata

$linktitle = $tabledata[0];
$linkdescription = $tabledata[1];
$linkphone = $tabledata[2];

# Build the search line with all fields we want to search in.
$searchline = $linktitle . " " . $linkdescription . " " . $linkphone;

# search by keywords
# only perform the keyword search if the length of the search string is greater than 2
$sfound = 0;
$found = 0;
$notfound = 1;

$stlen = length($searchstring);
if($stlen > 1) {
@words = split(/ +/,$searchstring);
foreach $aword (@words) {

if ($searchline =~ /\b$aword/i) {
$sfound = 1;
} else {
$notfound = 0;
}
}
}
if($sfound == 1 && $notfound == 1) {
$found = 1;
}

# if search string to too small.. set found to 1
if($stlen <= 1) {
$found = 1;
}

# OPTIONAL -- if page doesn't have a particular field then return not found
$tlen = length($linktitle);
if ($tlen < 1) {
$found = 0;
}

# this takes care of '' characters from line breaks
$linktitle =~ s/''//g;
$linkdescription =~ s/''//g;
$linkphone =~ s/''//g;
}

sub parse_form {

read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
if(length($buffer) < 5) {
$buffer = $ENV(QUERY_STRING};
}

@pairs = split(/&/,$buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/,$pair);

$value =~ tr/+//;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;

$FORM($name) = $value;
}
}

sub open_file {
local($filenar, $filemode, $filename) = @_;

open ($filevar, $filemode . $filename) ||
die ("Can't open $filename");
}

sub read_file {
local ($filevar) = @_;
<$filevar>;
}

######
END OF FILE
######



Not bad from memory, I think. There may be some typo's but I'll leave those to you to figure out. <G>


This second bit of code may take a bit of tweaking... I may leave out a part or two, but if I catch them I'll add them later.

The following code goes into DB.CGI, in SUB QUERY.

--------
METHOD 2
--------

1) After the following lines:

# Now let's build up all the regexpressions we will use. This saves the program
# from having to recompile the same regular expression every time.


add the following lines:

if($in{'bool}) {
($in{'bool'} eq 'and') ? ($bool = '&&') : ($bool = '||'); # No spaces between the || pipes

foreach $field (@search_fields) {
$finalreg = '';

foreach my $word (split /\s/, $in{$db_cols[$field]}) {
next if ($word =~ /^\s*$/);
$tmpreg = $word;
(!$in{'re'}) and ($tmpreg = "\Q$tmpreg\E");
($in{'ww'}) and ($tmpreg = "\\b$tmpreg\\b");
(!$in{'cs'}) and ($tmpreg = "(?i)$tmpreg");
$finalreg .= " m/$tmpreg/o $bool";
}
if ($in{$db_cols[$field]} eq "*") {
$finalreg = "m/.*/";
}
else {
chop $finalreg; chop $finalreg;
}
$regexp_func[$field] = eval "sub { $finalreg }";
}
}

else {

foreach $field (@search_fields) {
my $tmpreg = "$in{$db_cols[$field]}";
(!$in{'re'}) and ($tmpreg = "\Q$tmpreg\E");
($in{'ww'}) and ($tmpreg = "^$tmpreg\$");
(!$in{'cs'}) and ($tmpreg = "(?i)$tmpreg");
($in{$db_cols[$field]} eq "*") and ($tmpreg = ".*"); # A "*" matches anything.

$regexp_func[$field] = eval "sub { m/$tmpreg/o }";
$regexp_bold[$field] = $tmpreg;
}

-------

Finally, in HTML.PL, pass "&bool=and" when searching. This will instruct the system to search for all words. Exactly. So if you enter "and" or "or" it will search for those words as well. You could strip them out if you want, or find some way to use them, all up to you and your inginuity. :)

I hope this has been some help. I realize it's not going to be perfect, there are probably typos, and I bet there's a bit of code here or there that might be missing. To tell the truth, I got the boolean functional, but it was far from working. I strongly stress the first solution works a great deal better than the second.

I'll try to find the boolean.html file that was posted on my website. If I can locate it, I'll post where it can be found.

--Lee


Subject Author Views Date
Thread DBMan Boolean MOD leisurelee 2493 Nov 3, 2000, 8:45 PM
Post Re: DBMan Boolean MOD
tgardner 2317 Nov 5, 2000, 7:07 AM
Post Re: [leisurelee] DBMan Boolean MOD
omegadm 1907 Nov 22, 2002, 9:59 AM