179 lines
5.3 KiB
Perl
179 lines
5.3 KiB
Perl
# ==================================================================
|
|
# Gossamer Threads Module Library - http://gossamer-threads.com/
|
|
#
|
|
# GT::Search::MYSQL::VER3
|
|
# Author : Aki Mimoto
|
|
# CVS Info : 087,071,086,086,085
|
|
# $Id: VER3.pm,v 1.3 2004/08/28 03:53:49 jagerman Exp $
|
|
#
|
|
# Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
|
# ==================================================================
|
|
#
|
|
# Description:
|
|
# Class used to search indexed tables.
|
|
#
|
|
|
|
package GT::SQL::Search::MYSQL::VER3;
|
|
# ------------------------------------------------------------------------------
|
|
use strict;
|
|
use vars qw/ @ISA $ATTRIBS $VERSION $DEBUG $AUTOLOAD /;
|
|
use GT::SQL::Search::Base::Search;
|
|
@ISA = qw( GT::SQL::Search::Base::Search );
|
|
|
|
# ------------------------------------------------------------------------------
|
|
# Preamble information related to the object
|
|
|
|
$DEBUG = 0;
|
|
$VERSION = sprintf "%d.%03d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/;
|
|
$ATTRIBS = {
|
|
min_word_size => 4
|
|
};
|
|
|
|
sub _phrase_query {
|
|
# ------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $phrases = shift or return $_[0];
|
|
my $results = shift || {};
|
|
|
|
foreach my $phrase ( values %{$phrases} ) {
|
|
$self->debug_dumper( "Unioning: ", $phrase ) if ($self->{_debug});
|
|
|
|
my $tmp = {};
|
|
foreach my $keyword ( @{ $phrase->{phrase}|| [] } ) {
|
|
$tmp = $self->_get_words ( [ $keyword ], $tmp, 'intersect' );
|
|
keys %$tmp or return {};
|
|
}
|
|
foreach my $key ( keys %$tmp ) { $results->{$key} += $tmp->{$key} }
|
|
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
sub _get_phrase {
|
|
# ------------------------------------------------------------------------------
|
|
# one day change this so it does words properly
|
|
return _get_words(@_);
|
|
}
|
|
|
|
sub _union_query {
|
|
# ------------------------------------------------------------------------------
|
|
return _get_words(@_);
|
|
}
|
|
|
|
sub _intersect_query {
|
|
# ------------------------------------------------------------------------------
|
|
my ( $self, $keywords, $results ) = @_;
|
|
$keywords or return $results;
|
|
|
|
foreach my $keyword ( keys %{ $keywords || {} } ) {
|
|
$results = $self->_get_words ( [ $keyword ], $results, 'intersect' );
|
|
keys %$results or return {};
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
sub _phrase_intersect_query {
|
|
# ------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $phrases = shift or return $_[0];
|
|
my $results = shift || {};
|
|
|
|
my $tmp = $self->_phrase_query ( $phrases, $results );
|
|
keys %$results or return $tmp;
|
|
foreach my $key ( keys %$results ) {
|
|
if ( $tmp->{$key} ) {
|
|
$results->{$key} += $tmp->{$key};
|
|
}
|
|
else {
|
|
delete $results->{$key}
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
sub _disjoin_query {
|
|
# ------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $words = shift or return shift;
|
|
my $results = shift || {};
|
|
|
|
$results = $self->_get_words([ keys %{$words || {}} ], $results, 'disjoin' );
|
|
|
|
return $results;
|
|
}
|
|
|
|
sub _phrase_disjoin_query {
|
|
# ------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $phrases = shift or return shift;
|
|
my $results = shift || {};
|
|
|
|
my $tmp = $self->_phrase_query ( $phrases, $results );
|
|
keys %$results or return $tmp;
|
|
foreach my $key ( keys %$results ) {
|
|
$tmp->{$key} and delete $results->{$key};
|
|
}
|
|
}
|
|
|
|
sub _get_words {
|
|
# ------------------------------------------------------------------------------
|
|
my $self = shift;
|
|
my $words = shift or return $_[0] || {};
|
|
my $results = shift || {};
|
|
my $mode = lc shift;
|
|
|
|
my $tbl = $self->{table} or $self->error( 'BADARGS', 'FATAL', 'Must have table object defined' );
|
|
my $tname = $tbl->name();
|
|
my $wordlist = join " ", ( ref $words ? ( ref $words eq 'HASH' ? keys %$words : @$words ) : $words ) ;
|
|
my ($pk) = $tbl->pk;
|
|
|
|
my %weights = $tbl->_weight_cols();
|
|
my $cols = join(",", keys %weights);
|
|
my $qwrds = quotemeta( $wordlist );
|
|
my $where = ( $results and keys %$results )
|
|
? ("AND $pk IN(" . join(',', keys %$results) . ")")
|
|
: '';
|
|
my $query = qq!
|
|
SELECT $pk, MATCH($cols) AGAINST ('$qwrds') AS SCORE
|
|
FROM $tname
|
|
WHERE MATCH($cols) AGAINST ('$qwrds')
|
|
$where
|
|
!;
|
|
my $sth = $tbl->do_query( $query ) or return;
|
|
|
|
if ( $mode eq 'disjoin' ) {
|
|
while ( my $result = $sth->fetchrow ) {
|
|
delete $results->{$result};
|
|
}
|
|
}
|
|
elsif ( $mode eq 'intersect' ) {
|
|
my $tmp = {};
|
|
while ( my $aref = $sth->fetchrow_arrayref ) {
|
|
$tmp->{$aref->[0]} = $aref->[1];
|
|
}
|
|
if ( $results and keys %$results ) {
|
|
while (my ($id, $score) = each %$results) {
|
|
if (not defined $tmp->{$id}) {
|
|
delete $results->{$id};
|
|
next;
|
|
}
|
|
$results->{$id} += $score;
|
|
}
|
|
}
|
|
else {
|
|
$results = $tmp;
|
|
}
|
|
}
|
|
else {
|
|
while ( my $aref = $sth->fetchrow_arrayref ) {
|
|
$results->{$aref->[0]} += $aref->[1];
|
|
}
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
1;
|