pgLatLon

annotate create_test_db.schema.sql @ 72:8fa0ef5e4ee6

Fixed longitude wraparound for values equal to or greater than 360 degrees
author jbe
date Wed Feb 12 13:11:04 2020 +0100 (2020-02-12)
parents 3cbce515387f
children
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

Impressum / About Us