Facet results now have "truncated" field

To indicate if there was more than 20 distinct values. Refs #255
This commit is contained in:
Simon Willison 2018-05-15 06:50:27 -03:00 committed by Simon Willison
commit 142a550a99
3 changed files with 128 additions and 95 deletions

View file

@ -95,12 +95,15 @@
<p>Suggested facets: {% for facet in suggested_facets %}<a href="{{ facet.toggle_url }}">{{ facet.name }}</a> {% endfor %} <p>Suggested facets: {% for facet in suggested_facets %}<a href="{{ facet.toggle_url }}">{{ facet.name }}</a> {% endfor %}
{% endif %} {% endif %}
{% for facet_name, facet_values in facet_results.items() %} {% for facet_name, facet_info in facet_results.items() %}
<p><strong>{{ facet_name }}</strong></p> <p><strong>{{ facet_name }}</strong></p>
<ul> <ul>
{% for facet_value in facet_values %} {% for facet_value in facet_info.results %}
<li><a href="{{ facet_value.toggle_url }}">{{ facet_value.value }}</a> ({{ facet_value.count }})</li> <li><a href="{{ facet_value.toggle_url }}">{{ facet_value.value }}</a> ({{ facet_value.count }})</li>
{% endfor %} {% endfor %}
{% if facet_info.truncated %}
<li>...</li>
{% endif %}
</ul> </ul>
{% endfor %} {% endfor %}

View file

@ -490,6 +490,7 @@ class TableView(RowTableShared):
) )
# facets support # facets support
FACET_SIZE = 20
try: try:
facets = request.args["_facet"] facets = request.args["_facet"]
except KeyError: except KeyError:
@ -499,18 +500,23 @@ class TableView(RowTableShared):
facet_sql = """ facet_sql = """
select {col} as value, count(*) as count select {col} as value, count(*) as count
{from_sql} {and_or_where} {col} is not null {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( """.format(
col=escape_sqlite(column), col=escape_sqlite(column),
from_sql=from_sql, from_sql=from_sql,
and_or_where='and' if where_clauses else 'where', and_or_where='and' if where_clauses else 'where',
limit=FACET_SIZE+1,
) )
try: try:
facet_rows = await self.execute( facet_rows = await self.execute(
name, facet_sql, params, truncate=False, custom_time_limit=200 name, facet_sql, params, truncate=False, custom_time_limit=200
) )
facet_results[column] = [] facet_results[column] = {
for row in facet_rows: "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"]) selected = str(other_args.get(column)) == str(row["value"])
if selected: if selected:
toggle_path = path_with_removed_args( toggle_path = path_with_removed_args(
@ -520,7 +526,7 @@ class TableView(RowTableShared):
toggle_path = path_with_added_args( toggle_path = path_with_added_args(
request, {column: row["value"]} request, {column: row["value"]}
) )
facet_results[column].append({ facet_results[column]["results"].append({
"value": row["value"], "value": row["value"],
"count": row["count"], "count": row["count"],
"toggle_url": urllib.parse.urljoin( "toggle_url": urllib.parse.urljoin(

View file

@ -26,8 +26,6 @@ def test_database_page(app_client):
response = app_client.get('/test_tables.json', gather_request=False) response = app_client.get('/test_tables.json', gather_request=False)
data = response.json data = response.json
assert 'test_tables' == data['database'] assert 'test_tables' == data['database']
from pprint import pprint
pprint(data['tables'])
assert [{ assert [{
'columns': ['content'], 'columns': ['content'],
'name': '123_starts_with_digits', '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", "/test_tables/facetable.json?_facet=state&_facet=city",
{ {
"state": [ "state": {
{ "name": "state",
"value": "CA", "results": [
"count": 10, {
"selected": False, "value": "CA",
"toggle_url": "_facet=state&_facet=city&state=CA", "count": 10,
}, "toggle_url": "_facet=state&_facet=city&state=CA",
{ "selected": False,
"value": "MI", },
"count": 4, {
"selected": False, "value": "MI",
"toggle_url": "_facet=state&_facet=city&state=MI", "count": 4,
}, "toggle_url": "_facet=state&_facet=city&state=MI",
{ "selected": False,
"value": "MC", },
"count": 1, {
"selected": False, "value": "MC",
"toggle_url": "_facet=state&_facet=city&state=MC", "count": 1,
}, "toggle_url": "_facet=state&_facet=city&state=MC",
], "selected": False,
"city": [ }
{ ],
"value": "San Francisco", "truncated": False,
"count": 6, },
"selected": False, "city": {
"toggle_url": "_facet=state&_facet=city&city=San+Francisco", "name": "city",
}, "results": [
{ {
"value": "Detroit", "value": "San Francisco",
"count": 4, "count": 6,
"selected": False, "toggle_url": "_facet=state&_facet=city&city=San+Francisco",
"toggle_url": "_facet=state&_facet=city&city=Detroit", "selected": False,
}, },
{ {
"value": "Los Angeles", "value": "Detroit",
"count": 4, "count": 4,
"selected": False, "toggle_url": "_facet=state&_facet=city&city=Detroit",
"toggle_url": "_facet=state&_facet=city&city=Los+Angeles", "selected": False,
}, },
{ {
"value": "Memnonia", "value": "Los Angeles",
"count": 1, "count": 4,
"selected": False, "toggle_url": "_facet=state&_facet=city&city=Los+Angeles",
"toggle_url": "_facet=state&_facet=city&city=Memnonia", "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", "/test_tables/facetable.json?_facet=state&_facet=city&state=MI",
{ {
"state": [ "state": {
{ "name": "state",
"value": "MI", "results": [
"count": 4, {
"selected": True, "value": "MI",
"toggle_url": "_facet=state&_facet=city", "count": 4,
}, "selected": True,
], "toggle_url": "_facet=state&_facet=city",
"city": [ },
{ ],
"value": "Detroit", "truncated": False,
"count": 4, },
"selected": False, "city": {
"toggle_url": "_facet=state&_facet=city&state=MI&city=Detroit", "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", "/test_tables/facetable.json?_facet=planet_id",
{ {
"planet_id": [ "planet_id": {
{ "name": "planet_id",
"value": 1, "results": [
"count": 14, {
"selected": False, "value": 1,
"toggle_url": "_facet=planet_id&planet_id=1", "count": 14,
}, "selected": False,
{ "toggle_url": "_facet=planet_id&planet_id=1",
"value": 2, },
"count": 1, {
"selected": False, "value": 2,
"toggle_url": "_facet=planet_id&planet_id=2", "count": 1,
}, "selected": False,
], "toggle_url": "_facet=planet_id&planet_id=2",
},
],
"truncated": False,
}
}, },
), ( ), (
# planet_id is an integer field: # planet_id is an integer field:
"/test_tables/facetable.json?_facet=planet_id&planet_id=1", "/test_tables/facetable.json?_facet=planet_id&planet_id=1",
{ {
"planet_id": [ "planet_id": {
{ "name": "planet_id",
"value": 1, "results": [
"count": 14, {
"selected": True, "value": 1,
"toggle_url": "_facet=planet_id", "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) response = app_client.get(path, gather_request=False)
facet_results = response.json['facet_results'] facet_results = response.json['facet_results']
# We only compare the querystring portion of the taggle_url # We only compare the querystring portion of the taggle_url
for facet_name, facet_values in facet_results.items(): for facet_name, facet_info in facet_results.items():
for facet_value in facet_values: 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] facet_value['toggle_url'] = facet_value['toggle_url'].split('?')[1]
assert expected_facet_results == facet_results assert expected_facet_results == facet_results