admin_boundary_service.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from sqlalchemy.orm import Session
  2. from sqlalchemy.sql import text
  3. import json
  4. def get_boundary_geojson_by_name(db: Session, name: str, level: str = "auto") -> dict:
  5. """根据名称获取边界GeoJSON Feature
  6. Args:
  7. db (Session): 数据库会话
  8. name (str): 名称(县/市/省)
  9. level (str): 层级,可选 "county"|"city"|"province"|"auto"
  10. Returns:
  11. dict: GeoJSON Feature 对象
  12. """
  13. # county 精确匹配
  14. if level in ("county", "auto"):
  15. r = db.execute(text(
  16. """
  17. SELECT ST_AsGeoJSON(geometry) AS g, name, city_name, province_name
  18. FROM counties WHERE name=:n LIMIT 1
  19. """
  20. ), {"n": name}).fetchone()
  21. if r and r.g:
  22. return {
  23. "type": "Feature",
  24. "properties": {
  25. "level": "county",
  26. "name": r.name,
  27. "city": r.city_name,
  28. "province": r.province_name,
  29. },
  30. "geometry": json.loads(r.g)
  31. }
  32. # city 直接查询或从counties聚合
  33. if level in ("city", "auto"):
  34. # 优先从cities表直接查询
  35. r = db.execute(text(
  36. """
  37. SELECT ST_AsGeoJSON(geometry) AS g, name, province_name
  38. FROM cities WHERE name=:n LIMIT 1
  39. """
  40. ), {"n": name}).fetchone()
  41. if r and r.g:
  42. return {
  43. "type": "Feature",
  44. "properties": {
  45. "level": "city",
  46. "name": r.name,
  47. "province": r.province_name
  48. },
  49. "geometry": json.loads(r.g)
  50. }
  51. # 如果cities表没有,从counties表聚合
  52. r = db.execute(text(
  53. """
  54. SELECT ST_AsGeoJSON(ST_UnaryUnion(ST_Union(geometry))) AS g,
  55. MIN(province_name) AS province_name
  56. FROM counties WHERE city_name=:n
  57. """
  58. ), {"n": name}).fetchone()
  59. if r and r.g:
  60. return {
  61. "type": "Feature",
  62. "properties": {
  63. "level": "city",
  64. "name": name,
  65. "province": r.province_name
  66. },
  67. "geometry": json.loads(r.g)
  68. }
  69. # province 直接查询或从counties聚合
  70. if level in ("province", "auto"):
  71. # 优先从provinces表直接查询
  72. r = db.execute(text(
  73. """
  74. SELECT ST_AsGeoJSON(geometry) AS g, name
  75. FROM provinces WHERE name=:n LIMIT 1
  76. """
  77. ), {"n": name}).fetchone()
  78. if r and r.g:
  79. return {
  80. "type": "Feature",
  81. "properties": {
  82. "level": "province",
  83. "name": r.name
  84. },
  85. "geometry": json.loads(r.g)
  86. }
  87. # 如果provinces表没有,从counties表聚合
  88. r = db.execute(text(
  89. """
  90. SELECT ST_AsGeoJSON(ST_UnaryUnion(ST_Union(geometry))) AS g
  91. FROM counties WHERE province_name=:n
  92. """
  93. ), {"n": name}).fetchone()
  94. if r and r.g:
  95. return {
  96. "type": "Feature",
  97. "properties": {
  98. "level": "province",
  99. "name": name
  100. },
  101. "geometry": json.loads(r.g)
  102. }
  103. raise ValueError(f"未找到名称: {name}")