support filtering by geographic longitude and latitude in insights explorer queries

This commit is contained in:
MaysWind
2026-03-08 20:55:35 +08:00
parent a0fd468309
commit 4d7c3650b5
22 changed files with 244 additions and 20 deletions
+106 -14
View File
@@ -317,7 +317,7 @@ export class TransactionExplorerQuery {
condition = new TransactionExplorerDestinationAmountCondition(TransactionExplorerConditionOperatorType.Between, [0, 0]);
break;
case TransactionExplorerConditionField.GeoLocation:
condition = new TransactionExplorerGeoLocationCondition(TransactionExplorerConditionOperatorType.IsNotEmpty, []);
condition = new TransactionExplorerGeoLocationCondition(TransactionExplorerConditionOperatorType.IsNotEmpty, [TransactionExplorerGeoLocationCondition.MIN_LATITUDE, TransactionExplorerGeoLocationCondition.MAX_LATITUDE, TransactionExplorerGeoLocationCondition.MIN_LONGITUDE, TransactionExplorerGeoLocationCondition.MAX_LONGITUDE]);
break;
case TransactionExplorerConditionField.TransactionTag:
condition = new TransactionExplorerTransactionTagCondition(TransactionExplorerConditionOperatorType.HasAny, []);
@@ -670,7 +670,7 @@ export class TransactionExplorerConditionWithRelation {
break;
case TransactionExplorerConditionField.GeoLocation.value:
if (TransactionExplorerGeoLocationCondition.supportedOperators[conditionOperator] && Array.isArray(conditionValue)) {
condition = new TransactionExplorerGeoLocationCondition(conditionOperator as GeoLocationConditionOperator, conditionValue as string[]);
condition = new TransactionExplorerGeoLocationCondition(conditionOperator as GeoLocationConditionOperator, conditionValue as [number, number, number, number]);
}
break;
case TransactionExplorerConditionField.TransactionTag.value:
@@ -984,29 +984,47 @@ export class TransactionExplorerDestinationAmountCondition extends AbstractTrans
}
type GeoLocationConditionOperator = TransactionExplorerConditionOperatorType.IsEmpty |
TransactionExplorerConditionOperatorType.IsNotEmpty;
TransactionExplorerConditionOperatorType.IsNotEmpty |
TransactionExplorerConditionOperatorType.LatitudeBetween |
TransactionExplorerConditionOperatorType.LatitudeNotBetween |
TransactionExplorerConditionOperatorType.LongitudeBetween |
TransactionExplorerConditionOperatorType.LongitudeNotBetween;
export class TransactionExplorerGeoLocationCondition implements TransactionExplorerCondition<TransactionExplorerConditionFieldType.GeoLocation, string[]> {
export class TransactionExplorerGeoLocationCondition implements TransactionExplorerCondition<TransactionExplorerConditionFieldType.GeoLocation, [number, number, number, number]> {
public static readonly supportedOperators: PartialRecord<TransactionExplorerConditionOperatorType, true> = {
[TransactionExplorerConditionOperatorType.IsEmpty]: true,
[TransactionExplorerConditionOperatorType.IsNotEmpty]: true
[TransactionExplorerConditionOperatorType.IsNotEmpty]: true,
[TransactionExplorerConditionOperatorType.LatitudeBetween]: true,
[TransactionExplorerConditionOperatorType.LatitudeNotBetween]: true,
[TransactionExplorerConditionOperatorType.LongitudeBetween]: true,
[TransactionExplorerConditionOperatorType.LongitudeNotBetween]: true
};
public static readonly MIN_LATITUDE: number = -90.0;
public static readonly MAX_LATITUDE: number = 90.0;
public static readonly MIN_LONGITUDE: number = -180.0;
public static readonly MAX_LONGITUDE: number = 180.0;
public readonly field = TransactionExplorerConditionFieldType.GeoLocation;
public readonly operator: GeoLocationConditionOperator = TransactionExplorerConditionOperatorType.IsNotEmpty;
public value: string[];
public value: [number, number, number, number];
constructor(operator: GeoLocationConditionOperator, value: string[]) {
constructor(operator: GeoLocationConditionOperator, value: [number, number, number, number]) {
this.operator = operator;
this.value = value;
this.value = [
value[0] ?? TransactionExplorerGeoLocationCondition.MIN_LATITUDE,
value[1] ?? TransactionExplorerGeoLocationCondition.MAX_LATITUDE,
value[2] ?? TransactionExplorerGeoLocationCondition.MIN_LONGITUDE,
value[3] ?? TransactionExplorerGeoLocationCondition.MAX_LONGITUDE
];
}
public getValueForStore(): string[] {
if (this.operator === TransactionExplorerConditionOperatorType.IsEmpty || this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return [];
}
return [];
public getValueForStore(): [number, number, number, number] {
return [
this.value[0] ?? TransactionExplorerGeoLocationCondition.MIN_LATITUDE,
this.value[1] ?? TransactionExplorerGeoLocationCondition.MAX_LATITUDE,
this.value[2] ?? TransactionExplorerGeoLocationCondition.MIN_LONGITUDE,
this.value[3] ?? TransactionExplorerGeoLocationCondition.MAX_LONGITUDE
];
}
public match(transaction: TransactionInsightDataItem): boolean {
@@ -1014,6 +1032,62 @@ export class TransactionExplorerGeoLocationCondition implements TransactionExplo
return !transaction.geoLocation;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return !!transaction.geoLocation;
} else if (this.operator === TransactionExplorerConditionOperatorType.LatitudeBetween) {
if (!transaction.geoLocation) {
return false;
}
const latitude = transaction.geoLocation.latitude;
if (typeof(this.value[0]) === 'number' && latitude < this.value[0]) {
return false;
}
if (typeof(this.value[1]) === 'number' && latitude > this.value[1]) {
return false;
}
return true;
} else if (this.operator === TransactionExplorerConditionOperatorType.LatitudeNotBetween) {
if (!transaction.geoLocation) {
return false;
}
const latitude = transaction.geoLocation.latitude;
if (typeof(this.value[0]) === 'number' && typeof(this.value[1]) === 'number' && latitude >= this.value[0] && latitude <= this.value[1]) {
return false;
}
return true;
} else if (this.operator === TransactionExplorerConditionOperatorType.LongitudeBetween) {
if (!transaction.geoLocation) {
return false;
}
const longitude = transaction.geoLocation.longitude;
if (typeof(this.value[2]) === 'number' && longitude < this.value[2]) {
return false;
}
if (typeof(this.value[3]) === 'number' && longitude > this.value[3]) {
return false;
}
return true;
} else if (this.operator === TransactionExplorerConditionOperatorType.LongitudeNotBetween) {
if (!transaction.geoLocation) {
return false;
}
const longitude = transaction.geoLocation.longitude;
if (typeof(this.value[2]) === 'number' && typeof(this.value[3]) === 'number' && longitude >= this.value[2] && longitude <= this.value[3]) {
return false;
}
return true;
}
return false;
@@ -1024,6 +1098,24 @@ export class TransactionExplorerGeoLocationCondition implements TransactionExplo
return `geo_location IS EMPTY`;
} else if (this.operator === TransactionExplorerConditionOperatorType.IsNotEmpty) {
return `geo_location IS NOT EMPTY`;
} else if (this.operator === TransactionExplorerConditionOperatorType.LatitudeBetween || this.operator === TransactionExplorerConditionOperatorType.LatitudeNotBetween) {
const minLatitude: number = this.value[0] ?? TransactionExplorerGeoLocationCondition.MIN_LATITUDE;
const maxLatitude: number = this.value[1] ?? TransactionExplorerGeoLocationCondition.MAX_LATITUDE;
if (this.operator === TransactionExplorerConditionOperatorType.LatitudeBetween) {
return `(geo_location.latitude >= ${minLatitude} AND geo_location.latitude <= ${maxLatitude})`;
} else if (this.operator === TransactionExplorerConditionOperatorType.LatitudeNotBetween) {
return `(geo_location.latitude < ${minLatitude} OR geo_location.latitude > ${maxLatitude})`;
}
} else if (this.operator === TransactionExplorerConditionOperatorType.LongitudeBetween || this.operator === TransactionExplorerConditionOperatorType.LongitudeNotBetween) {
const minLongitude: number = this.value[2] ?? TransactionExplorerGeoLocationCondition.MIN_LONGITUDE;
const maxLongitude: number = this.value[3] ?? TransactionExplorerGeoLocationCondition.MAX_LONGITUDE;
if (this.operator === TransactionExplorerConditionOperatorType.LongitudeBetween) {
return `(geo_location.longitude >= ${minLongitude} AND geo_location.longitude <= ${maxLongitude})`;
} else if (this.operator === TransactionExplorerConditionOperatorType.LongitudeNotBetween) {
return `(geo_location.longitude < ${minLongitude} OR geo_location.longitude > ${maxLongitude})`;
}
}
return '';