@Saurabh Nanda:Ähnlich wie Sie es gepostet haben, können Sie auch eine einfache Funktion erstellen, um Ihr varchar-Array wie folgt in Kleinbuchstaben umzuwandeln:
CREATE OR REPLACE FUNCTION array_lowercase(varchar[]) RETURNS varchar[] AS
$BODY$
SELECT array_agg(q.tag) FROM (
SELECT btrim(lower(unnest($1)))::varchar AS tag
) AS q;
$BODY$
language sql IMMUTABLE;
Beachten Sie, dass ich auch die Tags von Leerzeichen kürze. Dies ist für Sie möglicherweise nicht erforderlich, aber ich tue es normalerweise aus Konsistenzgründen.
Testen:
SELECT array_lowercase(array['Hello','WOrLD']);
array_lowercase
-----------------
{hello,world}
(1 row)
Wie von Saurabh angemerkt, können Sie dann einen GIN-Index erstellen:
CREATE INDEX ix_tags ON tagtable USING GIN(array_lowercase(tags));
Und Abfrage:
SELECT * FROM tagtable WHERE ARRAY['mytag'::varchar] && array_lowercase(tags);
AKTUALISIERUNG: Leistung von WHILE
vs array_agg/unnest
Ich habe eine Tabelle mit 100K 10 Elementen text[]
erstellt Arrays (12 Zeichen zufällig gemischte Zeichenketten) und jede Funktion getestet.
Die Funktion array_agg/unnest hat zurückgegeben:
EXPLAIN ANALYZE VERBOSE SELECT array_lowercase(data) FROM test;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.test (cost=0.00..28703.00 rows=100000 width=184) (actual time=0.320..3041.292 rows=100000 loops=1)
Output: array_lowercase((data)::character varying[])
Total runtime: 3174.690 ms
(3 rows)
Die WHILE-Funktion hat Folgendes zurückgegeben:
EXPLAIN ANALYZE VERBOSE SELECT array_lowercase_while(data) FROM test;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.test (cost=0.00..28703.00 rows=100000 width=184) (actual time=5.128..4356.647 rows=100000 loops=1)
Output: array_lowercase_while((data)::character varying[])
Total runtime: 4485.226 ms
(3 rows)
AKTUALISIERUNG 2: FOREACH
vs. WHILE
Als letztes Experiment habe ich die WHILE-Funktion so geändert, dass sie FOREACH:
CREATE OR REPLACE FUNCTION array_lowercase_foreach(p_input varchar[]) RETURNS varchar[] AS $BODY$
DECLARE
el text;
r varchar[];
BEGIN
FOREACH el IN ARRAY p_input LOOP
r := r || btrim(lower(el))::varchar;
END LOOP;
RETURN r;
END;
$BODY$
language 'plpgsql'
Die Ergebnisse schienen denen von WHILE
ähnlich zu sein :
EXPLAIN ANALYZE VERBOSE SELECT array_lowercase_foreach(data) FROM test;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------
Seq Scan on public.test (cost=0.00..28703.00 rows=100000 width=184) (actual time=0.707..4106.867 rows=100000 loops=1)
Output: array_lowercase_foreach((data)::character varying[])
Total runtime: 4239.958 ms
(3 rows)
Obwohl meine Tests keineswegs streng sind, habe ich jede Version einige Male ausgeführt und festgestellt, dass die Zahlen repräsentativ sind, was darauf hindeutet, dass die SQL-Methode (array_agg/unnest) die schnellste ist.