Jeg forstår, at ingen udvidelse gør dette, så jeg har fundet en begrænset løsning:
Hvis A og B begge er normaliserede (længde 1), cos(A, B) = 1 - 0.5 * ||A - B||^2
. ||A - B||
er den euklidiske afstand og cos(A, B)
er cosinus-ligheden. Så større euklidisk afstand <=> mindre cosinus-lighed (giver intuitivt mening, hvis du forestiller dig en enhedscirkel), og hvis du har ikke-normale vektorer, påvirker det ikke deres cosinus-ligheder at ændre deres størrelser uden at ændre deres retninger. Fantastisk, så jeg kan normalisere mine vektorer og sammenligne deres euklidiske afstande...
Der er et godt svar her om Cube , som understøtter n-dimensionelle punkter og GiST-indekser på Euklidsk afstand, men det understøtter kun 100 eller færre dimensioner (kan hackes højere, men jeg havde problemer omkring 135 og højere, så nu er jeg bange). Kræver også Postgres 9.6 eller nyere.
Så:
- Sørg for, at jeg er ligeglad med at have højst 100 dimensioner. Opgrader til Postgres 9.6 eller nyere.
- Fyld min tabel med arrays for at repræsentere vektorer.
- Normaliser vektorerne for at skabe en ekstra kolonne med
cube
point. Opret et GiST-indeks på denne kolonne. - Ordner efter euklidisk afstand stigende for at få cosinus-lighed faldende:
EXPLAIN SELECT * FROM mytable ORDER BY normalized <-> cube(array[1,2,3,4,5,6,7,8,9,0]) LIMIT 10;
Hvis jeg har brug for mere end 100 dimensioner, kan jeg muligvis opnå dette ved at bruge flere indekserede kolonner. Vil i så fald opdatere svaret.
Opdatering: Temmelig sikker på, at der ikke er noget, jeg kan gøre ved at opdele>100-dimensionsvektoren i flere kolonner. Jeg ender med at skulle scanne hele bordet.