query.py 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import logging
  2. from flask import (
  3. Blueprint, current_app, jsonify, request, make_response,
  4. render_template, send_file)
  5. from rdflib import URIRef
  6. from rdflib.plugin import PluginException
  7. from lakesuperior import env
  8. from lakesuperior.api import query as query_api
  9. from lakesuperior.dictionaries.namespaces import ns_collection as nsc
  10. from lakesuperior.dictionaries.namespaces import ns_mgr as nsm
  11. from lakesuperior.toolbox import Toolbox
  12. # Query endpoint. raw SPARQL queries exposing the underlying layout can be made
  13. # available. Also convenience methods that allow simple lookups based on simple
  14. # binary comparisons should be added. Binary lookups—maybe?
  15. # N.B All data sources are read-only for this endpoint.
  16. logger = logging.getLogger(__name__)
  17. rdfly = env.app_globals.rdfly
  18. query = Blueprint('query', __name__)
  19. @query.route('/term_search', methods=['GET', 'POST'])
  20. def term_search():
  21. """
  22. Search by entering a search term and optional property and comparison term.
  23. """
  24. operands = (
  25. ('_id', 'Matches Term'),
  26. ('=', 'Is Equal To'),
  27. ('!=', 'Is Not Equal To'),
  28. ('<', 'Is Less Than'),
  29. ('>', 'Is Greater Than'),
  30. ('<=', 'Is Less Than Or Equal To'),
  31. ('>=', 'Is Greater Than Or Equal To'),
  32. )
  33. qres = term_list = []
  34. if request.method == 'POST':
  35. terms = request.json.get('terms', {})
  36. or_logic = request.json.get('logic', 'and') == 'or'
  37. logger.info('Form: {}'.format(request.json))
  38. logger.info('Terms: {}'.format(terms))
  39. logger.info('Logic: {}'.format(or_logic))
  40. qres = query_api.term_query(terms, or_logic)
  41. rsp = [
  42. uri.replace(nsc['fcres'], request.host_url.rstrip('/') + '/ldp')
  43. for uri in qres]
  44. return jsonify(rsp), 200
  45. else:
  46. return render_template(
  47. 'term_search.html', operands=operands, qres=qres, nsm=nsm)
  48. @query.route('/sparql', methods=['GET', 'POST'])
  49. def sparql():
  50. """
  51. Perform a direct SPARQL query on the underlying triplestore.
  52. :param str qry: SPARQL query string.
  53. """
  54. accept_mimetypes = {
  55. 'text/csv': 'csv',
  56. 'application/sparql-results+json': 'json',
  57. 'application/sparql-results+xml': 'xml',
  58. }
  59. if request.method == 'GET':
  60. return render_template('sparql_query.html', nsm=nsm)
  61. else:
  62. if request.mimetype == 'application/sparql-query':
  63. qstr = request.stream.read()
  64. else:
  65. qstr = request.form['query']
  66. logger.debug('Query: {}'.format(qstr))
  67. match = request.accept_mimetypes.best_match(accept_mimetypes.keys())
  68. fmt = (
  69. accept_mimetypes[match] if match
  70. else request.accept_mimetypes.best)
  71. try:
  72. out_stream = query_api.sparql_query(qstr, fmt)
  73. except PluginException:
  74. return (
  75. 'Unable to serialize results into format {}'.format(fmt), 406)
  76. return send_file(out_stream, mimetype=fmt), 200