adresses API: add limit param

This commit is contained in:
Johan Le Baut 2022-01-28 15:42:08 +01:00
parent 768418258e
commit 46aeaf7da4
3 changed files with 51 additions and 29 deletions

View file

@ -28,28 +28,38 @@ class AddressFinder:
self.dbPath = db_addresses_sqlite_path self.dbPath = db_addresses_sqlite_path
print("DB addresses Path : " + self.dbPath) print("DB addresses Path : " + self.dbPath)
def getCommunesFromNameOrZip(self, communeNameOrZip: str) -> list[Commune]: def getCommunesFromNameOrZip(self, communeNameOrZip: str, limit: int = None) -> list[Commune]:
con = sqlite3.connect(self.dbPath) con = sqlite3.connect(self.dbPath)
con.row_factory = sqlite3.Row con.row_factory = sqlite3.Row
cur = con.cursor() cur = con.cursor()
communes: list[Commune] = []
# Check if a search limit is specified, make sure it is an integer
select_limit = ""
if limit is not None:
try:
select_limit = f"LIMIT {int(limit)}"
except ValueError:
print("Error, limit arg not a valid int: ", limit)
try: try:
# If no search parameter, select all
if communeNameOrZip is None: if communeNameOrZip is None:
cur.execute(f"SELECT * from \"{DB_TABLE_INSEE_NAME}\"") cur.execute(
f"SELECT * from \"{DB_TABLE_INSEE_NAME}\" {select_limit}")
else: else:
communeSearch = communeNameOrZip communeSearch = communeNameOrZip
zipSearch = communeNameOrZip zipSearch = communeNameOrZip
searchOpertor = "OR" searchOpertor = "OR"
regexCommuneAndZip = r"[0-9]{5} .+" # For example: '33000 BO' # Allow search zip and commune at the same time, in the format "29530 PLO"
regexCommuneAndZip = r"[0-9]{5} .+"
if re.match(regexCommuneAndZip, communeNameOrZip): if re.match(regexCommuneAndZip, communeNameOrZip):
splitSearch = communeNameOrZip.split(' ') splitSearch = communeNameOrZip.split(' ')
zipSearch = splitSearch[0] zipSearch = splitSearch[0]
communeSearch = ' '.join(splitSearch[1:]) communeSearch = ' '.join(splitSearch[1:])
searchOpertor = "AND" searchOpertor = "AND"
cur.execute( cur.execute(
f"SELECT * from \"{DB_TABLE_INSEE_NAME}\" WHERE {DB_COL_COMMUNE_NAME} LIKE \"%{communeSearch}%\" COLLATE nocase {searchOpertor} {DB_COL_COMMUNE_POSTE} LIKE \"{zipSearch}%\"") f"SELECT * from \"{DB_TABLE_INSEE_NAME}\" WHERE {DB_COL_COMMUNE_NAME} LIKE \"%{communeSearch}%\" COLLATE nocase {searchOpertor} {DB_COL_COMMUNE_POSTE} LIKE \"{zipSearch}%\" {select_limit}")
except sqlite3.OperationalError as err: except sqlite3.OperationalError as err:
print("Error querying DB : {0}".format(err), file=sys.stderr) print("Error querying DB : {0}".format(err), file=sys.stderr)
return [] return []
@ -61,13 +71,13 @@ class AddressFinder:
codeInsee=row_obj[DB_COL_COMMUNE_INSEE], codeInsee=row_obj[DB_COL_COMMUNE_INSEE],
nom=row_obj[DB_COL_COMMUNE_NAME], nom=row_obj[DB_COL_COMMUNE_NAME],
codeZip=row_obj[DB_COL_COMMUNE_POSTE]) codeZip=row_obj[DB_COL_COMMUNE_POSTE])
# This way we avoid duplicates # This way we avoid duplicates in DB
communesMap[commune["codeInsee"]] = commune communesMap[commune["codeInsee"]] = commune
con.close() con.close()
return list(communesMap.values()) return list(communesMap.values())
def getCommuneFantoirVoies(self, communeInseeCode: str, voieSearch: str = None) -> list[FantoirVoie]: def getCommuneFantoirVoies(self, communeInseeCode: str, voieSearch: str = None, limit: int = None) -> list[FantoirVoie]:
# Extract data from DB # Extract data from DB
con = sqlite3.connect(self.dbPath) con = sqlite3.connect(self.dbPath)
@ -84,6 +94,13 @@ class AddressFinder:
# Get JSON payload # Get JSON payload
# Check if a search limit is specified, make sure it is an integer
if limit is not None:
try:
limit = int(limit)
except ValueError:
print("Error, limit arg not a valid int: ", limit)
fantoir_dict = [] fantoir_dict = []
# Check if data where found # Check if data where found
if data_raw is not None: if data_raw is not None:
@ -92,19 +109,28 @@ class AddressFinder:
data_dict = json.loads(data.get("value")) data_dict = json.loads(data.get("value"))
# In extracted JSON data, the interesting payload is behind "value" key # In extracted JSON data, the interesting payload is behind "value" key
fantoir_dict = data_dict.get("value") fantoir_dict = data_dict.get("value")
# Apply search filter if any
if voieSearch is not None: if voieSearch is not None:
# Can match multiple words, for example "avenue noe" matches "avenue de noes"
regexSearch = r".*" regexSearch = r".*"
for expr in voieSearch.split(' '): for expr in voieSearch.split(' '):
regexSearch += r"(?=" + expr + r").*" regexSearch += r"(?=" + expr + r").*"
regexSearch += r".*" regexSearch += r".*"
fantoir_voies_filtered = [] fantoir_voies_filtered = []
nb_match = 0
for voie in fantoir_dict: for voie in fantoir_dict:
for libelle in voie['libelle']: for libelle in voie['libelle']:
if re.search(regexSearch, libelle, re.IGNORECASE): if re.search(regexSearch, libelle, re.IGNORECASE):
fantoir_voies_filtered.append(voie) fantoir_voies_filtered.append(voie)
nb_match += 1
break break
fantoir_dict = fantoir_voies_filtered if limit is not None and nb_match >= limit:
break
fantoir_dict = fantoir_voies_filtered
else:
# Apply search limit if any
fantoir_dict = fantoir_dict[:limit]
else: else:
print("Did not found any data matching Insee code " + print("Did not found any data matching Insee code " +
str(communeInseeCode)) str(communeInseeCode))

