New ?tags__arraycontains=tag lookup against JSON fields

Part one of supporting facet-by-JSON-array, refs #359
This commit is contained in:
Simon Willison 2019-04-10 08:17:19 -07:00
commit 78e45ead4d
6 changed files with 74 additions and 41 deletions

View file

@ -523,26 +523,27 @@ CREATE TABLE facetable (
state text,
city_id integer,
neighborhood text,
tags text,
FOREIGN KEY ("city_id") REFERENCES [facet_cities](id)
);
INSERT INTO facetable
(planet_int, on_earth, state, city_id, neighborhood)
(planet_int, on_earth, state, city_id, neighborhood, tags)
VALUES
(1, 1, 'CA', 1, 'Mission'),
(1, 1, 'CA', 1, 'Dogpatch'),
(1, 1, 'CA', 1, 'SOMA'),
(1, 1, 'CA', 1, 'Tenderloin'),
(1, 1, 'CA', 1, 'Bernal Heights'),
(1, 1, 'CA', 1, 'Hayes Valley'),
(1, 1, 'CA', 2, 'Hollywood'),
(1, 1, 'CA', 2, 'Downtown'),
(1, 1, 'CA', 2, 'Los Feliz'),
(1, 1, 'CA', 2, 'Koreatown'),
(1, 1, 'MI', 3, 'Downtown'),
(1, 1, 'MI', 3, 'Greektown'),
(1, 1, 'MI', 3, 'Corktown'),
(1, 1, 'MI', 3, 'Mexicantown'),
(2, 0, 'MC', 4, 'Arcadia Planitia')
(1, 1, 'CA', 1, 'Mission', '["tag1", "tag2"]'),
(1, 1, 'CA', 1, 'Dogpatch', '["tag1", "tag3"]'),
(1, 1, 'CA', 1, 'SOMA', '[]'),
(1, 1, 'CA', 1, 'Tenderloin', '[]'),
(1, 1, 'CA', 1, 'Bernal Heights', '[]'),
(1, 1, 'CA', 1, 'Hayes Valley', '[]'),
(1, 1, 'CA', 2, 'Hollywood', '[]'),
(1, 1, 'CA', 2, 'Downtown', '[]'),
(1, 1, 'CA', 2, 'Los Feliz', '[]'),
(1, 1, 'CA', 2, 'Koreatown', '[]'),
(1, 1, 'MI', 3, 'Downtown', '[]'),
(1, 1, 'MI', 3, 'Greektown', '[]'),
(1, 1, 'MI', 3, 'Corktown', '[]'),
(1, 1, 'MI', 3, 'Mexicantown', '[]'),
(2, 0, 'MC', 4, 'Arcadia Planitia', '[]')
;
INSERT INTO simple_primary_key VALUES (1, 'hello');

View file

@ -1,3 +1,4 @@
from datasette.utils import detect_json1
from .fixtures import ( # noqa
app_client,
app_client_no_files,
@ -115,7 +116,7 @@ def test_database_page(app_client):
'hidden': False,
'primary_keys': ['id'],
}, {
'columns': ['pk', 'planet_int', 'on_earth', 'state', 'city_id', 'neighborhood'],
'columns': ['pk', 'planet_int', 'on_earth', 'state', 'city_id', 'neighborhood', 'tags'],
'name': 'facetable',
'count': 15,
'foreign_keys': {
@ -882,6 +883,18 @@ def test_table_filter_queries(app_client, path, expected_rows):
assert expected_rows == response.json['rows']
@pytest.mark.skipif(
not detect_json1(),
reason="Requires the SQLite json1 module"
)
def test_table_filter_json_arraycontains(app_client):
response = app_client.get("/fixtures/facetable.json?tags__arraycontains=tag1")
assert [
[1, 1, 1, 'CA', 1, 'Mission', '["tag1", "tag2"]'],
[2, 1, 1, 'CA', 1, 'Dogpatch', '["tag1", "tag3"]']
] == response.json['rows']
def test_max_returned_rows(app_client):
response = app_client.get(
'/fixtures.json?sql=select+content+from+no_primary_key'
@ -1244,7 +1257,8 @@ def test_expand_labels(app_client):
"value": 1,
"label": "San Francisco"
},
"neighborhood": "Dogpatch"
"neighborhood": "Dogpatch",
"tags": '["tag1", "tag3"]'
},
"13": {
"pk": 13,
@ -1255,7 +1269,8 @@ def test_expand_labels(app_client):
"value": 3,
"label": "Detroit"
},
"neighborhood": "Corktown"
"neighborhood": "Corktown",
"tags": '[]',
}
} == response.json

View file

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

View file

@ -187,7 +187,7 @@ def test_custom_json_encoder(obj, expected):
])
def test_build_where(args, expected_where, expected_params):
f = utils.Filters(sorted(args.items()))
sql_bits, actual_params = f.build_where_clauses()
sql_bits, actual_params = f.build_where_clauses("table")
assert expected_where == sql_bits
assert {
'p{}'.format(i): param