| rev | 
   line source | 
| 
jbe@0
 | 
     1 
 | 
| 
jbe@0
 | 
     2 CREATE EXTENSION latlon;
 | 
| 
jbe@0
 | 
     3 
 | 
| 
jbe@0
 | 
     4 CREATE TABLE "test" (
 | 
| 
jbe@0
 | 
     5         "id"            SERIAL4         PRIMARY KEY,
 | 
| 
jbe@0
 | 
     6         "location"      EPOINT          NOT NULL,
 | 
| 
jbe@10
 | 
     7         "surrounding"   ECIRCLE         NOT NULL,
 | 
| 
jbe@10
 | 
     8         "multipoint"    ECLUSTER        NOT NULL,
 | 
| 
jbe@46
 | 
     9         "triangle"      ECLUSTER        NOT NULL,
 | 
| 
jbe@46
 | 
    10         "votes"         INT4            NOT NULL );
 | 
| 
jbe@0
 | 
    11 
 | 
| 
jbe@10
 | 
    12 CREATE INDEX "test_location_key"    ON "test" USING gist ("location");
 | 
| 
jbe@10
 | 
    13 CREATE INDEX "test_surrounding_key" ON "test" USING gist ("surrounding");
 | 
| 
jbe@10
 | 
    14 CREATE INDEX "test_multipoint_key"  ON "test" USING gist ("multipoint");
 | 
| 
jbe@10
 | 
    15 CREATE INDEX "test_triangle_key"    ON "test" USING gist ("triangle");
 | 
| 
jbe@46
 | 
    16 CREATE INDEX "test_vote_key" ON "test" ("votes");
 | 
| 
jbe@0
 | 
    17 
 | 
| 
jbe@46
 | 
    18 
 | 
| 
jbe@46
 | 
    19 -- Below follows an example of how to perform a nearest-neighbor search with
 | 
| 
jbe@46
 | 
    20 -- weighted geometric objects (distance scaled anti-proportionally through
 | 
| 
jbe@46
 | 
    21 -- "votes" column).
 | 
| 
jbe@46
 | 
    22 --
 | 
| 
jbe@46
 | 
    23 -- NOTE: The approach may be speeded up by providing new data types like
 | 
| 
jbe@46
 | 
    24 --       "weighted_ecluster" with corresponding GiST index support in future
 | 
| 
jbe@46
 | 
    25 --       versions of pgLatLon.
 | 
| 
jbe@46
 | 
    26 
 | 
| 
jbe@46
 | 
    27 CREATE TYPE "test_with_relevance" AS (
 | 
| 
jbe@46
 | 
    28         "id"            INT4,
 | 
| 
jbe@46
 | 
    29         "location"      EPOINT,
 | 
| 
jbe@46
 | 
    30         "surrounding"   ECIRCLE,
 | 
| 
jbe@46
 | 
    31         "multipoint"    ECLUSTER,
 | 
| 
jbe@46
 | 
    32         "triangle"      ECLUSTER,
 | 
| 
jbe@46
 | 
    33         "votes"         INT4,
 | 
| 
jbe@46
 | 
    34         "relevance"     FLOAT8 );
 | 
| 
jbe@46
 | 
    35 
 | 
| 
jbe@46
 | 
    36 CREATE FUNCTION "get_by_relevance" (epoint, int4 = 1, int4 = 10000)
 | 
| 
jbe@46
 | 
    37   RETURNS SETOF "test_with_relevance"
 | 
| 
jbe@46
 | 
    38   LANGUAGE plpgsql STABLE AS $$
 | 
| 
jbe@46
 | 
    39     DECLARE
 | 
| 
jbe@46
 | 
    40       "max_votes" INT4;
 | 
| 
jbe@46
 | 
    41       "tries"     INT4 = 2;
 | 
| 
jbe@46
 | 
    42       "all"       INT4;
 | 
| 
jbe@46
 | 
    43       "matches"   INT4;
 | 
| 
jbe@46
 | 
    44     BEGIN
 | 
| 
jbe@46
 | 
    45       SELECT "votes" INTO "max_votes" FROM "test" ORDER BY "votes" DESC LIMIT 1;
 | 
| 
jbe@46
 | 
    46       IF "max_votes" > 0 THEN
 | 
| 
jbe@46
 | 
    47         LOOP
 | 
| 
jbe@46
 | 
    48           RAISE DEBUG 'Considering % entries', "tries";
 | 
| 
jbe@46
 | 
    49           SELECT
 | 
| 
jbe@46
 | 
    50             count(1),
 | 
| 
jbe@46
 | 
    51             count(CASE WHEN "relevance" < "worst_case" THEN 1 ELSE NULL END)
 | 
| 
jbe@46
 | 
    52             INTO "all", "matches"
 | 
| 
jbe@46
 | 
    53             FROM (
 | 
| 
jbe@46
 | 
    54               SELECT
 | 
| 
jbe@46
 | 
    55                 CASE
 | 
| 
jbe@46
 | 
    56                   WHEN "votes" = 0
 | 
| 
jbe@46
 | 
    57                   THEN 'inf'::FLOAT8
 | 
| 
jbe@46
 | 
    58                   ELSE "fair_distance" / "votes"
 | 
| 
jbe@46
 | 
    59                 END AS "relevance",
 | 
| 
jbe@46
 | 
    60                 max("fair_distance") OVER () / "max_votes" AS "worst_case"
 | 
| 
jbe@46
 | 
    61               FROM (
 | 
| 
jbe@46
 | 
    62                 SELECT fair_distance("triangle", $1, $3), "votes" FROM "test"
 | 
| 
jbe@46
 | 
    63                 ORDER BY fair_distance
 | 
| 
jbe@46
 | 
    64                 LIMIT "tries"
 | 
| 
jbe@46
 | 
    65               ) AS "subquery1"
 | 
| 
jbe@46
 | 
    66             ) AS "subquery2";
 | 
| 
jbe@46
 | 
    67           EXIT WHEN "matches" >= $2 OR "all" < "tries";
 | 
| 
jbe@46
 | 
    68           "tries" := "tries" * 2;
 | 
| 
jbe@46
 | 
    69         END LOOP;
 | 
| 
jbe@46
 | 
    70         RETURN QUERY SELECT * FROM (
 | 
| 
jbe@46
 | 
    71           SELECT
 | 
| 
jbe@46
 | 
    72             *,
 | 
| 
jbe@46
 | 
    73             CASE
 | 
| 
jbe@46
 | 
    74               WHEN "votes" = 0
 | 
| 
jbe@46
 | 
    75               THEN 'inf'::FLOAT8
 | 
| 
jbe@46
 | 
    76               ELSE fair_distance("triangle", $1, $3) / "votes"
 | 
| 
jbe@46
 | 
    77             END AS "relevance"
 | 
| 
jbe@46
 | 
    78             FROM "test" ORDER BY fair_distance("triangle", $1, $3) LIMIT "tries"
 | 
| 
jbe@46
 | 
    79         ) AS "subquery" ORDER BY "relevance", "id" LIMIT $2;
 | 
| 
jbe@46
 | 
    80       ELSE
 | 
| 
jbe@46
 | 
    81         RETURN QUERY SELECT * FROM "test" ORDER BY "id" LIMIT $2;
 | 
| 
jbe@46
 | 
    82       END IF;
 | 
| 
jbe@46
 | 
    83       RETURN;
 | 
| 
jbe@46
 | 
    84     END;
 | 
| 
jbe@46
 | 
    85   $$;
 | 
| 
jbe@46
 | 
    86 
 |