Búsqueda avanzada en OpacMarc

En abril de 2008, la mejor versión del formulario avanzado se encuentra en el Catálogo del Museo Mitre (en desarrollo).

Análisis

En form-advanced.htm

HIDDEN
advanced = 1
"Encontrar registros que tengan..."
filter1 : [libre]
filterType1 : TITLE
| NAME
| SUBJ
| PUB_NAME
| PUB_PLACE
| NOTE
| SN
| ACCESSION
| ANY
oper : AND
| OR
filter2 : [libre]
filterType2 : TITLE
| NAME
| SUBJ
| PUB_NAME
| PUB_PLACE
| NOTE
| SN
| ACCESSION
| ANY
"Pero excluir registros que tengan..."
exclude : [libre]
excludeType : TITLE
| NAME
| SUBJ
| PUB_NAME
| PUB_PLACE
| NOTE
| SN
| ACCESSION
| ANY
"Otras características de los registros"
date1 : [libre]
date2 : [libre]
lang : [opciones de menú]
trans : [opciones de menú]
m (material, medio) : [opciones de menú]
litForm : [opciones de menú]
biogr : [opciones de menú]
fest : [opciones de menú]
"Opciones para presentar los resultados"
sortBy
count (records per page)

En opac.xis

Estos son los parámetros relevantes para las búsquedas:

<cgitable><pft> '2001 query'/ /* puede tener más de una occ, si viene desde un índice */ '2002 searchType'/ '2005 oper'/ '2012 lang'/ '2013 pub'/ '2014 place'/ '2015 format'/ '2016 sortBy'/ '2019 litForm'/ '2020 biogr'/ '2021 trans'/ '2022 fecha1'/ '2023 fecha2'/ '2024 fest'/ /* Festchrift */ '2028 rpp'/ /* bib. records per page */ '2050 advanced'/ /* uso de form avanzado */ /* Búsqueda combinando campos */ '2051 query1'/ '2052 query2'/ '2053 searchType1'/ '2054 searchType2'/ ... </pft></cgitable>

En keyword-match-in-bib-record.xis

Los pasos son los siguientes:

definir el operador booleano a emplear

proteger el operador de truncamiento * (para que no se pierda en el próximo paso)

limpiar las expresiones recibidas, usando cleanQuery (resultado en v3001)

eliminar ' AND '

reemplazar el operador de truncamiento por $

si es búsqueda simple

insertar operador AND entre términos

añadir prefijo (e.g. -SN=) o sufijo (e.g. /(9204)) a cada término, según el tipo de búsqueda (v2002)

si es búsqueda avanzada

insertar operador AND entre términos (en filter1, filter2, exclude)

añadir sufijos/prefijos según el tipo de búsqueda (filterType1, filterType2, excludeType)

conectar filter1 y filter2 con el operador elegido

añadir un filtro (AND PREFIJO=valor) por cada característica adicional

si la búsqueda incluye fechas, realizar ciertas operaciones sobre ellas

realizar una limpieza final

Este es el código utilizado:

