1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-11-27 22:38:10 +02:00

Add parser and stringfyer for coordinate based distance search #1012

This commit is contained in:
Patrik J. Braun
2025-08-01 20:00:59 +02:00
parent 3b621d834a
commit 790b28715e
2 changed files with 145 additions and 19 deletions

View File

@@ -340,13 +340,38 @@ export class SearchQueryParser {
) {
from = from.slice(1, from.length - 1);
}
// Check if the from part matches coordinate pattern (number, number)
const coordMatch = from.match(/^\s*(-?\d+\.?\d*)\s*,\s*(-?\d+\.?\d*)\s*$/);
if (coordMatch) {
// It's a coordinate pair
const latitude = parseFloat(coordMatch[1]);
const longitude = parseFloat(coordMatch[2]);
return {
type: SearchQueryTypes.distance,
distance: intFromRegexp(str),
from: {
GPSData: {
latitude,
longitude
}
},
// only add negate if the value is true
...(new RegExp('^\\d*-' + this.keywords.kmFrom + '!:').test(str) && {
negate: true,
}),
} as DistanceSearch;
}
// If not coordinates, treat as location text
return {
type: SearchQueryTypes.distance,
distance: intFromRegexp(str),
from: {text: from},
// only add negate if the value is true
...(new RegExp('^\\d*-' + this.keywords.kmFrom + '!:').test(str) && {
negate: true,
}), // only add if the value is true
}),
} as DistanceSearch;
}
@@ -557,25 +582,28 @@ export class SearchQueryParser {
? ''
: (query as RangeSearch).value)
);
case SearchQueryTypes.distance:
if ((query as DistanceSearch).from.text.indexOf(' ') !== -1) {
return (
(query as DistanceSearch).distance +
'-' +
this.keywords.kmFrom +
colon +
'(' +
(query as DistanceSearch).from.text +
')'
);
case SearchQueryTypes.distance: {
const distanceQuery = query as DistanceSearch;
const text = distanceQuery.from.text;
const coords = distanceQuery.from.GPSData;
let locationStr = '';
if (text) {
// If we have location text, use that
locationStr = text;
} else if (coords && coords.latitude != null && coords.longitude != null) {
// If we only have coordinates, use them
locationStr = `${coords.latitude.toFixed(6)}, ${coords.longitude.toFixed(6)}`;
}
return (
(query as DistanceSearch).distance +
'-' +
this.keywords.kmFrom +
colon +
(query as DistanceSearch).from.text
);
// Add brackets if the location string contains spaces
if (locationStr.indexOf(' ') !== -1) {
locationStr = `(${locationStr})`;
}
return `${distanceQuery.distance}-${this.keywords.kmFrom}${colon}${locationStr}`;
}
case SearchQueryTypes.orientation:
return (
this.keywords.orientation +

View File

@@ -112,8 +112,106 @@ describe('SearchQueryParser', () => {
check({type: SearchQueryTypes.max_resolution, value: 5, negate: true} as MaxResolutionSearch);
});
it('Distance search', () => {
// Test location-based distance search
check({type: SearchQueryTypes.distance, distance: 10, from: {text: 'New York'}} as DistanceSearch);
check({type: SearchQueryTypes.distance, distance: 10, from: {text: 'New York'}, negate: true} as DistanceSearch);
// Test coordinate-based distance search
check({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
}
} as DistanceSearch);
// Test coordinate-based distance search with negation
check({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
},
negate: true
} as DistanceSearch);
// Test parsing specific coordinate formats
const parser = new SearchQueryParser(defaultQueryKeywords);
// Test basic coordinate format
expect(parser.parse('5-km-from:(40.712776, -74.005974)')).to.deep.equals({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
}
} as DistanceSearch);
// Test coordinate format with extra spaces
expect(parser.parse('5-km-from:( 40.712776 , -74.005974 )')).to.deep.equals({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
}
} as DistanceSearch);
// Test coordinates with different decimal places
expect(parser.parse('5-km-from:(40.7, -74.1)')).to.deep.equals({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.7,
longitude: -74.1
}
}
} as DistanceSearch);
// Test negated coordinate search
expect(parser.parse('5-km-from!:(40.712776, -74.005974)')).to.deep.equals({
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
},
negate: true
} as DistanceSearch);
// Test stringification of coordinates
const query: DistanceSearch = {
type: SearchQueryTypes.distance,
distance: 5,
from: {
GPSData: {
latitude: 40.712776,
longitude: -74.005974
}
}
};
expect(parser.stringify(query)).to.equals('5-km-from:(40.712776, -74.005974)');
// Test stringification of negated coordinates
const negatedQuery: DistanceSearch = {
...query,
negate: true
};
expect(parser.stringify(negatedQuery)).to.equals('5-km-from!:(40.712776, -74.005974)');
});
it('OrientationSearch search', () => {
check({type: SearchQueryTypes.orientation, landscape: true} as OrientationSearch);