.
1. Login to your linksql admin, then paste this url into your browse
Please note if you have used a different name for the cached page table, you have to change the "
" in the URL to your table name.
2. In the Indexing Scheme dropdown list, choose INTERNAL, then click "Update table", by doing this, linksql will add two tables to your database: Cached_Page_Score_List and Cached_Page_Word_List.
3. Add this code to nph_index.cgi at (about) line 176 before this line "# All done." (
4. Do the initial indexing.
You can do it by clicking repair search in your browser or in shell by typing perl nph-index.cgi.
If you have already stored many cached pages, this process may take long and the Cached_Page_Score_List and Cached_Page_Word_List tables may get big.
After initial indexing, you don't need to do it again. Every time you cache a new page, it will get automatically indexed. You will see the records growing in Cached_Page_Score_List and Cached_Page_Word_List table after a page is cached, if not, the automatic indexing is not working!
. Modify Admin/Links/User/Search.pm (
Below is the modified the version of search.pm. Code in
Code:
# ==================================================================
# Links SQL - enhanced directory management system
#
# Website :
http://gossamer-threads.com/ # Support :
http://gossamer-threads.com/scripts/support/ # CVS Info : 087,069,082,087,085
# Revision : $Id: Search.pm,v 1.14 2002/05/13 16:59:50 alex Exp $
#
# Copyright (c) 2001
Gossamer Threads Inc. All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================package Links::User::Search;
# ==================================================================
use strict;
use Links qw/$DB $IN $USER $CFG/;
use Links::SiteHTML;
use Links::Build;sub handle {
#--------------------------------------------------------------------------------
# Determine whether we are displaying the search form, or doing a
# search.
#
my $db = $Links::DB->table('Links');
my $results = {};
my $args = $IN->get_hash;# Remove search fields we aren't allowed to search on.
if ($CFG->{search_blocked}) {
foreach my $col (@{$CFG->{search_blocked}}) {
$col =~ s/^\s*|\s*$//g;
if ($args->{$col}) {
delete $args->{$col};
$IN->delete ($col);
}
delete $args->{"$col-lt"};
$IN->delete ("$col-lt");
delete $args->{"$col-gt"};
$IN->delete ("$col-gt");
}
}
# Make sure we only search on validated links.
$IN->param('isValidated', ['Yes']);# If query is set we know we are searching.
defined $args->{'query'} and ($args->{query} =~ /\S/) and return search();
# Otherwise, if we pass in a field name, we can search on that too.
foreach (keys %{$db->cols}) {
if ((defined $args->{$_} and length $args->{$_}) or
(defined $args->{"$_-lt"} and length $args->{"$_-lt"}) or
(defined $args->{"$_-gt"} and length $args->{"$_-gt"}))
{
return search();
}
}
print $IN->header();
print Links::SiteHTML::display('search');
}sub search {
# ------------------------------------------------------------------
# Do the search and print out the results.
#
my $results = GT::Plugins->dispatch ($CFG->{admin_root_path} . '/Plugins', 'search_results', \&query, {});
if (defined $results->{error}) {
print $IN->header();
print Links::SiteHTML::display ('search', $results);
}
else {
print $IN->header();
print Links::SiteHTML::display ('search_results', $results);
}
if ($CFG->{debug_level} > 1) {
print "<blockquote><pre>", GT::SQL->query_stack_disp , "</pre></blockquote>";
}
}sub query {
# ------------------------------------------------------------------
# Query the database.
#
my $query = $IN->param('query');
my $term = $IN->escape($IN->param('query'));# First get our search options.
my $args = $IN->get_hash;
$args->{query} =~ s,^\s*|\s*$,,g;
$args->{bool} = (defined $args->{bool} and $args->{bool} =~ /^(and|or)$/i) ? uc $1 : $CFG->{search_bool};
$args->{nh} = (defined $args->{nh} and $args->{nh} =~ /^(\d+)$/) ? $1 : 1;
$args->{mh} = (defined $args->{mh} and $args->{mh} =~ /^(10|25|50|100)$/) ? $1 : $CFG->{search_maxhits};
$args->{substring} = defined $args->{substring} ? $args->{substring} : $CFG->{search_substring};
$args->{so} = (defined $args->{so} and $args->{so} =~ /^(asc|desc)$/i ? $1 : '');
$args->{sb} and ($args->{sb} =~ /^[\w\s,]+$/ or ($args->{sb} = ''));
#Cached_Page add two lines
my $whole_word = 1 if $args->{substring}=0; #For making summary
my @search_words = split('\s+',$args->{query});
# Get our Links/Category db object.
my $links = $Links::DB->table('Links');
my $categories = $Links::DB->table('Category');# We don't do a category search if we only have a filters.
my $filter = 0;
if (! defined $query or ($query eq '')) {
$filter = 1;
}
$args->{filter} = $filter;# Then do the search.
$args->{callback} = \&_cat_search_subcat if ($args->{catid});
my $orig_sb = $args->{sb};
my $orig_so = $args->{so};
$args->{sb} = $CFG->{build_sort_order_search_cat};
$args->{so} = '';
$filter and $args->{sb} =~ s/score//;
my $cat_sth = $categories->query_sth ($args) unless ($filter);
my $cat_count = $filter ? 0 : $categories->hits(); $args->{callback} = \&_search_subcat if ($args->{catid});
$args->{sb} = $orig_sb ? $orig_sb : $CFG->{build_sort_order_search} || '';
$args->{so} = (defined $orig_so and $orig_so =~ /^(asc|desc)$/i) ? $1 : 'ASC';
$filter and $args->{sb} =~ s/score//;
my $link_sth = $links->query_sth ($args);
my $link_count = $links->hits;
#Cached_Page add
# query cached table
$args->{field_name}='Page';
$args->{bool} = (defined $args->{bool} and $args->{bool} =~ /^(and|or)$/i) ? uc $1 : $CFG->{search_bool};
$args->{substring} = defined $args->{substring} ? $args->{substring} : $CFG->{search_substring};
my $cache_db = $DB->table ('Cached_Page'); #Change the table name if you have used a different one.
my $cache_sth = $cache_db->query_sth($args);
my $cache_count = $cache_db->hits;
# Cached_Page end
# Return if no results.
unless ($link_count or $cat_count
or $cache_count) {
#add $cache_count to this line return { error => Links::language('SEARCH_NOLINKS'), term => $term };
}
#Cached_Page add
# First combine all links matches
my $results;
my (@link_ids, $seen); # id hit from links table
if ($link_count) {
$results = $link_sth->fetchall_hashref;
@link_ids = map { $_->{ID} } @$results;
for my $id (@link_ids) {
$seen->{$id} ++;
}
}
# Now get cache page
if ($cache_count){
my (@cache_ids, $result_fm_cache);
while (my $cache_hit = $cache_sth->fetchrow_hashref) {
# make summary from page content for display
my $page = _make_summary(\@search_words, $cache_hit->{Page}, $whole_word);
push @cache_ids, $cache_hit->{LinkID} unless exists $seen->{$cache_hit->{LinkID}}; # get ids only from cached table
$result_fm_cache->{$cache_hit->{LinkID}} = $page;
}
# Now need to query links table again to get basic link variable for those extra hits from cached table
# I know this will slow down search speed, any better algo here? if (@cache_ids >=1){
my $cond = GT::SQL::Condition->new('ID', 'IN', \@cache_ids);
my $extra_links = $links->select ( {isValidated => 'Yes'}, $cond);
my $extra_count = $links->hits;
$link_count = $link_count + $extra_count; # add to sum
my $newlinks;
## There must be results, so no need to test $extra_count
while (my $newlink = $extra_links->fetchrow_hashref) {
# Replace description with cached page summary for display so users will see the matches
$newlink->{Description}= $result_fm_cache->{$newlink->{ID}};
push @{$results}, $newlink; # add extra links to the pool
}
}
}
#Cached_Page end
# Now format the category results.
my $count = 0;
my ($category_results, @category_results_loop);
if (!$filter and $cat_count) {
while (my $cat = $cat_sth->fetchrow_hashref) {
last if ($count++ > $args->{mh});
my $title = Links::Build::build ('title_linked', { name => $cat->{Full_Name}, complete => 1, home => 0 });
$category_results .= "<li>$title\n";
$cat->{title_linked} = $title;
push @category_results_loop, $cat;
}
}# And format the link results.
my ($link_results, %link_output);
if ($link_count) {
#Cached_Page remove one line here
#my $results = $link_sth->fetchall_hashref;
$links->add_reviews ($results);
if ($CFG->{build_search_gb}) {
#Cached_Page remove one line
#my @ids = map { $_->{ID} } @$results;
my $catlink = $DB->table('CatLinks','Category');
#Cached_Page remove one line
#
my %names = $catlink->select ('LinkID', 'Full_Name', { LinkID => \@ids })->fetchall_list;
#Cached_Page add one line my %names = $catlink->select ('LinkID', 'Full_Name', { LinkID => \@link_ids })->fetchall_list; foreach my $link (@$results) {
push @{$link_output{$names{$link->{ID}}}}, $link;
}
}
else {
push @{$link_output{none}}, @$results;
}
}# Join the link results by category if we are grouping.
my @link_results_loop;
if ($CFG->{build_search_gb}) {
foreach my $cat (sort keys %link_output) {
my $title = Links::Build::build ('title_linked', { name => $cat, complete => 1, home => 0 });
$link_results .= "<p><b>$title</b>" . join ("", map { Links::SiteHTML::display('link', $_) } @{$link_output{$cat}});
$link_output{$cat}->[0]->{title_linked} = $title;
push @link_results_loop, @{$link_output{$cat}};
}
}
else {
$link_results = join ("", map { Links::SiteHTML::display('link', $_) } @{$link_output{none}});
push @link_results_loop, @{$link_output{none}};
}# Generate a toolbar if requested.
my $toolbar;
if (($link_count > $args->{mh}) or ($cat_count > $args->{mh})) {
my $url = $IN->url ( { query_string => 1 } );
$url =~ s/([;&?]?)nh=(\d+)/($1 and $1 eq '?') ? '?' : ''/eg;
$toolbar = Links::Build::build ('search_toolbar', {
url => $url,
numlinks => $link_count > $cat_count ? $link_count : $cat_count,
nh => $args->{nh},
mh => $args->{mh}
});
}
else {
$toolbar = '';
}# If we are bolding the results, let's bold them.
if ($CFG->{search_bold}) {
my $tempquery = $args->{query};
$tempquery =~ s/[+\-"']//g;
my @terms = split /\s/, $tempquery;
foreach my $term (@terms) {
next unless ($term);
$term =~ s/^\s*|\s*$//;
if ($term =~ s/(.+)\*(.*)/$1/) {
push @terms, $2 if ($2);
$term = $1;
}
$link_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "<B>$2</B>",gie if ($link_results);
$category_results =~ s,(<[^>]+>)|(\Q$term\E),defined($1) ? $1 : "<B>$2</B>",gie if ($category_results);
}
} # Print the output.
my $results = {
link_results => $link_results,
link_results_loop => \@link_results_loop,
category_results => $category_results,
category_results_loop => \@category_results_loop,
link_hits => $link_count,
cat_hits => $cat_count,
next => $toolbar,
term => $term
};
return $results;
}sub _search_subcat {
# -------------------------------------------------------------------
# First argument is the query/table object, second argument is the current
# result set (note: can be quite large). Must return a new result set.
#
my ($query, $results) = @_;
return $results unless (keys %$results); # No matches. my $cat_db = $DB->table ('Category');
my $catlink_db = $DB->table ('CatLinks', 'Category');# We need the full name of the category.
my @cat_ids = $IN->param('catid') or return $results;
my (@children, %seen);
foreach my $id (@cat_ids) {
next if ($id !~ /^\d+$/);
my $child = $cat_db->children($id) or next;
push @children, @$child, $id;
}
@children or return $results;
@children = grep { ! $seen{$_}++ } @children;# Now do the joined query.
my $link_ids = '(' . join(',', keys %{$results}) . ')';
my $cat_ids = '(' . join(',', @children) . ')';
my $cond = GT::SQL::Condition->new (
'CategoryID', 'IN', \$cat_ids,
'LinkID', 'IN', \$link_ids
);
my $sth = $catlink_db->select ($cond, ['LinkID']);
my $filtered = {};
while (my ($id) = $sth->fetchrow_array) {
$filtered->{$id} = $results->{$id};
}
return $filtered;
}sub _search_subcat_and {
# -------------------------------------------------------------------
# Search subcategories using AND.
#
my ($query, $results) = @_;
return $results unless (keys %$results); # No matches my $cat_db = $DB->table ('Category');
my $catlink_db = $DB->table ('CatLinks', 'Category');# We need the full name of the category.
my @cat_ids = $IN->param('catid') or return $results;
my %final = %$results;
foreach my $id (@cat_ids) {
next unless ($id =~ /^\d+$/);
my @children;
my $childs = $cat_db->children($id);
push @children, @$childs, $id;
my $cond = GT::SQL::Condition->new(
CategoryID => 'IN' => \@children,
LinkID => 'IN' => [ keys %final]
);
%final = ();
my $sth = $catlink_db->select($cond, ['LinkID']);
while (my $link_id = $sth->fetchrow_array) {
$final{$link_id} = $results->{$link_id};
}
}
return \%final;
}sub _cat_search_subcat {
# -------------------------------------------------------------------
# First argument is the query/table object, second argument is the current
# result set (note: can be quite large). Must return a new result set.
#
my ($query, $results) = @_;
return $results unless (keys %$results); # No matches. my $cat_db = $DB->table('Category');
my @cat_ids = $IN->param('catid') or return $results;
my (@children, %seen);
foreach my $id (@cat_ids) {
next if ($id !~ /^\d+$/);
my $child = $cat_db->children($id) or next;
push @children, @$child, $id;
}
@children or return $results;
@children = grep { ! $seen{$_}++ } @children; my %subcats = map { $_ => 1 } @children;
my $filtered = {};
while (my ($k, $s) = each %$results) {
$filtered->{$k} = $s if (exists $subcats{$k});
}
return $filtered;
}
sub _make_summary {
#--------------------------------------------------------------------
#Make a excerpt from matched sentences of cached pages
# Modified from KSearch v1.4, Copyright (C) 2000 David Kim (kscripts.com) my ($terms, $page, $whole_word) = @_;
my ($desc, $line, $pre, $post, $match, $prem, $postm, $bdy);
my $SHOW_MATCHES_LENGTH=150; #excerpt sentence length for result
my $show_matches = 1; # how many matches to show
my @lines;
$whole_word =1;
my $spaces = " " x $SHOW_MATCHES_LENGTH;
$bdy = $page;
$bdy =~ s/<.*?>|&\w+;|&\w+;|&#\d+;/ /gi;
foreach my $term (@$terms) {
my $count;
if ($whole_word==1) {
while ($count < $show_matches && $bdy =~ /\b$term\b/gis) {
$count++; $pre = "$`"; $post = "$'"; $match = $&;
my $LENGTH = int (($SHOW_MATCHES_LENGTH - length $match)/2);
$pre =~ m/\b(.{0,$LENGTH})$/; $prem = $1;
$post =~ m/^(.{0,$LENGTH})\b/; $postm = $1; $post = "$'", $bdy = "$pre $post";
$line = join("", '...', $prem, $match, $postm, '...');
push @lines, $line;
}
} else {
while ($count < $show_matches && $bdy =~ /$term/gis) {
$count++; $pre = "$`"; $post = "$'"; $match = $&;
my $LENGTH = int (($SHOW_MATCHES_LENGTH - length $match)/2);
$pre =~ m/\b(.{0,$LENGTH})$/; $prem = $1;
$post =~ m/^(.{0,$LENGTH})\b/; $postm = $1; $post = "$'", $bdy = "$pre $post";
$line = join("", '...', $prem, $match, $postm, ' ');
push @lines, $line;
}
}
}
return join(" ", @lines);
}
1;
After modifying Search.pm, give it a try by searching something in user's interface.
I have attached the modified Search.pm in case you cannot keep the format by copying the code from here.
I hope it works for you guys.