feat: Migrate Street and Task models from MongoDB to CouchDB

- Replace Street model with CouchDB-based implementation
- Replace Task model with CouchDB-based implementation
- Update routes to use new model interfaces
- Handle geospatial queries with CouchDB design documents
- Maintain adoption functionality and middleware
- Use denormalized document structure with embedded data
- Update test files to work with new models
- Ensure API compatibility while using CouchDB underneath

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
This commit is contained in:
William Valentin
2025-11-01 13:12:34 -07:00
parent 2961107136
commit 7c7bc954ef
14 changed files with 1943 additions and 928 deletions

View File

@@ -123,14 +123,31 @@ class CouchDBService {
},
indexes: {
"streets-by-location": {
index: { fields: ["type", "location"] },
index: {
fields: ["type", "location"],
partial_filter_selector: { "type": "street" }
},
name: "streets-by-location",
type: "json"
},
"streets-by-status": {
index: { fields: ["type", "status"] },
index: {
fields: ["type", "status"],
partial_filter_selector: { "type": "street" }
},
name: "streets-by-status",
type: "json"
},
"streets-geo": {
index: {
fields: ["type", "location"],
partial_filter_selector: {
"type": "street",
"location": { "$exists": true }
}
},
name: "streets-geo",
type: "json"
}
}
},
@@ -729,15 +746,37 @@ class CouchDBService {
// Street-specific operations
async findStreetsByLocation(bounds) {
return this.find({
type: 'street',
status: 'available',
location: {
$geoWithin: {
$box: bounds
try {
// For CouchDB, we need to handle geospatial queries differently
// We'll use a bounding box approach with the geo index
const [sw, ne] = bounds;
const query = {
selector: {
type: 'street',
status: 'available',
location: {
$exists: true
}
},
limit: 1000 // Reasonable limit for geographic queries
};
const streets = await this.find(query);
// Filter by bounding box manually (since CouchDB doesn't support $geoWithin in Mango)
return streets.filter(street => {
if (!street.location || !street.location.coordinates) {
return false;
}
}
});
const [lng, lat] = street.location.coordinates;
return lng >= sw[0] && lng <= ne[0] && lat >= sw[1] && lat <= ne[1];
});
} catch (error) {
console.error("Error finding streets by location:", error.message);
throw error;
}
}
async adoptStreet(userId, streetId) {