Find match candidates

This commit is contained in:
Edward Betts 2021-05-12 16:55:40 +02:00
parent 95366a76dd
commit 5b13ca1595
2 changed files with 66 additions and 1 deletions

View file

@ -368,6 +368,11 @@ function mouse_events(marker, qid) {
var tag_or_key_list = response.data.tag_or_key_list;
var item_detail = build_item_detail(items[qid].wikidata, tag_or_key_list);
detail.innerHTML = item_detail;
var item_osm_candidates_url = `/api/1/item/${qid}/candidates`;
axios.get(item_osm_candidates_url).then((response) => {
console.log(response.data);
});
});
});

View file

@ -1,11 +1,12 @@
#!/usr/bin/python3
from flask import Flask, render_template, request, jsonify, redirect, url_for
from sqlalchemy import func
from sqlalchemy import func, or_
from sqlalchemy.orm import selectinload
from matcher import nominatim, model, database, commons, wikidata, wikidata_api
from collections import Counter
from time import time
from geoalchemy2 import Geography
import GeoIP
srid = 4326
@ -403,6 +404,65 @@ def api_get_item_tags(item_id):
return jsonify(success=True, qid=item.qid, tag_or_key_list=osm_list, duration=t1)
def get_tag_filter(item):
osm_list = get_item_tags(item)
tag_filter = []
for tag_or_key in osm_list:
if tag_or_key.startswith("Key:"):
tag_filter.append(model.Polygon.tags.has_key(tag_or_key[4:]))
if tag_or_key.startswith("Tag:"):
k, _, v = tag_or_key.partition("=")
tag_filter.append(model.Polygon.tags[k] == v)
return or_(*tag_filter)
def get_nearby(item, max_distance=100):
osm_objects = {}
distances = {}
tag_filter = get_tag_filter(item)
for loc in item.locations:
lat, lon = loc.get_lat_lon()
point = func.ST_SetSRID(func.ST_MakePoint(lon, lat), 4326)
dist = func.ST_Distance(point, model.Polygon.way.cast(Geography()))
q = (model.Polygon.query
.add_columns(dist.label('distance'))
.filter(dist < max_distance, tag_filter)
.order_by(point.distance_centroid(model.Polygon.way))
.limit(20))
for i, dist in q:
osm_objects.setdefault(i.identifier, i)
if i.identifier not in distances or dist < distances[i.identifier]:
distances[i.identifier] = dist
return [(osm_objects[identifier], dist)
for identifier, dist
in sorted(distances.items(), key=lambda i:i[1])]
@app.route("/api/1/item/Q<int:item_id>/candidates")
def api_find_osm_candidates(item_id):
t0 = time()
item = model.Item.query.get(item_id)
max_distance = 100
nearby = []
for osm, dist in get_nearby(item, max_distance):
cur = {
"identifier": osm.identifier,
"distance": dist,
"tags": osm.tags,
"area": osm.area,
"geojson": osm.geojson(),
}
nearby.append(cur)
t1 = time() - t0
return jsonify(success=True, qid=item.qid, nearby=nearby, duration=t1)
@app.route("/api/1/missing")
def api_missing_wikidata_items():
qids_arg = request.args.get("qids")