diff --git a/datasette/templates/table.html b/datasette/templates/table.html
index 605962d2..30162330 100644
--- a/datasette/templates/table.html
+++ b/datasette/templates/table.html
@@ -95,12 +95,15 @@
Suggested facets: {% for facet in suggested_facets %}{{ facet.name }} {% endfor %}
{% endif %}
-{% for facet_name, facet_values in facet_results.items() %}
+{% for facet_name, facet_info in facet_results.items() %}
{{ facet_name }}
- {% for facet_value in facet_values %}
+ {% for facet_value in facet_info.results %}
- {{ facet_value.value }} ({{ facet_value.count }})
{% endfor %}
+ {% if facet_info.truncated %}
+ - ...
+ {% endif %}
{% endfor %}
diff --git a/datasette/views/table.py b/datasette/views/table.py
index 81bb0c52..a567d42c 100644
--- a/datasette/views/table.py
+++ b/datasette/views/table.py
@@ -490,6 +490,7 @@ class TableView(RowTableShared):
)
# facets support
+ FACET_SIZE = 20
try:
facets = request.args["_facet"]
except KeyError:
@@ -499,18 +500,23 @@ class TableView(RowTableShared):
facet_sql = """
select {col} as value, count(*) as count
{from_sql} {and_or_where} {col} is not null
- group by {col} order by count desc limit 20
+ group by {col} order by count desc limit {limit}
""".format(
col=escape_sqlite(column),
from_sql=from_sql,
and_or_where='and' if where_clauses else 'where',
+ limit=FACET_SIZE+1,
)
try:
facet_rows = await self.execute(
name, facet_sql, params, truncate=False, custom_time_limit=200
)
- facet_results[column] = []
- for row in facet_rows:
+ facet_results[column] = {
+ "name": column,
+ "results": [],
+ "truncated": len(facet_rows) > FACET_SIZE,
+ }
+ for row in facet_rows[:FACET_SIZE]:
selected = str(other_args.get(column)) == str(row["value"])
if selected:
toggle_path = path_with_removed_args(
@@ -520,7 +526,7 @@ class TableView(RowTableShared):
toggle_path = path_with_added_args(
request, {column: row["value"]}
)
- facet_results[column].append({
+ facet_results[column]["results"].append({
"value": row["value"],
"count": row["count"],
"toggle_url": urllib.parse.urljoin(
diff --git a/tests/test_api.py b/tests/test_api.py
index 45b4b43c..a68c8a07 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -26,8 +26,6 @@ def test_database_page(app_client):
response = app_client.get('/test_tables.json', gather_request=False)
data = response.json
assert 'test_tables' == data['database']
- from pprint import pprint
- pprint(data['tables'])
assert [{
'columns': ['content'],
'name': '123_starts_with_digits',
@@ -893,103 +891,127 @@ def test_page_size_matching_max_returned_rows(app_client_returend_rows_matches_p
(
"/test_tables/facetable.json?_facet=state&_facet=city",
{
- "state": [
- {
- "value": "CA",
- "count": 10,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&state=CA",
- },
- {
- "value": "MI",
- "count": 4,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&state=MI",
- },
- {
- "value": "MC",
- "count": 1,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&state=MC",
- },
- ],
- "city": [
- {
- "value": "San Francisco",
- "count": 6,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&city=San+Francisco",
- },
- {
- "value": "Detroit",
- "count": 4,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&city=Detroit",
- },
- {
- "value": "Los Angeles",
- "count": 4,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&city=Los+Angeles",
- },
- {
- "value": "Memnonia",
- "count": 1,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&city=Memnonia",
- },
- ],
- },
+ "state": {
+ "name": "state",
+ "results": [
+ {
+ "value": "CA",
+ "count": 10,
+ "toggle_url": "_facet=state&_facet=city&state=CA",
+ "selected": False,
+ },
+ {
+ "value": "MI",
+ "count": 4,
+ "toggle_url": "_facet=state&_facet=city&state=MI",
+ "selected": False,
+ },
+ {
+ "value": "MC",
+ "count": 1,
+ "toggle_url": "_facet=state&_facet=city&state=MC",
+ "selected": False,
+ }
+ ],
+ "truncated": False,
+ },
+ "city": {
+ "name": "city",
+ "results": [
+ {
+ "value": "San Francisco",
+ "count": 6,
+ "toggle_url": "_facet=state&_facet=city&city=San+Francisco",
+ "selected": False,
+ },
+ {
+ "value": "Detroit",
+ "count": 4,
+ "toggle_url": "_facet=state&_facet=city&city=Detroit",
+ "selected": False,
+ },
+ {
+ "value": "Los Angeles",
+ "count": 4,
+ "toggle_url": "_facet=state&_facet=city&city=Los+Angeles",
+ "selected": False,
+ },
+ {
+ "value": "Memnonia",
+ "count": 1,
+ "toggle_url": "_facet=state&_facet=city&city=Memnonia",
+ "selected": False,
+ }
+ ],
+ "truncated": False,
+ }
+ }
), (
"/test_tables/facetable.json?_facet=state&_facet=city&state=MI",
{
- "state": [
- {
- "value": "MI",
- "count": 4,
- "selected": True,
- "toggle_url": "_facet=state&_facet=city",
- },
- ],
- "city": [
- {
- "value": "Detroit",
- "count": 4,
- "selected": False,
- "toggle_url": "_facet=state&_facet=city&state=MI&city=Detroit",
- },
- ],
+ "state": {
+ "name": "state",
+ "results": [
+ {
+ "value": "MI",
+ "count": 4,
+ "selected": True,
+ "toggle_url": "_facet=state&_facet=city",
+ },
+ ],
+ "truncated": False,
+ },
+ "city": {
+ "name": "city",
+ "results": [
+ {
+ "value": "Detroit",
+ "count": 4,
+ "selected": False,
+ "toggle_url": "_facet=state&_facet=city&state=MI&city=Detroit",
+ },
+ ],
+ "truncated": False,
+ },
},
), (
"/test_tables/facetable.json?_facet=planet_id",
{
- "planet_id": [
- {
- "value": 1,
- "count": 14,
- "selected": False,
- "toggle_url": "_facet=planet_id&planet_id=1",
- },
- {
- "value": 2,
- "count": 1,
- "selected": False,
- "toggle_url": "_facet=planet_id&planet_id=2",
- },
- ],
+ "planet_id": {
+ "name": "planet_id",
+ "results": [
+ {
+ "value": 1,
+ "count": 14,
+ "selected": False,
+ "toggle_url": "_facet=planet_id&planet_id=1",
+ },
+ {
+ "value": 2,
+ "count": 1,
+ "selected": False,
+ "toggle_url": "_facet=planet_id&planet_id=2",
+ },
+ ],
+ "truncated": False,
+ }
},
), (
# planet_id is an integer field:
"/test_tables/facetable.json?_facet=planet_id&planet_id=1",
{
- "planet_id": [
- {
- "value": 1,
- "count": 14,
- "selected": True,
- "toggle_url": "_facet=planet_id",
- }
- ],
+ "planet_id": {
+ "name": "planet_id",
+ "results": [
+ {
+ "value": 1,
+ "count": 14,
+ "selected": True,
+ "toggle_url": "_facet=planet_id",
+ }
+ ],
+ "truncated": False,
+ },
},
)
])
@@ -997,7 +1019,9 @@ def test_facets(app_client, path, expected_facet_results):
response = app_client.get(path, gather_request=False)
facet_results = response.json['facet_results']
# We only compare the querystring portion of the taggle_url
- for facet_name, facet_values in facet_results.items():
- for facet_value in facet_values:
+ for facet_name, facet_info in facet_results.items():
+ assert facet_name == facet_info["name"]
+ assert False is facet_info["truncated"]
+ for facet_value in facet_info["results"]:
facet_value['toggle_url'] = facet_value['toggle_url'].split('?')[1]
assert expected_facet_results == facet_results