Skip to content

Commit

Permalink
Add keywords field and like_list search condition providing a proper …
Browse files Browse the repository at this point in the history
…means of adding and seerching on multi-word terms with high sensitivity and specifity.
  • Loading branch information
drn05r authored and EPrints Services committed May 24, 2020
1 parent fbe9c6b commit f3406a9
Show file tree
Hide file tree
Showing 5 changed files with 285 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/lang/en/phrases/system.xml
Expand Up @@ -1574,7 +1574,8 @@ For more information see <a href="http://eprints.org/d/?keyword=MetaFields">Meta
<epp:phrase id="lib/searchfield:help_text">Enter a term or terms to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_multilang">Enter a term or terms to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_id">Enter an exact term to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_idci">Enter an almost (case-insensitive) term to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_idci">Enter an almost exact (case-insensitive) term to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_keywords">Enter an almost exact (case-insensitive) term to search for a set of keywords</epp:phrase>
<epp:phrase id="lib/searchfield:help_fulltext">Enter a term or terms to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_url">Enter some text to search for.</epp:phrase>
<epp:phrase id="lib/searchfield:help_year">Enter a single year (e.g. 1999), or a range of years, e.g. `1990-2000', `1990-' or -2000'.</epp:phrase>
Expand All @@ -1592,6 +1593,7 @@ For more information see <a href="http://eprints.org/d/?keyword=MetaFields">Meta
<epp:phrase id="lib/searchfield:text_any">any of</epp:phrase>
<epp:phrase id="lib/searchfield:text_all">all of</epp:phrase>
<epp:phrase id="lib/searchfield:desc_is"><epc:pin name="name"/> is <epc:pin name="value"/></epp:phrase>
<epp:phrase id="lib/searchfield:desc_has"><epc:pin name="name"/> has <epc:pin name="value"/></epp:phrase>
<epp:phrase id="lib/searchfield:desc_true"><epc:pin name="name"/></epp:phrase>
<epp:phrase id="lib/searchfield:desc_false"><b>NOT</b> <epc:pin name="name"/></epp:phrase>
<epp:phrase id="lib/searchfield:desc_any_in"><epc:pin name="name"/> matches any of <epc:pin name="value"/></epp:phrase>
Expand Down
1 change: 1 addition & 0 deletions perl_lib/EPrints/MetaField.pm
Expand Up @@ -2356,6 +2356,7 @@ sub get_property_defaults
volatile => EP_PROPERTY_FALSE,
virtual => EP_PROPERTY_FALSE,
default_value => EP_PROPERTY_UNDEF,
separator => EP_PROPERTY_UNDEF,
match => "EQ",
merge => "ALL",

Expand Down
174 changes: 174 additions & 0 deletions perl_lib/EPrints/MetaField/Keywords.pm
@@ -0,0 +1,174 @@
######################################################################
#
# EPrints::MetaField::Keywords;
#
######################################################################
#
#
######################################################################

=pod
=head1 NAME
B<EPrints::MetaField::Keywords> - no description
=head1 DESCRIPTION
not done
=over 4
=cut

package EPrints::MetaField::Keywords;

use strict;
use warnings;

BEGIN
{
our( @ISA );

@ISA = qw( EPrints::MetaField::Id );
}

use EPrints::MetaField::Id;

sub get_sql_type
{
my( $self, $session ) = @_;

return $session->get_database->get_column_type(
$self->get_sql_name(),
EPrints::Database::SQL_CLOB,
!$self->get_property( "allow_null" ),
undef,
undef,
$self->get_sql_properties,
);
}

sub get_property_defaults
{
my( $self ) = @_;
my %defaults = $self->SUPER::get_property_defaults;
$defaults{match} = "EQ";
$defaults{input_rows} = $EPrints::MetaField::FROM_CONFIG;
$defaults{maxlength} = 65535;
$defaults{sql_index} = 0;
$defaults{separator} = ",";
return %defaults;
}

sub get_search_conditions
{
my( $self, $session, $dataset, $search_value, $match, $merge,
$search_mode ) = @_;

if( $match eq "SET" )
{
return EPrints::Search::Condition->new(
"is_not_null",
$dataset,
$self );
}

if( $match eq "EQ" )
{
if( !EPrints::Utils::is_set( $search_value ) )
{
return EPrints::Search::Condition->new(
'is_null',
$dataset,
$self );
}

return EPrints::Search::Condition->new(
'like_list',
$dataset,
$self,
$search_value );
}

return $self->get_search_conditions_not_ex(
$session,
$dataset,
$search_value,
$match,
$merge,
$search_mode );
}

