summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/config.py2
-rw-r--r--python/fatcat/routes.py28
-rw-r--r--python/fatcat/search.py49
-rw-r--r--python/fatcat/templates/base.html10
-rw-r--r--python/fatcat/templates/release_search.html33
-rw-r--r--python/tests/routes.py8
6 files changed, 124 insertions, 6 deletions
diff --git a/python/config.py b/python/config.py
index a7ec4b50..21c1e148 100644
--- a/python/config.py
+++ b/python/config.py
@@ -6,6 +6,8 @@ class Config(object):
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URI') or \
'sqlite:///' + os.path.join(basedir, 'fatcat_dev.sqlite')
SQLALCHEMY_TRACK_MODIFICATIONS = False
+ ELASTIC_BACKEND = "http://search.qa.fatcat.wiki:8088"
+ ELASTIC_INDEX = "crossref-works"
# "Event more verbose" debug options. SECRET_KEY is bogus.
#SQLALCHEMY_ECHO = True
diff --git a/python/fatcat/routes.py b/python/fatcat/routes.py
index f4c7c513..8fe74a2d 100644
--- a/python/fatcat/routes.py
+++ b/python/fatcat/routes.py
@@ -5,11 +5,11 @@ from flask import Flask, render_template, send_from_directory, request, \
url_for, abort, g, redirect, jsonify, session
from fatcat import app, api
from fatcat_client.rest import ApiException
+from fatcat.search import do_search
### Views ###################################################################
-
@app.route('/container/<uuid:ident>', methods=['GET'])
def container_view(ident):
try:
@@ -156,6 +156,32 @@ def editor_changelog(username):
return render_template('editor_changelog.html', editor=editor,
changelog_entries=changelog_entries)
+### Search ##################################################################
+
+@app.route('/release/search', methods=['GET', 'POST'])
+def search():
+
+ limit = 20
+ query = request.args.get('q')
+
+ # Convert raw DOIs to DOI queries
+ if query is not None:
+ oldquery = query.split()
+ for word in oldquery:
+ if word.startswith("10.") and word.count("/") >= 1:
+ query = query.replace(word, 'doi:"{}"'.format(word))
+
+ # Convert "author:" query to "authors:"
+ if query is not None:
+ query = query.replace("author:", "authors:")
+
+ if 'q' in request.args.keys():
+ # always do files for HTML
+ found = do_search(query, limit=limit)
+ return render_template('release_search.html', found=found)
+ else:
+ return render_template('release_search.html')
+
### Static Routes ###########################################################
diff --git a/python/fatcat/search.py b/python/fatcat/search.py
new file mode 100644
index 00000000..7ed7a99c
--- /dev/null
+++ b/python/fatcat/search.py
@@ -0,0 +1,49 @@
+
+import requests
+from flask import abort
+from fatcat import app
+
+
+def do_search(q, limit=20):
+
+ print("Search hit: " + q)
+ if limit > 100:
+ # Sanity check
+ limit = 100
+
+ search_request = {
+ "query": {
+ "query_string": {
+ "query": q,
+ "analyzer": "textIcuSearch",
+ "default_operator": "AND",
+ "analyze_wildcard": True,
+ "lenient": True,
+ "auto_generate_phrase_queries": True,
+ "default_field": "_all",
+ },
+ },
+ "size": int(limit),
+ }
+
+ resp = requests.get("%s/%s/_search" %
+ (app.config['ELASTIC_BACKEND'], app.config['ELASTIC_INDEX']),
+ json=search_request)
+
+ if resp.status_code != 200:
+ print("elasticsearch non-200 status code: " + str(resp.status_code))
+ print(resp.content)
+ abort(resp.status_code)
+
+ content = resp.json()
+ results = [h['_source'] for h in content['hits']['hits']]
+ for h in results:
+ # Ensure 'authors' is a list, not a single string
+ if type(h['authors']) is not list:
+ h['authors'] = [h['authors'], ]
+
+ found = content['hits']['total']
+ return {"query": { "q": q },
+ "count_returned": len(results),
+ "count_found": found,
+ "results": results }
diff --git a/python/fatcat/templates/base.html b/python/fatcat/templates/base.html
index ae487a18..ac6fef43 100644
--- a/python/fatcat/templates/base.html
+++ b/python/fatcat/templates/base.html
@@ -26,10 +26,12 @@
<a href="#" class="item">Guide</a>
<div class="right menu">
<div class="item">
- <div class="ui transparent inverted icon input">
- <i class="search icon"></i>
- <input type="text" placeholder="Search...">
- </div>
+ <form class="" role="search" action="/release/search" method="get">
+ <div class="ui transparent inverted icon input">
+ <i class="search icon"></i>
+ <input type="text" placeholder="Search..." name="q">
+ </div>
+ </form>
</div>
<div class="ui simple dropdown item">
demo-user <i class="dropdown icon"></i>
diff --git a/python/fatcat/templates/release_search.html b/python/fatcat/templates/release_search.html
new file mode 100644
index 00000000..39c9bbe6
--- /dev/null
+++ b/python/fatcat/templates/release_search.html
@@ -0,0 +1,33 @@
+{% extends "base.html" %}
+{% block body %}
+
+{% if found %}
+<h1>Search Results</h1>
+<i>Showing top {{ found.count_returned }} out of {{ found.count_found }} results for: <code>{{ found.query.q }}</code></i>
+{% for paper in found.results %}
+<div>
+ <h4 style="margin-top: 1em; margin-bottom: 4px;"><a href="/release/lookup?doi={{ paper.doi }}" style="color: #2224c7;">{{ paper['title'] }}</a></h4>
+ <h5 style="margin-top: 4px; margin-bottom: 4px;">{{ ", ".join(paper.authors) }}</h5>
+ DOI: <a href="http://oadoi.org/{{paper.doi }}" style="color: green;">{{ paper.doi }}</a>
+ <br>Journal: {{ paper.journal }}
+ <!-- <br>Date: {{ paper.date }} -->
+</div>
+{% else %}
+<br/>
+<p>Try:</p>
+<ul>
+ <li>Search <a href="https://dissem.in/search?q={{ found.query.q | urlencode }}">dissem.in</a></li>
+ <li>Search <a href="https://www.base-search.net/Search/Results?lookfor={{ found.query.q | urlencode }}">BASE</a></li>
+ <li>Search <a href="https://scholar.google.com/scholar?q={{ found.query.q | urlencode }}">Google Scholar</a></li>
+</ul>
+<div class="featurette-inner text-center" style="padding-top: 25%;">
+<h3>Found nothing!</h3>
+</div>
+{% endfor %}
+{% else %}
+<div class="featurette-inner text-center" style="padding-top: 25%;">
+<h3>Enter a query above</h3>
+</div>
+{% endif %}
+
+{% endblock %}
diff --git a/python/tests/routes.py b/python/tests/routes.py
index b2cfd058..f92df54c 100644
--- a/python/tests/routes.py
+++ b/python/tests/routes.py
@@ -54,7 +54,13 @@ def test_all_views(app):
rv = app.get('/release/00000000-0000-0000-4444-000000000002')
assert rv.status_code == 200
- rv = app.get('/release/00000000-0000-0000-4444-000000000002'.format(route))
+ rv = app.get('/release/lookup?doi=10.123/abc')
+ assert rv.status_code == 302
+
+ rv = app.get('/release/lookup?doi=10.123%2Fabc')
+ assert rv.status_code == 302
+
+ rv = app.get('/release/search')
assert rv.status_code == 200
rv = app.get('/work/00000000-0000-0000-5555-000000000002')