Skip to content

Commit

Permalink
document: advanced search config and endpoint
Browse files Browse the repository at this point in the history
* Adds configuration for enabled/disabled advanced search.
* Adds a new field in the document schema to group
  call number for holdings and items.
* Adds a new endpoint for advanced search config.

⚠️  update ES mapping and reindex ES documents

Co-Authored-by: Bertrand Zuchuat <[email protected]>
  • Loading branch information
Garfield-fr committed Nov 14, 2023
1 parent e07c8be commit f8bc474
Show file tree
Hide file tree
Showing 5 changed files with 326 additions and 7 deletions.
183 changes: 183 additions & 0 deletions rero_ils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ def _(x):
RERO_ILS_ILL_REQUEST_ON_GLOBAL_VIEW = True
RERO_ILS_ILL_DEFAULT_SOURCE = 'RERO +'

# DOCUMENT ADVANCED SEARCH
RERO_ILS_APP_DOCUMENT_ADVANCED_SEARCH = True

# Rate limiting
# =============
#: Storage for ratelimiter.
Expand Down Expand Up @@ -3639,3 +3642,183 @@ def _(x):
RERO_ILS_PASSWORD_SPECIAL_CHAR = False
RERO_ILS_PASSWORD_GENERATOR = 'rero_ils.modules.utils:password_generator'
RERO_ILS_PASSWORD_VALIDATOR = 'rero_ils.modules.utils:password_validator'

# ADVANCED SEARCH CONFIG
# ======================
def search_type(field):
"""Search type options.
:param: field: the field key.
:return: a list of options.
"""
output = [];
if field not in [
'country', 'canton', 'rdaContentType', 'rdaMediaType',
'rdaCarrierType'
]:
output.append({'label': _('contains'), 'value': 'contains'})
output.append({'label': _('exact'), 'value': 'phrase'})
return output

RERO_ILS_APP_ADVANCED_SEARCH_CONFIG = [
{
'label': 'Title',
'value': 'title',
'field': 'title.*',
'options': {
'search_type': search_type('title')
}
},
{
'label': 'Responsibility statement',
'value': 'responsibilityStatement',
'field': 'responsibilityStatement.value',
'options': {
'search_type': search_type('responsibilityStatement')
}
},
{
'label': 'Contribution',
'value': 'contribution',
'field': 'contribution.entity.*',
'options': {
'search_type': search_type('contribution')
}
},
{
'label': 'Country',
'value': 'country',
'field': 'provisionActivity.place.country',
'options': {
'search_type': search_type('country')
}
},
{
'label': 'Canton',
'value': 'canton',
'field': 'provisionActivity.place.canton',
'options': {
'search_type': search_type('canton')
}
},
{
'label': 'Provision activity statement',
'value': 'provisionActivityStatement',
'field': 'provisionActivity._text.value',
'options': {
'search_type': search_type('provisionActivityStatement')
}
},
{
'label': 'Series statement',
'value': 'seriesStatement',
'field': 'seriesStatement.*',
'options': {
'search_type': search_type('seriesStatement')
}
},
{
'label': 'Identifier',
'value': 'identifiedBy',
'field': 'identifiedBy.value',
'options': {
'search_type': search_type('identifiedBy')
}
},
{
'label': 'ISBN',
'value': 'isbn',
'field': 'isbn',
'options': {
'search_type': search_type('isbn')
}
},
{
'label': 'ISSN',
'value': 'issn',
'field': 'issn',
'options': {
'search_type': search_type('issn')
}
},
{
'label': 'Genre, form',
'value': 'genreForm',
'field': 'genreForm.entity.*',
'options': {
'search_type': search_type('genreForm')
}
},
{
'label': 'Subject',
'value': 'subjects',
'field': 'subjects.entity.*',
'options': {
'search_type': search_type('subjects')
}
},
{
'label': 'Call number',
'value': 'callNumber',
'field': 'call_numbers',
'options': {
'search_type': search_type('callNumber')
}
},
{
'label': 'Local fields (document)',
'value': 'documentLocalFields',
'field': 'local_fields.*',
'options': {
'search_type': search_type('documentLocalFields')
}
},
{
'label': 'Local fields (holdings)',
'value': 'holdingsLocalFields',
'field': 'holdings.local_fields.*',
'options': {
'search_type': search_type('holdingsLocalFields')
}
},
{
'label': 'Local fields (items)',
'value': 'itemLocalFields',
'field': 'holdings.items.local_fields.*',
'options': {
'search_type': search_type('itemLocalFields')
}
},
{
'label': 'Classification',
'value': 'classification',
'field': 'classification.*',
'options': {
'search_type': search_type('classification')
}
},
{
'label': 'RDA content type',
'value': 'rdaContentType',
'field': 'contentMediaCarrier.contentType',
'options': {
'search_type': search_type('rdaContentType')
}
},
{
'label': 'RDA media type',
'value': 'rdaMediaType',
'field': 'contentMediaCarrier.mediaType',
'options': {
'search_type': search_type('rdaMediaType')
}
},
{
'label': 'RDA carrier type',
'value': 'rdaCarrierType',
'field': 'contentMediaCarrier.carrierType',
'options': {
'search_type': search_type('rdaCarrierType')
}
},
]
61 changes: 60 additions & 1 deletion rero_ils/modules/documents/api_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@