sub render_search_description
{
my( $self, $session, $sfname, $value, $merge, $match ) = @_;

my( $phraseid );
if( $match eq "EQ" || $match eq "EX" )
{
$phraseid = "lib/searchfield:desc_has";
}
elsif( $merge eq "ANY" ) # match = "IN"
{
$phraseid = "lib/searchfield:desc_any_in";
}
else
{
$phraseid = "lib/searchfield:desc_all_in";
}

my $valuedesc = $self->render_search_value(
$session,
$value,
$merge,
$match );

return $session->html_phrase(
$phraseid,
name => $sfname,
value => $valuedesc );
}


sub split_search_value
{
my( $self, $session, $value ) = @_;

return split /$self->{separator}\s*/, $value;
}


######################################################################
1;

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2019 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
=for LICENSE BEGIN
This file is part of EPrints 3.4 L<http://www.eprints.org/>.
EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.
EPrints 3.4 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END
2 changes: 2 additions & 0 deletions perl_lib/EPrints/Search/Condition.pm
Expand Up @@ -70,6 +70,7 @@ use EPrints::Search::Condition::IndexStart;
use EPrints::Search::Condition::Grep;
use EPrints::Search::Condition::NameMatch;
use EPrints::Search::Condition::Like;
use EPrints::Search::Condition::LikeList;
use EPrints::Search::Condition::InSubject;
use EPrints::Search::Condition::IsNull;
use EPrints::Search::Condition::IsNotNull;
Expand Down Expand Up @@ -115,6 +116,7 @@ sub new
if( $op eq "grep" ) { return EPrints::Search::Condition::Grep->new( @params ); }
if( $op eq "regexp" ) { return EPrints::Search::Condition::Regexp->new( @params ); }
if( $op eq "like" ) { return EPrints::Search::Condition::Like->new( @params ); }
if( $op eq "like_list" ) { return EPrints::Search::Condition::LikeList->new( @params ); }
if ( $op =~ m/^(=|<=|>=|<|>)$/ )
{
return EPrints::Search::Condition::Comparison->new( $op, @params );
Expand Down
105 changes: 105 additions & 0 deletions perl_lib/EPrints/Search/Condition/LikeList.pm
@@ -0,0 +1,105 @@
######################################################################
#
# EPrints::Search::Condition::NameMatch
#
######################################################################
#
#
######################################################################

=pod
=head1 NAME
B<EPrints::Search::Condition::LikeList> - "like_list" search condition
=head1 DESCRIPTION
Matches items that are in a list (e.g. a set of comma separated keywords) whilst ignoring case
=cut

package EPrints::Search::Condition::LikeList;

use EPrints::Search::Condition::Comparison;

@ISA = qw( EPrints::Search::Condition::Comparison );

use strict;

sub new
{
my( $class, @params ) = @_;

my $self = {};
$self->{op} = "like_list";
$self->{dataset} = shift @params;
$self->{field} = shift @params;
$self->{params} = \@params;

return bless $self, $class;
}


sub logic
{
my( $self, %opts ) = @_;

my $prefix = $opts{prefix};
$prefix = "" if !defined $prefix;

my $db = $opts{session}->get_database;
my $table = $prefix . $self->table;
my $sql_name = $self->{field}->get_sql_name;
my $sep = $self->{field}->{separator};

my $identifier = $db->quote_identifier( $table, $sql_name );
my $value = EPrints::Database::prep_like_value( $self->{params}->[0] );

return sprintf( _make_REPLACE( $sep ) . $db->sql_LIKE." '%%%s%s%s%%' OR " . _make_REPLACE( $sep ) . $db->sql_LIKE." '%s%s%%' OR " . _make_REPLACE( $sep ) . $db->sql_LIKE." '%%%s%s' OR " . _make_REPLACE( $sep ) . $db->sql_LIKE." '%s'",
$identifier, $sep, $value, $sep,
$identifier, $value, $sep,
$identifier, $sep, $value,
$identifier, $value,
);
}

sub _make_REPLACE
{
my( $separator ) = @_;
return " REPLACE(%s, '".$separator." ', '$separator') ";
}


1;

=head1 COPYRIGHT
=for COPYRIGHT BEGIN
Copyright 2019 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.
http://www.eprints.org/eprints-3.4/
=for COPYRIGHT END
=for LICENSE BEGIN
This file is part of EPrints 3.4 L<http://www.eprints.org/>.
EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.
EPrints 3.4 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.
=for LICENSE END

0 comments on commit f3406a9

Please sign in to comment.