View file

@ -85,9 +85,9 @@
var voies=[] var voies=[]
var voie="" var voie=""
function fillCommunes(search='') { function fillCommunes(search='') {
var api="addresses/communes"; var api="addresses/communes?limit=15";
if (search != '') { if (search != '') {
api+="?s="+search; api+="&s="+search;
} }
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
@ -97,13 +97,10 @@
if (JSON.stringify(data) !== JSON.stringify(communes)){ if (JSON.stringify(data) !== JSON.stringify(communes)){
$("#communes").empty(); $("#communes").empty();
communes=data communes=data
for (let i = 0; i < 20; i++) { communes.forEach(commune => {
if (! communes[i]) { $("#communes").append("<option codeInsee=" + commune.codeInsee + " value='" +
break; commune.codeZip + ' ' + commune.nom + "'></option>");
} });
$("#communes").append("<option codeInsee=" + communes[i].codeInsee + " value='" +
communes[i].codeZip + ' ' + communes[i].nom + "'></option>");
}
} }
if (communes.length == 1) { if (communes.length == 1) {
codeInsee=communes[0].codeInsee; codeInsee=communes[0].codeInsee;
@ -119,9 +116,9 @@
var voies=[] var voies=[]
function fillVoies(codeInsee,search='') { function fillVoies(codeInsee,search='') {
var api="addresses/fantoirvoies/" + codeInsee; var api="addresses/fantoirvoies/" + codeInsee + '?limit=15';
if (search != '') { if (search != '') {
api+="?s="+search; api+="&s="+search;
} }
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
@ -131,13 +128,10 @@
if (JSON.stringify(data) !== JSON.stringify(voies)){ if (JSON.stringify(data) !== JSON.stringify(voies)){
$("#voies").empty(); $("#voies").empty();
voies=data voies=data
for (let i = 0; i < 20; i++) { voies.forEach(voie => {
if (! voies[i]) { $("#voies").append("<option id=" + voie.id + " value='" +
break; voie.libelle[0] + "'></option>");
} });
$("#voies").append("<option id=" + voies[i].id + " value='" +
voies[i].libelle[0] + "'></option>");
}
if (voies.length == 1) { if (voies.length == 1) {
$('#btnTestAdresse').collapse('show'); $('#btnTestAdresse').collapse('show');
voie=voies[0].libelle[0] voie=voies[0].libelle[0]

View file

@ -33,7 +33,8 @@ def get_form():
@app.route("/addresses/communes", methods=['GET']) @app.route("/addresses/communes", methods=['GET'])
def get_communes(): def get_communes():
to_search=request.args.get('s') to_search=request.args.get('s')
communes=addressFinder.getCommunesFromNameOrZip(to_search) limit=request.args.get('limit')
communes=addressFinder.getCommunesFromNameOrZip(to_search,limit)
response = app.response_class( response = app.response_class(
response=json.dumps(communes), response=json.dumps(communes),
mimetype='application/json' mimetype='application/json'
@ -43,7 +44,8 @@ def get_communes():
@app.route("/addresses/fantoirvoies/<codeInsee>", methods=['GET']) @app.route("/addresses/fantoirvoies/<codeInsee>", methods=['GET'])
def get_fantoir_voies(codeInsee): def get_fantoir_voies(codeInsee):
to_search=request.args.get('s') to_search=request.args.get('s')
fantoirVoies=addressFinder.getCommuneFantoirVoies(codeInsee,to_search) limit=request.args.get('limit')
fantoirVoies=addressFinder.getCommuneFantoirVoies(codeInsee,to_search,limit)
response = app.response_class( response = app.response_class(
response=json.dumps(fantoirVoies), response=json.dumps(fantoirVoies),
mimetype='application/json' mimetype='application/json'