<!-- Operador booleano por defecto --> <field action="replace" tag="2005"><pft>if a(v2005) then 'AND' fi</pft></field> <!-- Limpiamos la expresión recibida; el resultado queda en v3001 --> <call name="cleanQuery"><pft> if 'TITLE~ANY' : v2002 then replace(v2001,'*','XXXTRUNCATEXXX'), /* XXXTRUNCATEXXX es un string (alfabético) improbable, para evitar que el símbolo de truncación se pierda durante la limpieza */ fi </pft></call> <!-- ATENCION: clean query1 & query2 ??? --> <!-- Armamos la search expression --> <field action="replace" tag="3001"><pft> replace(replace(s(mpu,v3001), /* v3001 es la expresión luego de la limpieza; usamos mpu porque cleanQuery no cambia el case */ 'XXXTRUNCATEXXX','$'), ' AND ',' ') </pft></field> <field action="replace" tag="3001"><pft> if p(v2001) then /* Búsqueda simple */ select v2002 case 'TITLE' : replace(v3001,' ',s('/(9204)',x1,v2005,x1)), '/(9204)', ' OR ', replace(v3001,' ',s('/(9404)',x1,v2005,x1)), '/(9404)', /* incluimos las series. TO-DO: revisar cada lugar donde diga "9204" */ case 'SN' : /* originalmente sólo ISBN e ISSN; lo extendemos a otros identificadores numéricos */ '-SN=',v2001, ' OR -SN=',replace(v2001,'-',''), /* aceptamos un ISBN que traiga guiones */ ' OR -INV=',v2001, /* nros. de inventario */ ' OR -NC=',v2001, /* nros. de control */ case 'ANY' : replace(v3001,' ',s(x1,v2005,x1)), endsel, else /* Búsqueda avanzada */ /* TO-DO: truncamiento */ '(', if p(v2051) then replace(v2051,' ',s(v2006,'/',v2053,x1,v2005,x1)), v2006, select v2053 case 'TITLE': '/(9204)', case 'NAME' : '/(9104)', case 'SUBJ' : '/(9604)', endsel, fi, if p(v2051) and p(v2052) then x1,v2005,x1, fi, if p(v2052) then replace(v2052,' ',s(v2006,'/',v2054,x1,v2005,x1)), v2006, select v2054 case 'TITLE': '/(9204)', case 'NAME' : '/(9104)', case 'SUBJ' : '/(9604)', endsel, fi, ')', fi, if p(v2013) then ' AND ',replace(v2013,' ','$/(9261) AND '),'$/(9261)', fi, if p(v2014) then ' AND ',replace(v2014,' ','$/(9260) AND '),'$/(9260)', fi, " AND -LANG="v2012^*, " AND -BIB="v2018, " AND -FICTION="v2019, " AND -BIOGR=YES"d2020, " AND -TRANS="v2021, " AND -FEST"d2024, </pft></field> <!-- Si no se usaron fechas, la expresión de búsqueda está (casi) lista --> <flow action="jump"><pft> if s(v2022,v2023) = '' then 'SEARCH_EXPR_READY' fi </pft></flow> <!-- Pero si hay fechas, tenemos que manipularlas para incorporarlas a la expresión --> <!-- No queremos fechas en blanco --> <field action="replace" tag="2022"><pft>"1600"n2022</pft></field> <field action="replace" tag="2023"><pft>"2000"n2023</pft></field> <!-- v3020: distancia entre fechas --> <field action="replace" tag="3020"><pft>f(val(v2023) - val(v2022),1,0)</pft></field> <!-- ATENCION: este error debería producir un mensaje bien específico, o quizás debería el sistema invertir el orden de las fechas?? --> <flow action="jump"><pft>if val(v3020) < 0 then 'ZERO_HITS' fi</pft></flow> <field action="replace" tag="3022"><pft>v2022</pft></field> <flow action="jump"><pft>if val(v3020) = 0 then 'COMPACTAR_FECHAS' fi</pft></flow> <!-- v3022: la secuencia de años --> <do> <parm name="count"><pft>v3020</pft></parm> <define>1001 Isis_Current</define> <loop> <field action="import" tag="list">3022</field> <field action="add" tag="3022"><pft>f(val(v3022[1]) + val(v1001),1,0)</pft></field> <field action="export" tag="list">3022</field> </loop> </do> <!-- ================================================== --> <label>COMPACTAR_FECHAS</label> <!-- ================================================== --> <!--display><pft>ALL</pft></display--> <display><pft>@COMPACT-DATES.PFT</pft></display> <proc>d3022d3023d3024d3025d3026</proc> <!-- Añadimos las fechas a la expresión de búsqueda --> <field action="replace" tag="3001"><pft> v3001,' AND (', |-F=|v3027+| OR |, ')', </pft></field> <!-- ================================================== --> <label>SEARCH_EXPR_READY</label> <!-- ================================================== --> <!-- Finalmente, quitamos un posible '$/(9204)' de la expresión de búsqueda --> <field action="replace" tag="3001"><pft> replace(replace(replace(v3001, '($/(9204)) AND ',''), '(/(9204)) AND ',''), '() AND ',''), </pft></field>