Join-Tabellen mit einem Wert innerhalb einer Spalte JSONB

Gibt es zwei Tabellen:

Autorisierte Ansprechpartner (auth_contacts):

(
userid varchar
contacts jsonb
)

contacts enthält ein array von Kontakten mit Attributen {contact_id, type}

discussion:

(
contact_id varchar
discussion_id varchar
discussion_details jsonb
)

Den Tisch auth_contacts hat mindestens 100k Datensätze, so dass es nicht JSONB-Typ ist nicht angemessen nach, wie es wäre, die doppelte oder dreifache Menge der Datensätze.

Beispieldaten für auth_contacts:

userid  | contacts
'11111' | '{"contact": [{"type": "type_a", "contact_id": "1-A-12"}
                      , {"type": "type_b", "contact_id": "1-A-13"}]}'

discussion Tabelle hat 5 Millionen sonderbare Aufzeichnungen.

Ich joinen will auf discussion.contact_id (relationale Spalte) mit contact id, welche ein json-Objekt in array von json-Objekten in auth_contacts.contacts.

Eine sehr grobe Art und Weise ist:

SELECT *
FROM discussion d 
JOIN (SELECT userid, JSONB_OBJECT_KEYS(a.contacts) AS auth_contact
      FROM auth_contacts a) AS contacts
      ON (d.contact_id = contacts.auth_contact::text)

Was dieser tut, ist eigentlich zur Laufzeit erstellen (inner sql) userid vs Kontakt-id-Tabelle (was ich zu vermeiden, und damit ging für JSONB-Datentyp
Diese Abfrage für einen Benutzer mit großen Datensätzen dauert 26 Sekunden, das ist noch nicht alles gut.
Habe versucht ein paar andere Möglichkeiten: PostgreSQL 9.4: Aggregat /Join-Tabelle auf JSON-Feld-id im inneren array

Aber es sollte eine sauberere und bessere Weg wäre so einfach wie
JOIN d.contact_id = contacts -> contact -> contact_id?
Wenn ich versuche, es nicht Ertrag keine Ergebnisse.

Bei der Suche im Netz scheint dies eine ziemlich langwierige Aufgabe?

Wenn Sie versuchen, verwenden Sie contacts->'contact'->'contact_id' es werden nicht alle Werte da contact ist ein array. Technisch könnte man so etwas wie contacts->'contact'@>'[{"contact_id":"1-A-12"}]' aber für die Teilnahme basiert auf, ich bin nicht sicher, es wäre effizienter.
Kontakte->'Kontakt'->0->'contact_id', Kontakte->'Kontakt'->1->'contact_id' gibt nachfolgende Werte. Für '@>' es ist eigentlich für die überprüfung von Bedingung (ob Links enthält, im Recht) und kann nicht verwendet werden, für sich als pro sich meiner Kenntnis. Wäre es möglich ?
Es ist möglich, eine hässliche SELECT * FROM discussion d JOIN auth a ON a.contacts->'contact'@>('[{"contact_id":"'||d.contact_id||'"}]')::jsonb basiert auf einem Schnelltest, aber ich würde nicht erwarten, es zu sein, die performant. Vielleicht mit `jsonb_array_elements() wäre besser, aber es hat immer noch zu explodieren die Werte aus dem JSON-sowieso.
Vereinbart wurde ja. Aber wie Sie bereits erwähnt, Leistung klug, es ist ein killer. Ich denke es sollte ein schneller und sauberer Weg, wie ist es in MongoDB?
Der index wird verwendet, auf die auth_contacts Seite. Zum Beispiel nachschlagen auth_user für eine Diskussion gegeben. Für die andere Richtung, Sie würden unnest dann join unter Verwendung des PK-index auf discussion.contact_id. Aber das ist alles akademisches Gerede. Die wirkliche Lösung ist ein vernünftiger Daten-Modell.

InformationsquelleAutor Prachi Tripathi | 2015-07-09

Schreibe einen Kommentar