Suggest column facet only if at least one count > 1

Fixes #638
This commit is contained in:
Simon Willison 2019-11-21 16:56:55 -08:00
commit fd137da7f8
4 changed files with 65 additions and 35 deletions

View file

@ -143,9 +143,10 @@ class ColumnFacet(Facet):
if column in already_enabled: if column in already_enabled:
continue continue
suggested_facet_sql = """ suggested_facet_sql = """
select distinct {column} from ( select {column}, count(*) as n from (
{sql} {sql}
) where {column} is not null ) where {column} is not null
group by {column}
limit {limit} limit {limit}
""".format( """.format(
column=escape_sqlite(column), sql=self.sql, limit=facet_size + 1 column=escape_sqlite(column), sql=self.sql, limit=facet_size + 1
@ -165,6 +166,8 @@ class ColumnFacet(Facet):
and num_distinct_values > 1 and num_distinct_values > 1
and num_distinct_values <= facet_size and num_distinct_values <= facet_size
and num_distinct_values < row_count and num_distinct_values < row_count
# And at least one has n > 1
and any(r["n"] > 1 for r in distinct_values)
): ):
suggested_facets.append( suggested_facets.append(
{ {

View file

@ -669,26 +669,27 @@ CREATE TABLE facetable (
neighborhood text, neighborhood text,
tags text, tags text,
complex_array text, complex_array text,
distinct_some_null,
FOREIGN KEY ("city_id") REFERENCES [facet_cities](id) FOREIGN KEY ("city_id") REFERENCES [facet_cities](id)
); );
INSERT INTO facetable INSERT INTO facetable
(created, planet_int, on_earth, state, city_id, neighborhood, tags, complex_array) (created, planet_int, on_earth, state, city_id, neighborhood, tags, complex_array, distinct_some_null)
VALUES VALUES
("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Mission', '["tag1", "tag2"]', '[{"foo": "bar"}]'), ("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Mission', '["tag1", "tag2"]', '[{"foo": "bar"}]', 'one'),
("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Dogpatch', '["tag1", "tag3"]', '[]'), ("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Dogpatch', '["tag1", "tag3"]', '[]', 'two'),
("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'SOMA', '[]', '[]'), ("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'SOMA', '[]', '[]', null),
("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Tenderloin', '[]', '[]'), ("2019-01-14 08:00:00", 1, 1, 'CA', 1, 'Tenderloin', '[]', '[]', null),
("2019-01-15 08:00:00", 1, 1, 'CA', 1, 'Bernal Heights', '[]', '[]'), ("2019-01-15 08:00:00", 1, 1, 'CA', 1, 'Bernal Heights', '[]', '[]', null),
("2019-01-15 08:00:00", 1, 1, 'CA', 1, 'Hayes Valley', '[]', '[]'), ("2019-01-15 08:00:00", 1, 1, 'CA', 1, 'Hayes Valley', '[]', '[]', null),
("2019-01-15 08:00:00", 1, 1, 'CA', 2, 'Hollywood', '[]', '[]'), ("2019-01-15 08:00:00", 1, 1, 'CA', 2, 'Hollywood', '[]', '[]', null),
("2019-01-15 08:00:00", 1, 1, 'CA', 2, 'Downtown', '[]', '[]'), ("2019-01-15 08:00:00", 1, 1, 'CA', 2, 'Downtown', '[]', '[]', null),
("2019-01-16 08:00:00", 1, 1, 'CA', 2, 'Los Feliz', '[]', '[]'), ("2019-01-16 08:00:00", 1, 1, 'CA', 2, 'Los Feliz', '[]', '[]', null),
("2019-01-16 08:00:00", 1, 1, 'CA', 2, 'Koreatown', '[]', '[]'), ("2019-01-16 08:00:00", 1, 1, 'CA', 2, 'Koreatown', '[]', '[]', null),
("2019-01-16 08:00:00", 1, 1, 'MI', 3, 'Downtown', '[]', '[]'), ("2019-01-16 08:00:00", 1, 1, 'MI', 3, 'Downtown', '[]', '[]', null),
("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Greektown', '[]', '[]'), ("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Greektown', '[]', '[]', null),
("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Corktown', '[]', '[]'), ("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Corktown', '[]', '[]', null),
("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Mexicantown', '[]', '[]'), ("2019-01-17 08:00:00", 1, 1, 'MI', 3, 'Mexicantown', '[]', '[]', null),
("2019-01-17 08:00:00", 2, 0, 'MC', 4, 'Arcadia Planitia', '[]', '[]') ("2019-01-17 08:00:00", 2, 0, 'MC', 4, 'Arcadia Planitia', '[]', '[]', null)
; ;
CREATE TABLE binary_data ( CREATE TABLE binary_data (

View file

@ -197,6 +197,7 @@ def test_database_page(app_client):
"neighborhood", "neighborhood",
"tags", "tags",
"complex_array", "complex_array",
"distinct_some_null",
], ],
"primary_keys": ["pk"], "primary_keys": ["pk"],
"count": 15, "count": 15,
@ -1042,15 +1043,38 @@ def test_table_filter_json_arraycontains(app_client):
"Mission", "Mission",
'["tag1", "tag2"]', '["tag1", "tag2"]',
'[{"foo": "bar"}]', '[{"foo": "bar"}]',
"one",
],
[
2,
"2019-01-14 08:00:00",
1,
1,
"CA",
1,
"Dogpatch",
'["tag1", "tag3"]',
"[]",
"two",
], ],
[2, "2019-01-14 08:00:00", 1, 1, "CA", 1, "Dogpatch", '["tag1", "tag3"]', "[]"],
] == response.json["rows"] ] == response.json["rows"]
def test_table_filter_extra_where(app_client): def test_table_filter_extra_where(app_client):
response = app_client.get("/fixtures/facetable.json?_where=neighborhood='Dogpatch'") response = app_client.get("/fixtures/facetable.json?_where=neighborhood='Dogpatch'")
assert [ assert [
[2, "2019-01-14 08:00:00", 1, 1, "CA", 1, "Dogpatch", '["tag1", "tag3"]', "[]"] [
2,
"2019-01-14 08:00:00",
1,
1,
"CA",
1,
"Dogpatch",
'["tag1", "tag3"]',
"[]",
"two",
]
] == response.json["rows"] ] == response.json["rows"]
@ -1503,6 +1527,7 @@ def test_expand_labels(app_client):
"neighborhood": "Dogpatch", "neighborhood": "Dogpatch",
"tags": '["tag1", "tag3"]', "tags": '["tag1", "tag3"]',
"complex_array": "[]", "complex_array": "[]",
"distinct_some_null": "two",
}, },
"13": { "13": {
"pk": 13, "pk": 13,
@ -1514,6 +1539,7 @@ def test_expand_labels(app_client):
"neighborhood": "Corktown", "neighborhood": "Corktown",
"tags": "[]", "tags": "[]",
"complex_array": "[]", "complex_array": "[]",
"distinct_some_null": None,
}, },
} == response.json } == response.json

View file

@ -21,22 +21,22 @@ world
) )
EXPECTED_TABLE_WITH_LABELS_CSV = """ EXPECTED_TABLE_WITH_LABELS_CSV = """
pk,created,planet_int,on_earth,state,city_id,city_id_label,neighborhood,tags,complex_array pk,created,planet_int,on_earth,state,city_id,city_id_label,neighborhood,tags,complex_array,distinct_some_null
1,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Mission,"[""tag1"", ""tag2""]","[{""foo"": ""bar""}]" 1,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Mission,"[""tag1"", ""tag2""]","[{""foo"": ""bar""}]",one
2,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Dogpatch,"[""tag1"", ""tag3""]",[] 2,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Dogpatch,"[""tag1"", ""tag3""]",[],two
3,2019-01-14 08:00:00,1,1,CA,1,San Francisco,SOMA,[],[] 3,2019-01-14 08:00:00,1,1,CA,1,San Francisco,SOMA,[],[],
4,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Tenderloin,[],[] 4,2019-01-14 08:00:00,1,1,CA,1,San Francisco,Tenderloin,[],[],
5,2019-01-15 08:00:00,1,1,CA,1,San Francisco,Bernal Heights,[],[] 5,2019-01-15 08:00:00,1,1,CA,1,San Francisco,Bernal Heights,[],[],
6,2019-01-15 08:00:00,1,1,CA,1,San Francisco,Hayes Valley,[],[] 6,2019-01-15 08:00:00,1,1,CA,1,San Francisco,Hayes Valley,[],[],
7,2019-01-15 08:00:00,1,1,CA,2,Los Angeles,Hollywood,[],[] 7,2019-01-15 08:00:00,1,1,CA,2,Los Angeles,Hollywood,[],[],
8,2019-01-15 08:00:00,1,1,CA,2,Los Angeles,Downtown,[],[] 8,2019-01-15 08:00:00,1,1,CA,2,Los Angeles,Downtown,[],[],
9,2019-01-16 08:00:00,1,1,CA,2,Los Angeles,Los Feliz,[],[] 9,2019-01-16 08:00:00,1,1,CA,2,Los Angeles,Los Feliz,[],[],
10,2019-01-16 08:00:00,1,1,CA,2,Los Angeles,Koreatown,[],[] 10,2019-01-16 08:00:00,1,1,CA,2,Los Angeles,Koreatown,[],[],
11,2019-01-16 08:00:00,1,1,MI,3,Detroit,Downtown,[],[] 11,2019-01-16 08:00:00,1,1,MI,3,Detroit,Downtown,[],[],
12,2019-01-17 08:00:00,1,1,MI,3,Detroit,Greektown,[],[] 12,2019-01-17 08:00:00,1,1,MI,3,Detroit,Greektown,[],[],
13,2019-01-17 08:00:00,1,1,MI,3,Detroit,Corktown,[],[] 13,2019-01-17 08:00:00,1,1,MI,3,Detroit,Corktown,[],[],
14,2019-01-17 08:00:00,1,1,MI,3,Detroit,Mexicantown,[],[] 14,2019-01-17 08:00:00,1,1,MI,3,Detroit,Mexicantown,[],[],
15,2019-01-17 08:00:00,2,0,MC,4,Memnonia,Arcadia Planitia,[],[] 15,2019-01-17 08:00:00,2,0,MC,4,Memnonia,Arcadia Planitia,[],[],
""".lstrip().replace( """.lstrip().replace(
"\n", "\r\n" "\n", "\r\n"
) )