"""Blueprint for document api."""

from flask import Blueprint, abort, jsonify
from functools import cmp_to_key

from flask import Blueprint, abort, current_app, jsonify
from flask import request as flask_request
from invenio_jsonschemas import current_jsonschemas
from invenio_jsonschemas.errors import JSONSchemaNotFound

from rero_ils.modules.decorators import check_logged_as_librarian

from .api import Document
from .utils import get_remote_cover
Expand Down Expand Up @@ -50,3 +56,56 @@ def document_availability(pid):
return jsonify({
'available': Document.is_available(pid, view_code)
})


@api_blueprint.route('/advanced-search-config')
@cached(timeout=300, query_string=True)
@check_logged_as_librarian
def advanced_search_config():
"""Advanced search config."""

def sort_medias(a, b):
"""Sort only media start with rda in label."""
a, b = a['label'], b['label']
if a.startswith('rda') and b.startswith('rda'):
return a > b
elif a.startswith('rda'):
return -1
elif b.startswith('rda'):
return 1
else:
return a > b

try:
cantons = current_jsonschemas.get_schema('common/cantons-v0.0.1.json')
countries = current_jsonschemas.get_schema(
'common/countries-v0.0.1.json')
medias = current_jsonschemas.get_schema(
'documents/document_content_media_carrier-v0.0.1.json')
except JSONSchemaNotFound:
abort(404)

media_items = medias['contentMediaCarrier']['items']['oneOf']
media_types = []
carrier_types = []
for item in media_items:
if rda_type := item.get('properties', {}).get('mediaType', {}):
data = rda_type.get('title')
media_types.append({'label': data, 'value': data})
if rda_type := item.get('properties', {}).get('carrierType', {}):
for option in rda_type.get('form', {}).get('options'):
if option not in carrier_types:
carrier_types.append(option)
return jsonify({
'fieldsConfig': current_app.config.get(
'RERO_ILS_APP_ADVANCED_SEARCH_CONFIG', []),
'fieldsData': {
'country': countries['country']['form']['options'],
'canton': cantons['canton']['form']['options'],
'rdaContentType': medias['definitions']['contentType']['items']
['form']['options'],
'rdaMediaType': sorted(media_types, key=cmp_to_key(sort_medias)),
'rdaCarrierType': sorted(
carrier_types, key=cmp_to_key(sort_medias))
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -526,10 +526,10 @@
"type": "object",
"properties": {
"canton": {
"type": "text"
"type": "keyword"
},
"country": {
"type": "text"
"type": "keyword"
},
"identifiedBy": {
"type": "object",
Expand Down Expand Up @@ -1139,10 +1139,12 @@
}
},
"call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"second_call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"index": {
"type": "text"
Expand All @@ -1166,10 +1168,12 @@
"type": "keyword"
},
"call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"second_call_number": {
"type": "text"
"type": "text",
"copy_to": "call_numbers"
},
"status": {
"type": "keyword"
Expand Down Expand Up @@ -2135,6 +2139,9 @@
}
}
},
"call_numbers": {
"type": "text"
},
"_draft": {
"type": "boolean"
},
Expand Down
2 changes: 2 additions & 0 deletions rero_ils/modules/patrons/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ def logged_user():
'agentLabelOrder': config.get('RERO_ILS_AGENTS_LABEL_ORDER', {}),
'agentSources': config.get('RERO_ILS_AGENTS_SOURCES', []),
'operationLogs': config.get('RERO_ILS_ENABLE_OPERATION_LOG', []),
'documentAdvancedSearch': config.get(
'RERO_ILS_APP_DOCUMENT_ADVANCED_SEARCH', False),
'userProfile': {
'readOnly': config.get(
'RERO_PUBLIC_USERPROFILES_READONLY', False),
Expand Down
Loading

0 comments on commit f8bc474

Please sign in to comment.