Lines 343-349
sub getRecords {
Link Here
|
343 |
my $facets_counter = {}; |
343 |
my $facets_counter = {}; |
344 |
my $facets_info = {}; |
344 |
my $facets_info = {}; |
345 |
my $facets = getFacets(); |
345 |
my $facets = getFacets(); |
346 |
my $facets_maxrecs = C4::Context->preference('maxRecordsForFacets')||20; |
|
|
347 |
|
346 |
|
348 |
my @facets_loop; # stores the ref to array of hashes for template facets loop |
347 |
my @facets_loop; # stores the ref to array of hashes for template facets loop |
349 |
|
348 |
|
Lines 502-533
sub getRecords {
Link Here
|
502 |
# Fill the facets while we're looping, but only for the |
501 |
# Fill the facets while we're looping, but only for the |
503 |
# biblioserver and not for a scan |
502 |
# biblioserver and not for a scan |
504 |
if ( !$scan && $servers[ $i - 1 ] =~ /biblioserver/ ) { |
503 |
if ( !$scan && $servers[ $i - 1 ] =~ /biblioserver/ ) { |
505 |
|
504 |
$facets_counter = GetFacets( $results[ $i - 1 ] ); |
506 |
my $jmax = $size > $facets_maxrecs |
505 |
$facets_info = _get_facets_info( $facets ); |
507 |
? $facets_maxrecs |
|
|
508 |
: $size; |
509 |
|
510 |
for ( my $j = 0 ; $j < $jmax ; $j++ ) { |
511 |
|
512 |
my $marc_record = new_record_from_zebra ( |
513 |
'biblioserver', |
514 |
$results[ $i - 1 ]->record($j)->raw() |
515 |
); |
516 |
|
517 |
if ( ! defined $marc_record ) { |
518 |
warn "ERROR DECODING RECORD - $@: " . |
519 |
$results[ $i - 1 ]->record($j)->raw(); |
520 |
next; |
521 |
} |
522 |
|
523 |
_get_facets_data_from_record( $marc_record, $facets, $facets_counter ); |
524 |
$facets_info = _get_facets_info( $facets ); |
525 |
} |
526 |
} |
506 |
} |
527 |
|
507 |
|
528 |
# warn "connection ", $i-1, ": $size hits"; |
|
|
529 |
# warn $results[$i-1]->record(0)->render() if $size > 0; |
530 |
|
531 |
# BUILD FACETS |
508 |
# BUILD FACETS |
532 |
if ( $servers[ $i - 1 ] =~ /biblioserver/ ) { |
509 |
if ( $servers[ $i - 1 ] =~ /biblioserver/ ) { |
533 |
for my $link_value ( |
510 |
for my $link_value ( |
Lines 652-657
sub getRecords {
Link Here
|
652 |
return ( undef, $results_hashref, \@facets_loop ); |
629 |
return ( undef, $results_hashref, \@facets_loop ); |
653 |
} |
630 |
} |
654 |
|
631 |
|
|
|
632 |
sub GetFacets { |
633 |
|
634 |
my $rs = shift; |
635 |
my $facets; |
636 |
|
637 |
my $index_mode = C4::Context->config('zebra_auth_index_mode') // 'dom'; |
638 |
|
639 |
if ( $index_mode eq 'dom' ) { |
640 |
$facets = _get_facets_from_zebra( $rs ); |
641 |
} else { |
642 |
$facets = _get_facets_from_records( $rs ); |
643 |
} |
644 |
|
645 |
return $facets; |
646 |
} |
647 |
|
648 |
sub _get_facets_from_records { |
649 |
|
650 |
my $rs = shift; |
651 |
|
652 |
my $facets_maxrecs = C4::Context->preference('maxRecordsForFacets') // 20; |
653 |
my $facets_config = getFacets(); |
654 |
my $facets = {}; |
655 |
my $size = $rs->size(); |
656 |
my $jmax = $size > $facets_maxrecs |
657 |
? $facets_maxrecs |
658 |
: $size; |
659 |
|
660 |
for ( my $j = 0 ; $j < $jmax ; $j++ ) { |
661 |
|
662 |
my $marc_record = new_record_from_zebra ( |
663 |
'biblioserver', |
664 |
$rs->record( $j )->raw() |
665 |
); |
666 |
|
667 |
if ( ! defined $marc_record ) { |
668 |
warn "ERROR DECODING RECORD - $@: " . |
669 |
$rs->record( $j )->raw(); |
670 |
next; |
671 |
} |
672 |
|
673 |
_get_facets_data_from_record( $marc_record, $facets_config, $facets ); |
674 |
} |
675 |
|
676 |
return $facets; |
677 |
} |
678 |
|
655 |
=head2 _get_facets_data_from_record |
679 |
=head2 _get_facets_data_from_record |
656 |
|
680 |
|
657 |
C4::Search::_get_facets_data_from_record( $marc_record, $facets, $facets_counter ); |
681 |
C4::Search::_get_facets_data_from_record( $marc_record, $facets, $facets_counter ); |
Lines 696-701
sub _get_facets_data_from_record {
Link Here
|
696 |
} |
720 |
} |
697 |
} |
721 |
} |
698 |
|
722 |
|
|
|
723 |
=head2 _get_facets_from_zebra |
724 |
|
725 |
my $facets = _get_facets_from_zebra( $result_set ) |
726 |
|
727 |
Retrieves facets for a specified result set. It loops through the facets defined |
728 |
in C4::Koha::getFacets and returns a hash with the following structure: |
729 |
|
730 |
{ facet_idx => { |
731 |
facet_value => count |
732 |
}, |
733 |
... |
734 |
} |
735 |
|
736 |
=cut |
737 |
|
738 |
sub _get_facets_from_zebra { |
739 |
|
740 |
my $rs = shift; |
741 |
|
742 |
# save current elementSetName |
743 |
my $elementSetName = $rs->option( 'elementSetName' ); |
744 |
|
745 |
my $facets_loop = getFacets(); |
746 |
my $facets_data = {}; |
747 |
# loop through defined facets and fill the facets hashref |
748 |
foreach my $facet ( @$facets_loop ) { |
749 |
|
750 |
my $idx = $facet->{ idx }; |
751 |
my $sep = $facet->{ sep }; |
752 |
my $facet_values = _get_facet_from_result_set( $idx, $rs, $sep ); |
753 |
if ( $facet_values ) { |
754 |
# we've actually got a result |
755 |
$facets_data->{ $idx } = $facet_values; |
756 |
} |
757 |
} |
758 |
# set elementSetName to its previous value to avoid side effects |
759 |
$rs->option( elementSetName => $elementSetName ); |
760 |
|
761 |
return $facets_data; |
762 |
} |
763 |
|
764 |
=head2 _get_facet_from_result_set |
765 |
|
766 |
my $facet_values = |
767 |
C4::Search::_get_facet_from_result_set( $facet_idx, $result_set, $sep ) |
768 |
|
769 |
Internal function that extracts facet information for a specific index ($facet_idx) and |
770 |
returns a hash containing facet values and count: |
771 |
|
772 |
{ |
773 |
$facet_value => $count , |
774 |
... |
775 |
} |
776 |
|
777 |
Warning: this function has the side effect of changing the elementSetName for the result |
778 |
set. It is a helper function for the main loop, which takes care of backing it up for |
779 |
restoring. |
780 |
|
781 |
=cut |
782 |
|
783 |
sub _get_facet_from_result_set { |
784 |
|
785 |
my $facet_idx = shift; |
786 |
my $rs = shift; |
787 |
my $sep = shift; |
788 |
|
789 |
my $internal_sep = '<*>'; |
790 |
|
791 |
return if ( ! defined $facet_idx || ! defined $rs ); |
792 |
# zebra's facet element, untokenized index |
793 |
my $facet_element = 'zebra::facet::' . $facet_idx . ':0:100'; |
794 |
# configure zebra results for retrieving the desired facet |
795 |
$rs->option( elementSetName => $facet_element ); |
796 |
# get the facet record from result set |
797 |
my $facet = $rs->record( 0 )->raw; |
798 |
# if the facet has no restuls... |
799 |
return if !defined $facet; |
800 |
# TODO: benchmark DOM vs. SAX performance |
801 |
my $facet_dom = XML::LibXML->load_xml( |
802 |
string => ($facet) |
803 |
); |
804 |
my @terms = $facet_dom->getElementsByTagName('term'); |
805 |
return if ! @terms; |
806 |
|
807 |
my $facets = {}; |
808 |
foreach my $term ( @terms ) { |
809 |
my $facet_value = $term->textContent; |
810 |
$facet_value =~ s/\Q$internal_sep\E/$sep/ if defined $sep; |
811 |
$facets->{ $facet_value } = $term->getAttribute( 'occur' ); |
812 |
} |
813 |
|
814 |
return $facets; |
815 |
} |
816 |
|
699 |
=head2 _get_facets_info |
817 |
=head2 _get_facets_info |
700 |
|
818 |
|
701 |
my $facets_info = C4::Search::_get_facets_info( $facets ) |
819 |
my $facets_info = C4::Search::_get_facets_info( $facets ) |
702 |
- |
|
|