diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index c6973d06..8e33b877 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -1443,6 +1443,7 @@ _table_config_keys = ( "fts_table", "fts_pk", "searchmode", + "suggest_facets", ) diff --git a/datasette/views/table.py b/datasette/views/table.py index 594e925e..ef2125f2 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -1378,7 +1378,9 @@ async def table_view_data( suggested_facets = [] # Calculate suggested facets if ( - datasette.setting("suggest_facets") + table_metadata.get( + "suggest_facets", datasette.setting("suggest_facets") + ) and datasette.setting("allow_facet") and not _next and not nofacet diff --git a/docs/facets.rst b/docs/facets.rst index 15fe7227..a838aa7b 100644 --- a/docs/facets.rst +++ b/docs/facets.rst @@ -254,6 +254,55 @@ For the currently filtered data are there any columns which, if applied as a fac That last point is particularly important: Datasette runs a query for every column that is displayed on a page, which could get expensive - so to avoid slow load times it sets a time limit of just 50ms for each of those queries. This means suggested facets are unlikely to appear for tables with millions of records in them. +You can turn off suggested facets for a specific table by setting ``"suggest_facets"`` to ``false`` in the table's configuration: + +.. [[[cog + from metadata_doc import metadata_example + metadata_example(cog, { + "databases": { + "mydb": { + "tables": { + "big_table": { + "suggest_facets": False + } + } + } + } + }) +.. ]]] + +.. tab:: metadata.yaml + + .. code-block:: yaml + + databases: + mydb: + tables: + big_table: + suggest_facets: false + + +.. tab:: metadata.json + + .. code-block:: json + + { + "databases": { + "mydb": { + "tables": { + "big_table": { + "suggest_facets": false + } + } + } + } + } +.. [[[end]]] + +This will disable suggested facets for that table only. Other tables in the same database will continue to suggest facets as normal. Explicitly requested facets (using ``?_facet=column``) will still work. + +You can also disable suggested facets for the entire Datasette instance using the :ref:`setting_suggest_facets` setting. + Speeding up facets with indexes ------------------------------- diff --git a/tests/test_table_api.py b/tests/test_table_api.py index 51e40ad1..5b0301c7 100644 --- a/tests/test_table_api.py +++ b/tests/test_table_api.py @@ -1002,6 +1002,39 @@ def test_suggest_facets_off(): ) +def test_suggest_facets_off_per_table(): + with make_app_client( + metadata={ + "databases": { + "fixtures": { + "tables": { + "facetable": {"suggest_facets": False}, + } + } + } + } + ) as client: + # suggested_facets should be [] for the table with suggest_facets: false + assert ( + [] + == client.get("/fixtures/facetable.json?_extra=suggested_facets").json[ + "suggested_facets" + ] + ) + # But other tables should still get suggestions + other = client.get( + "/fixtures/simple_primary_key.json?_extra=suggested_facets" + ).json["suggested_facets"] + # simple_primary_key has a 'content' column that can be faceted + assert isinstance(other, list) + # Explicit facets should still work even when suggestions are off + response = client.get( + "/fixtures/facetable.json?_facet=state&_extra=suggested_facets" + ) + assert response.json["suggested_facets"] == [] + assert response.json["facet_results"]["results"] != {} + + @pytest.mark.asyncio @pytest.mark.parametrize("nofacet", (True, False)) async def test_nofacet(ds_client, nofacet):