This is an old revision of the document!
Queremos organizar el display de una lista de registros bibliográficos asociados a un encabezamiento (pensemos por ahora en nombres personales), de manera tal que queden separados en bloques los registros donde la persona aparece como “autor”, de aquellos donde desempeña otra función. A su vez, sería deseable subclasificar estos últimos de acuerdo al tipo de función.
Un ejemplo sencillo puede verse en este mensaje del grupo Catalis.
Consideremos, para simplificar, que “autor” corresponde a un 100 o un 700 sin código de relación (subcampo $4), y “otra función” corresponde a un 700 con $4.
Si —tal como sucede actualmente— al invertido de la base BIBLIO mandamos los puntos de acceso sin hacer distinción según la relación (700$4), entonces al recuperar usando un punto de acceso obtendremos indiscriminadamente todos los registros asociados, y la clasificación en base a la relación habrá que hacerla analizando cada uno de los registros recuperados. Esto agrega un costo a cada búsqueda, proporcional al número de registros recuperados.
Si en cambio mandamos al invertido de forma diferenciada los “autores” y los “otra-función”, entonces podemos hacer dos búsquedas separadas: con una recuperamos los registros donde Fulano aparece como “autor”, y con otra aquellos donde Fulano aparece en “otra-función”. Luego ordenamos cada uno de esos dos conjuntos por el criterio que corresponda. Para aplicar esa distinción a nivel del invertido podemos usar diferentes tags en la FST, e.g. 9100 para “autor” y 9101 para “otra-función”.
Pero, ¿y si queremos ser más específicos y poder recuperar solamente registros donde Fulano es editor, o director de tesis, en vez de juntar todos los casos de “otra-función” en una misma bolsa? Tal vez deberíamos añadir nuevas claves al diccionario, de la forma _NAME_<id>_<relación>
:
_NAME_1234_--- <= "autor" (i.e., relación no especificada) _NAME_1234_EDT <= editor _NAME_1234_AUI <= prologuista _NAME_1234_TRL <= traductor
Si la persona tiene más de un código de relación (p.ej. aui
y trl
):
_NAME_1234_AUI_TRL <= traductor y prologuista
aunque quizás sea mejor enviarlos al invertido en forma separada, así lo recuperamos al buscar por una cualquiera de las relaciones:
_NAME_1234_AUI <= prologuista _NAME_1234_TRL <= traductor
Actualmente, sólo estamos usando esta clave:
_NAME_1234 <= no discrimina relaciones
Parece que sería redundante conservarla si vamos a utilizar las propuestas arriba, pero… ¡Atención! Si bien para una búsqueda general podríamos usar _NAME_1234_$
(que agrupa todos los casos), para determinar de manera sencilla el número de postings (registros asociados al encabezamiento) conviene tener también una clave “limpia” _NAME_1234
, aunque esto resulte redundante. Actualmente se usa algo así para encontrar los postings asociados al encabezamiento v9:
f(npost(['biblio']'_NAME_'v9),1,0)
y no podemos usar npost()
con un término que incluya el sufijo $
.
Actualmente sólo usamos las claves _NAME_<id> para poder averiguar fácilmente la cantidad de postings asociados a un encabezamiento (hacer un wcgrep de “_NAME_” y de “_%s_”), pero no para las búsquedas por encabezamiento en la base BIBLIO, que siguen dependiendo de la forma *textual* del encabezamiento (con los consiguientes problemas asociados al límite en la longitud de las claves, ver heading-match-in-bib-record.xis
). Si bien es conveniente que la URL de una búsqueda de este tipo tenga como query el encabezamiento, y no un identificador numérico (que podría llegar a variar), podríamos introducir un paso intermedio que mapee el encabezamiento, recibido vía URL, a su identificador, y luego hacer la búsqueda en biblio de manera precisa, usando sólo el identificador. No importa que el identificador sea inestable (i.e., que pueda cambiar en una futura generación de las bases del OPAC), ya que no lo estaríamos exponiendo públicamente. (¿Por qué no habremos hecho esto antes?)
Cómo hacer el mapeo encabezamiento ⇒ id (on the fly, con cada petición):
Este procedimiento sería similar (pero más fácil y limpio) al actualmente empleado, que hace la búsqueda directamente en BIBLIO, sin pasar por el id. Si hacemos esto, ¿podemos omitir los encabezamientos completos en el invertido de BIBLIO?
Modificar las líneas 9100 que generan claves de la forma _NAME_<id>
:
if p(v700) then proc('d1000', 'd1001'), /* limpiamos campos auxiliares */ proc( /*'d1000',*/ (, 'a1000¦', replace(v700*3,'^','¦a1000¦'), '¦', 'a1000¦##¦', ) ), /* loop sobre v1000 */ ,(, if v1000 = '##' then /, proc('d1001'), /* almacena los $4 de una ocurrencia del v700 */ else if 'abcdq' : v1000.1 then '~'v1000*1, /* ATENCION! esto sólo funciona si 700$4 aparece *ANTES* que 700$9 */ else if '4' = v1000.1 then proc('d1001','a1001|',v1001[1],'_',v1000*1,'|'), else if '9' = v1000.1 then /, '_NAME_', /* sin sufijo */ v1000*1, /, '_NAME_', /* con sufijo para indicar la relación */ v1000*1, if v1001[1] = '' then '_---' else v1001[1], fi, / fi,fi,fi,fi, ,), fi,
El algoritmo sería algo como esto:
query
para convertirlo en la expresión de búsqueda expr
(esto es, aplicar a query las transformaciones necesarias para que pueda ser utilizado como clave de búsqueda)expr
matches
← {}
H
encontrado:H
coincide con query
: matches
← matches + {encabezamiento}
matches
tiene cero o más de un elemento: error, abortarID
← id del único encabezamiento en matches
relations
← {}
k
del diccionario BIBLIO entre _NAME_<ID>_---
y _NAME_<ID>_zzz
:relations
← relations
+ {los 3 caracteres finales de k
}rel
en relations
:_NAME_<ID>_<rel>
<!-- Encontrar ID del encabezamiento --> <!-- Primero, normalizar query. Ver cómo aparecen los encabezamientos en el diccionario de las bases NAME, SUBJ. Notar que no coincide con el diccionario de BIBLIO. --> <field tag="3001" action="replace"><pft>hacer algo a v2001</pft></field> <!-- Búsqueda --> <do task="search"> <parm name="db"><pft>v2003</pft></parm> <!-- v2003: NAME / SUBJ --> <parm name="expression"><pft>v3001</pft></parm> <!-- v2001 normalizado --> <define>1002 Isis_Total</define> <loop> <field action="import" tag="list">2001</field> <flow action=""><pft>if val(v1002) <> 1 then 'Quit' fi</pft></flow> <field tag="9" action="replace"><pft>if v1 = v2001 then v9 fi</pft></field> <field tag="9" action="export">9</field> </loop> </do> <!-- Encontrar relaciones asociadas al encabezamiento --> <do task="keyrange"> <parm name="db">BIBLIO</parm> <parm name="from"><pft>'_'v2003'_', v9, '_'</pft></parm> <parm name="to"><pft>'_'v2003'_', v9, '_ZZZ'</pft></parm> <define>1 Isis_Key</define> <loop> <list action="load" type="list"><pft>v1</pft></list> </loop> </do> <!-- Encontrar y procesar los registros bibliográficos --> <!-- La lista contiene las relaciones (claves para las búsquedas) --> <do task="list"> <define>1 Isis_Item</define> <!-- Una búsqueda por cada clave --> <!-- FIXME - Vamos a tener un problema con la limitación de wxis a una única lista; en cada búsqueda necesitamos una lista para almacenar los resultados antes de presentarlos, pero todas las búsquedas viven dentro de un ''do task=list'' exterior --> <display><pft>'<h3>Relación: ', right(v1, 3),'</h3>'</pft></display> <do task="search"> <parm name="db">BIBLIO</parm> <parm name="expression"><pft>v1</pft></parm> <define>1002 Isis_Total</define> <loop> <!-- procesar cada registro bibliográfico --> <display><pft>'Total: ',v1002,'<br>'</pft></display> </loop> </do> </do>
ATENCIÓN a la diferencia entre estas dos maneras de enviar encabezamientos a los diccionarios, según la base:
-- NAME -- ~ABREGU MARTIN ~ADERINWALE AYODELE ~ADLER GLENN 1958 ~AFRICA INSTITUTE OF SOUTH AFR ~AFRICA LEADERSHIP FORUM ~AGUERO FELIPE ~ALBERT EINSTEIN INSTITUTION C ~ALEN ANDRE ~ALFONSIN RAUL ~ARMSTRONG CHARLES K -- BIBLIO -- ~ABREGU_MARTIN ~ADERINWALE_AYODELE ~ADLER_GLENN~1958- ~AFRICA_INSTITUTE_OF_SOUTH_AFR ~AFRICA_LEADERSHIP_FORUM ~AGUERO_FELIPE
~ALBERT_EINSTEIN_INSTITUTION_[ ~ALEN_ANDRE ~ALFONSIN_RAUL ~ARMSTRONG_CHARLES_K
¿Qué pasa si un nombre aparece como “autor” y como “otra función” en un mismo registro? Creo que no debería suceder que un nombre se repitiera en campos 100/700.
¿Qué hacemos con la mezcla que puede llegar a haber dentro del conjunto de registros correspondientes a “otra función”? Quizás ahora sí podríamos analizar registro por registro, una vez que nos acotamos a este conjunto. Tendremos un problema si un nombre tiene más de un $4 en un mismo registro.
¡Ojo con los puntos de acceso de nombre-título, 700$a$t (con o sin $4)!
Ver la relación entre esta organización del listado y la paginación.
Algunos detalles podrán depender del tipo de relaciones que sean más importantes (i.e., que nos interese destacar) en cada catálogo particular. Por ejemplo, los roles “fotógrafo” o “ilustrador” podrían ser más relevantes en una colección de arte que en una general.
Preguntas que deberían ser fáciles de responder:
keyrange
en BIBLIO, from=_NAME_<H>_ to=_NAME_<H>_
(¿y si quisiéramos averiguarlo sólo mirando NAME?)npost(['BIBLIO']'_NAME_<H>_<f>')
; ejemplo: npost(['BIBLIO']'_NAME_12345_EDT')
(función: editor)Para permitir la organización de registros aquí planteada, es fundamental que los puntos de acceso incluyan información (normalizada) acerca de la relación. No siempre esta información ha sido registrada, de manera que antes de considerar la implementación de esta funcionalidad para una determinada base bibliográfica, analicemos el uso de los subcampos de relación (7xx$4, 7xx$e), y hagamos las modificaciones apropiadas.
mxtb biblio create=v700_e "30:(v700^e/)" mx v700_e "pft=v999,c6,v1/" now mxtb biblio create=v700_4 "30:(v700^4/)" mx v700_4 "pft=v999,c6,v1/" now
Los 700$e deberían convertirse en 700$4. TAREA: escribir script.
(Repetir para otros 7xx.)
mx biblio "pft=if v245^c:'edit' and not v700^e:'edit' and not v700^4:'edt' then mfn/v245/(v700/)# fi" now lw=300