Es wäre viel effizienter, Ihre Werte in einem normalisierten Schema zu speichern. Sie können es jedoch auch mit Ihrem aktuellen Setup zum Laufen bringen.
Annahmen
Angenommen, diese Tabellendefinition:
CREATE TABLE tbl (tbl_id int, usr jsonb);
"Benutzer" ist ein reserviertes Wort und würde doppelte Anführungszeichen erfordern, um als Spaltenname verwendet zu werden. Tu das nicht. Ich benutze usr
stattdessen.
Abfrage
Die Abfrage ist nicht so trivial wie die (jetzt gelöschten) Kommentare es scheinen ließen:
SELECT t.tbl_id, obj.val->>'count' AS count
FROM tbl t
JOIN LATERAL jsonb_array_elements(t.usr) obj(val) ON obj.val->>'_id' = '1'
WHERE t.usr @> '[{"_id":"1"}]';
Es gibt 3 grundlegende Schritte :
1. Identifizieren Sie qualifizierende Zeilen kostengünstig
WHERE t.usr @> '[{"_id":"1"}]'
Identifiziert Zeilen mit übereinstimmendem Objekt im JSON-Array. Der Ausdruck kann einen generischen GIN-Index für die jsonb
Spalte oder einen mit der spezielleren Operatorklasse verwenden jsonb_path_ops
:
CREATE INDEX tbl_usr_gin_idx ON tbl USING gin (usr jsonb_path_ops);
Die hinzugefügte WHERE
Klausel ist logisch redundant , es ist jedoch erforderlich, den Index zu verwenden. Der Ausdruck in der Join-Klausel erzwingt dieselbe Bedingung, jedoch erst, nachdem das Array in jeder bisher qualifizierenden Zeile nicht getestet wurde. Mit der Indexunterstützung verarbeitet Postgres zunächst nur Zeilen, die ein qualifizierendes Objekt enthalten. Bei kleinen Tabellen spielt das keine große Rolle, bei großen Tabellen und nur wenigen qualifizierenden Zeilen macht dies einen großen Unterschied.
Verbunden:
2. Identifizieren Sie übereinstimmende Objekte im Array
Unnest mit jsonb_array_elements()
. ( unnest()
ist nur für Postgres-Array-Typen geeignet.) Da wir nur daran interessiert sind, Objekte tatsächlich abzugleichen, filtern Sie sofort in der Verknüpfungsbedingung.
Verbunden:
3. Extrahieren Sie den Wert für den verschachtelten Schlüssel 'count'
Nachdem qualifizierende Objekte extrahiert wurden, einfach : obj.val->>'count'
.
obj(value)
? Ist es auf derLATERAL JOIN
, derjsonb_array_elements
oder woanders?JOIN LATERAL jsonb_array_elements(t.usr) obj(value) is short for JOIN LATERAL jsonb_array_elements(t.usr) AS obj(value)
und dasobj(value)
ist ein Tabellen- und Spaltenalias? Wennobj
es sich in diesem Beispiel um einen Tabellenalias handelt, wofür handelt es sich um einen Alias? Das Set kehrte von zurückjsonb_array_elements
?JOIN LATERAL jsonb_array_elements(t.usr) obj ON obj->>'_id' = '1'
hatte der gleiche Effekt (sobald Sie die select-Anweisung aktualisieren, umvalue
statt zu verwendenval
). Es scheint, dassjsonb_array_elements(t.usr)
eine Tabelle mit nur einer Spalte zurückgegeben wird. Ist Postgres klug und erkennt, dass diesobj ->>
dasselbe ist wieobj.val ->>
?