2013-06-18 11 views
5

Sono nuovo di PostgreSQL e la mia domanda è simile a quello qui: linkPostgreSQL per scorrere attraverso le righe e trovare la corrispondenza più vicina utilizzando personalizzato distanza funzione

Per esempio, ho la seguente tabella:

| id |  vector   | 
| 1 | { 1.43, 3.54, 5.55} | 
| 2 | { 4.46, 5.56, 4.55} | 
| 3 | { 7.48, 2.54, 4.55} | 
| 4 | { 2.44, 2.34, 4.55} | 

una query di esempio che va qualcosa come

SELECT * FROM my_table WHERE vector CLOSEST('{1.23, 4.43, 4.63}') 

dovrebbe tornare con conseguente righe in modo ordinato, in cui determino il vecto "più vicino" r utilizzando una funzione Distanza personalizzata, ad es. calc_l2norm (doppia precisione [], doppia precisione []) che restituisce la distanza euclidea.

+0

Così, da più vicino, vuoi dire la distanza minima tra la punta del vettore di riferimento e che di quelli memorizzati nel database? –

+0

sì. calcolare la distanza tra il vettore di query e tutti i vettori nel database. –

risposta

5

In generale è possibile risolvere questo tipo di problemi utilizzando una funzione memorizzata, scritta in Java o Scala (alcuni potrebbero preferire PL/SQL, C o C++).

PostgreSql supporta le funzioni memorizzate (basate su Java), quindi consentire alla query SQL di recuperare i dati e passarli a una funzione memorizzata. La funzione memorizzata restituisce la distanza, quindi puoi filtrare/ordinare ecc. Su di essa.

Sulla base di una tabella come questa

create table point(vector float8[]); 
insert into point values('{0.0, 0.0, 0.0}'); 
insert into point values('{0.5, 0.5, 0.5}'); 

con una funzione Java come questo:

public class PlJava { 
    public final static double distance2(double[] v1, double[] v2) { 
     return Math.sqrt(Math.pow(v2[0] - v1[0], 2) 
      + Math.pow(v2[1] - v1[1], 2) + Math.pow(v2[2] - v1[2], 2)); 
    } 
} 

e la dichiarazione di funzione in SQL:

CREATE FUNCTION pljava.distance2(float8[], float8[]) 
    RETURNS float8 
    AS 'PlJava.distance2' 
    IMMUTABLE 
    LANGUAGE java; 

la query potrebbe sembrare this:

select 
    point.*, 
    pljava.distance2(vector, '{1.0, 1.0, 1.0}') as dist 
    from 
    point 
    order by 
    dist;  

che si traduce in

vector  |  dist 
---------------+------------------- 
{0.5,0.5,0.5} | 0.866025403784439 
{0,0,0}  | 1.73205080756888 

Aggiornamento

funzioni memorizzate possono essere scritti in C e C++ pure. C++ richiede più impegno, perché l'interfaccia di PostgreSql utilizza la convenzione di chiamata C. Vedere Using C++ for Extensibility

+0

ha, la cosa Java è interessante (puoi fare lo stesso usando C++?). So che potresti farlo con C poichè puoi scegliere 'C' come lingua quando scrivi la definizione della funzione nello strumento pgAdmin. Ma questo è utile in quanto ho intenzione di utilizzare le funzioni di distanza più complesse. –

+0

Sì, è possibile anche in C e C++; Ho aggiornato la risposta. – Beryllium

Problemi correlati