add center and radius params

This commit is contained in:
Matteo Rosati
2026-01-18 11:41:55 +01:00
parent 6cd8997516
commit de53b760c4
2 changed files with 177 additions and 11 deletions

View File

@@ -401,6 +401,81 @@ curl "http://localhost:7000/plexts?min_timestamp=2026-01-12T10:00:00Z&max_timest
curl "http://localhost:7000/plexts?event_types=PORTAL_CAPTURED&player_name=Albicocca&min_timestamp=2026-01-12T10:00:00Z" curl "http://localhost:7000/plexts?event_types=PORTAL_CAPTURED&player_name=Albicocca&min_timestamp=2026-01-12T10:00:00Z"
``` ```
##### GET /plexts/from-db
Get plexts from MongoDB with optional filters. Returns plexts sorted by timestamp (most recent first).
**Query Parameters:**
| Parameter | Type | Default | Description |
| --------------- | ------- | -------- | --------------------------------------------------- |
| `player_name` | String | None | Player name to filter by |
| `timestamp_from` | Integer | None | Minimum timestamp in milliseconds (optional) |
| `timestamp_to` | Integer | None | Maximum timestamp in milliseconds (optional) |
| `limit` | Integer | 100 | Maximum number of results to return |
| `center` | String | None | Geographic center point in format "latitude,longitude" (optional, requires radius) |
| `radius` | Integer | None | Search radius in meters (optional, requires center) |
**Geospatial Query:**
When both `center` and `radius` parameters are provided, the endpoint returns plexts within the specified radius from the center point. The response includes a `distance` field (in meters) for each result.
**Response with geospatial query:**
```json
{
"count": 5,
"plexts": [
{
"id": "abc123",
"timestamp": 1736659207000,
"timestamp_formatted": "2026-01-12 11:00:07",
"text": "Albicocca captured L' Arboreto",
"team": "RESISTANCE",
"plext_type": "PLAYER_GENERATED",
"categories": 0,
"event_type": "PORTAL_CAPTURED",
"player_name": "Albicocca",
"portal_name": "L' Arboreto",
"coordinates": {
"type": "Point",
"coordinates": [12.365208, 45.573661]
},
"distance": 125.5,
"markup": [...]
}
]
}
```
**Note:** Both `center` and `radius` parameters must be provided together. If neither is provided, the endpoint returns all plexts matching other filters without geospatial filtering.
**Examples:**
```bash
# Get all plexts from MongoDB
curl "http://localhost:7000/plexts/from-db"
# Filter by player name
curl "http://localhost:7000/plexts/from-db?player_name=Albicocca"
# Filter by time range
curl "http://localhost:7000/plexts/from-db?timestamp_from=17366592000000&timestamp_to=1736745600000"
# Geospatial query: Get plexts within 1km of a specific location
curl "http://localhost:7000/plexts/from-db?center=45.573661,12.365208&radius=1000"
# Geospatial query with player filter
curl "http://localhost:7000/plexts/from-db?center=45.573661,12.365208&radius=1000&player_name=Albicocca"
# Geospatial query with time filter
curl "http://localhost:7000/plexts/from-db?center=45.573661,12.365208&radius=1000&timestamp_from=17366592000000"
# Combine all filters
curl "http://localhost:7000/plexts/from-db?center=45.573661,12.365208&radius=1000&player_name=Albicocca&timestamp_from=17366592000000&limit=10"
```
**Authentication:** Basic Auth required
### Scheduler ### Scheduler
The scheduler automatically collects Ingress events every minute and stores them in MongoDB. The scheduler automatically collects Ingress events every minute and stores them in MongoDB.

95
app.py
View File

