From b5ec746f7c6f07e42728890d6454fdde365bddd2 Mon Sep 17 00:00:00 2001 From: Jean-Pascal MILCENT Date: Thu, 2 May 2024 12:13:41 +0200 Subject: [PATCH] feat: improve municipalities search (unaccent, word part) Resolve #531. --- atlas/atlasAPI.py | 2 +- .../repositories/vmCommunesRepository.py | 149 +++++++++--------- data/update/update_1.6.1to1.6.2.sql | 5 + docs/changelog.rst | 15 ++ 4 files changed, 96 insertions(+), 75 deletions(-) diff --git a/atlas/atlasAPI.py b/atlas/atlasAPI.py index de661edc..aeb736a7 100644 --- a/atlas/atlasAPI.py +++ b/atlas/atlasAPI.py @@ -30,7 +30,7 @@ def searchCommuneAPI(): session = db.session search = request.args.get("search", "") limit = request.args.get("limit", 50) - results = vmCommunesRepository.getCommunesSearch(session, search, limit) + results = vmCommunesRepository.searchMunicipalities(session, search, limit) session.close() return jsonify(results) diff --git a/atlas/modeles/repositories/vmCommunesRepository.py b/atlas/modeles/repositories/vmCommunesRepository.py index bd5c8dcf..b1d781e3 100644 --- a/atlas/modeles/repositories/vmCommunesRepository.py +++ b/atlas/modeles/repositories/vmCommunesRepository.py @@ -1,74 +1,75 @@ -# -*- coding:utf-8 -*- - -import ast - -from flask import current_app -from sqlalchemy import distinct -from sqlalchemy.sql import text -from sqlalchemy.sql.expression import func - -from atlas.modeles.entities.vmCommunes import VmCommunes - - -def getAllCommunes(session): - req = session.query(distinct(VmCommunes.commune_maj), VmCommunes.insee).all() - communeList = list() - for r in req: - temp = {"label": r[0], "value": r[1]} - communeList.append(temp) - return communeList - - -def getCommunesSearch(session, search, limit=50): - req = session.query( - distinct(VmCommunes.commune_maj), VmCommunes.insee, func.length(VmCommunes.commune_maj) - ).filter(VmCommunes.commune_maj.ilike("%" + search + "%")) - - req = req.order_by(VmCommunes.commune_maj) - - req = req.limit(limit).all() - - communeList = list() - for r in req: - temp = {"label": r[0], "value": r[1]} - communeList.append(temp) - return communeList - - -def getCommuneFromInsee(connection, insee): - sql = """ - SELECT c.commune_maj, - c.insee, - c.commune_geojson - FROM atlas.vm_communes c - WHERE c.insee = :thisInsee - """ - req = connection.execute(text(sql), thisInsee=insee) - communeObj = dict() - for r in req: - communeObj = { - "areaName": r.commune_maj, - "areaCode": str(r.insee), - "areaGeoJson": ast.literal_eval(r.commune_geojson), - } - return communeObj - - -def getCommunesObservationsChilds(connection, cd_ref): - sql = """ - SELECT DISTINCT (com.insee) AS insee, com.commune_maj - FROM atlas.vm_communes com - JOIN atlas.vm_observations obs - ON obs.insee = com.insee - WHERE obs.cd_ref IN ( - SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) - ) - OR obs.cd_ref = :thiscdref - ORDER BY com.commune_maj ASC - """ - req = connection.execute(text(sql), thiscdref=cd_ref) - listCommunes = list() - for r in req: - temp = {"insee": r.insee, "commune_maj": r.commune_maj} - listCommunes.append(temp) - return listCommunes +# -*- coding:utf-8 -*- + +import ast + +from sqlalchemy import distinct +from sqlalchemy.sql import text +from sqlalchemy.sql.expression import func + +from atlas.modeles.entities.vmCommunes import VmCommunes + + +def getAllCommunes(session): + req = session.query(distinct(VmCommunes.commune_maj), VmCommunes.insee).all() + communeList = list() + for r in req: + temp = {"label": r[0], "value": r[1]} + communeList.append(temp) + return communeList + + +def searchMunicipalities(session, search, limit=50): + like_search = "%" + search.replace(" ", "%") + "%" + + query = ( + session.query( + distinct(VmCommunes.commune_maj), + VmCommunes.insee, + func.length(VmCommunes.commune_maj), + ) + .filter(func.unaccent(VmCommunes.commune_maj).ilike(func.unaccent(like_search))) + .order_by(VmCommunes.commune_maj) + .limit(limit) + ) + results = query.all() + + return [{"label": r[0], "value": r[1]} for r in results] + + +def getCommuneFromInsee(connection, insee): + sql = """ + SELECT c.commune_maj, + c.insee, + c.commune_geojson + FROM atlas.vm_communes c + WHERE c.insee = :thisInsee + """ + req = connection.execute(text(sql), thisInsee=insee) + communeObj = dict() + for r in req: + communeObj = { + "areaName": r.commune_maj, + "areaCode": str(r.insee), + "areaGeoJson": ast.literal_eval(r.commune_geojson), + } + return communeObj + + +def getCommunesObservationsChilds(connection, cd_ref): + sql = """ + SELECT DISTINCT (com.insee) AS insee, com.commune_maj + FROM atlas.vm_communes com + JOIN atlas.vm_observations obs + ON obs.insee = com.insee + WHERE obs.cd_ref IN ( + SELECT * FROM atlas.find_all_taxons_childs(:thiscdref) + ) + OR obs.cd_ref = :thiscdref + ORDER BY com.commune_maj ASC + """ + req = connection.execute(text(sql), thiscdref=cd_ref) + listCommunes = list() + for r in req: + temp = {"insee": r.insee, "commune_maj": r.commune_maj} + listCommunes.append(temp) + return listCommunes diff --git a/data/update/update_1.6.1to1.6.2.sql b/data/update/update_1.6.1to1.6.2.sql index 8841c952..c2a20a1e 100644 --- a/data/update/update_1.6.1to1.6.2.sql +++ b/data/update/update_1.6.1to1.6.2.sql @@ -43,3 +43,8 @@ CREATE INDEX ON atlas.vm_observations_mailles CREATE INDEX ON atlas.vm_observations_mailles USING btree (id_maille, cd_ref); + + +-- ISSUE #531 & #532 +CREATE EXTENSION IF NOT EXISTS unaccent SCHEMA "public"; + diff --git a/docs/changelog.rst b/docs/changelog.rst index 2709dccf..66b57b61 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -2,6 +2,21 @@ CHANGELOG ========= +[Unreleased] +------------------ + +🐛 **Optimisations** + +- AmĂ©lioration de la "recherche par commune": mots tronquĂ©s, sans accent (#531 par @jpm-cbna) + + +⚠ **Notes de version** + +Si vous mettez Ă  jour GeoNature-atlas : + +- ExĂ©cutez le script SQL de mise Ă  jour de la BDD : https://github.com/PnX-SI/GeoNature-atlas/blob/master/data/update/update_1.6.1to1.6.2.sql + + 1.6.1 (2023-10-16) ------------------