Repository: alephdata/aleph
Issue: Improve dataset search

Currently, when you search for Syria, datasets with the keyword Syrian don't get returned. We should make searches a bit more fuzzy in this regard. Not sure how inclusive the search is, but it should take into account the metadata (summary, sources) as well. 

Changed files:
aleph/tests/test_collections_api.py, aleph/search/__init__.py

diff --git a/aleph/search/__init__.py b/aleph/search/__init__.py
index c415213e5..0f5c789f7 100644
--- a/aleph/search/__init__.py
+++ b/aleph/search/__init__.py
@@ -31,6 +31,30 @@ class CollectionsQuery(Query):
             filters.append({"ids": {"values": ids}})
         return filters
 
+    def get_text_query(self):
+        query = super().get_text_query()
+
+        # By default, queries use the Elasticsearch `query_string` query which considers only
+        # exact matches. Users expect the collection search to match variations of the same
+        # word by default (e.g. Russia/Russian, owner/owners, leas/leaked), without using explicit
+        # advanced query syntax to enable fuzzy matching.
+        # As the `query_string` query does not support enabling fuzzy matching by default, we add
+        # a second subquery to handle this. This allows users to still use the advanced query syntax
+        # in cases that aren’t covered by the default fuzziness (e.g. prefixes/wildcard searches).
+        if self.parser.text:
+            query.append(
+                {
+                    "multi_match": {
+                        "query": self.parser.text,
+                        "fields": ensure_list(self.TEXT_FIELDS),
+                        "operator": "AND",
+                        "fuzziness": "AUTO:3,4",
+                    }
+                }
+            )
+
+        return query
+
     def get_index(self):
         return collections_index()
 
diff --git a/aleph/tests/test_collections_api.py b/aleph/tests/test_collections_api.py
index 99030edf5..d102ee2cc 100644
--- a/aleph/tests/test_collections_api.py
+++ b/aleph/tests/test_collections_api.py
@@ -48,6 +48,29 @@ class CollectionsApiTestCase(TestCase):
         assert res.json["results"][0]["countries"] == ["us"], res.json
         assert validate(res.json["results"][0], "Collection")
 
+    def test_index_fuzzy_search(self):
+        _, headers = self.login(is_admin=True)
+
+        # Note the typo in "Colection"
+        res = self.client.get("/api/2/collections?q=Test Colection", headers=headers)
+
+        assert res.status_code == 200, res
+        assert res.json["total"] == 1, res.json
+        assert res.json["results"][0]["label"] == "Test Collection"
+
+    def test_index_advanced_search(self):
+        _, headers = self.login(is_admin=True)
+        self.col = self.create_collection(
+            label="OpenContracting",
+            category="procurement",
+        )
+
+        res = self.client.get("/api/2/collections?q=Open*", headers=headers)
+
+        assert res.status_code == 200, res
+        assert res.json["total"] == 1, res.json
+        assert res.json["results"][0]["label"] == "OpenContracting"
+
     def test_sitemap(self):
         res = self.client.get("/api/2/sitemap.xml")
         assert res.status_code == 200, res