@@ -32,9 +32,12 @@ def get_plexts_from_db():
timestamp_from: Minimum timestamp in milliseconds (optional) timestamp_from: Minimum timestamp in milliseconds (optional)
timestamp_to: Maximum timestamp in milliseconds (optional) timestamp_to: Maximum timestamp in milliseconds (optional)
limit: Maximum number of results to return (optional, default: 100) limit: Maximum number of results to return (optional, default: 100)
center: Geographic center point in format "latitude,longitude" (optional, requires radius)
radius: Search radius in meters (optional, requires center)
Returns: Returns:
JSON response with list of plexts (without _id field), limited by the limit parameter JSON response with list of plexts (without _id field), limited by the limit parameter.
When using geospatial query (center and radius), includes a 'distance' field in meters.
""" """
try: try:
# Parse query parameters # Parse query parameters
@@ -42,6 +45,8 @@ def get_plexts_from_db():
timestamp_from = request.args.get("timestamp_from") timestamp_from = request.args.get("timestamp_from")
timestamp_to = request.args.get("timestamp_to") timestamp_to = request.args.get("timestamp_to")
limit_param = request.args.get("limit") limit_param = request.args.get("limit")
center = request.args.get("center")
radius = request.args.get("radius")
# Validate and convert timestamp parameters to integers if provided # Validate and convert timestamp parameters to integers if provided
if timestamp_from is not None: if timestamp_from is not None:
@@ -67,6 +72,44 @@ def get_plexts_from_db():
else: else:
limit = 100 limit = 100
# Validate geospatial parameters
# Both center and radius must be provided together, or neither
if (center is not None) != (radius is not None):
return jsonify({
"error": "Both 'center' and 'radius' parameters must be provided together"
}), 400
# Parse and validate center parameter if provided
center_coords = None
if center is not None:
try:
# Parse center in format "latitude,longitude"
lat_str, lng_str = center.split(',')
lat = float(lat_str)
lng = float(lng_str)
# Validate latitude and longitude ranges
if not (-90 <= lat <= 90):
return jsonify({"error": "Latitude must be between -90 and 90"}), 400
if not (-180 <= lng <= 180):
return jsonify({"error": "Longitude must be between -180 and 180"}), 400
center_coords = (lat, lng)
except ValueError:
return jsonify({
"error": "Invalid center format. Use format: 'latitude,longitude' (e.g., '45.573661,12.365208')"
}), 400
# Parse and validate radius parameter if provided
radius_meters = None
if radius is not None:
try:
radius_meters = int(radius)
if radius_meters <= 0:
return jsonify({"error": "Radius must be a positive integer"}), 400
except ValueError:
return jsonify({"error": "Radius must be an integer"}), 400
# Build MongoDB filter query # Build MongoDB filter query
filter_query = {} filter_query = {}
@@ -91,7 +134,48 @@ def get_plexts_from_db():
collection = db[collection_name] collection = db[collection_name]
try: try:
# Projection to exclude _id field # Ensure geospatial index exists
try:
collection.create_index([("coordinates", "2dsphere")], background=True)
except PyMongoError as e:
logger.warning(f"Could not create geospatial index: {e}")
# Execute query based on whether geospatial parameters are provided
if center_coords and radius_meters:
# Use $geoNear aggregation for geospatial query
lat, lng = center_coords
pipeline = [
{
"$geoNear": {
"near": {
"type": "Point",
"coordinates": [lng, lat] # GeoJSON uses [longitude, latitude]
},
"distanceField": "distance", # Add distance to results
"maxDistance": radius_meters, # in meters
"spherical": True # Use spherical geometry
}
},
{
"$match": filter_query # Apply other filters
},
{
"$sort": {"timestamp": -1} # Sort by timestamp (most recent first)
},
{
"$limit": limit
},
{
"$project": {
"_id": 0 # Exclude _id field
}
}
]
# Execute aggregation pipeline
plexts = list(collection.aggregate(pipeline))
else:
# Use standard find() query for non-geospatial queries
projection = {"_id": 0} projection = {"_id": 0}
# Execute query with sorting (timestamp DESC - most recent first) and dynamic limit # Execute query with sorting (timestamp DESC - most recent first) and dynamic limit
@@ -237,8 +321,15 @@ def index():
"timestamp_from": "Minimum timestamp in milliseconds (optional)", "timestamp_from": "Minimum timestamp in milliseconds (optional)",
"timestamp_to": "Maximum timestamp in milliseconds (optional)", "timestamp_to": "Maximum timestamp in milliseconds (optional)",
"limit": "Maximum number of results to return (optional, default: 100)", "limit": "Maximum number of results to return (optional, default: 100)",
"center": "Geographic center point in format 'latitude,longitude' (optional, requires radius)",
"radius": "Search radius in meters (optional, requires center)",
}, },
"authentication": "Basic Auth required", "authentication": "Basic Auth required",
"geospatial_query": {
"description": "When both center and radius are provided, returns plexts within the specified radius from the center point. If neither is provided, returns all plexts matching other filters.",
"example": "center=45.573661,12.365208&radius=1000",
"response_field": "distance (meters) - included in results when using geospatial query",
},
}, },
}, },
} }