So erstellen Sie einen Index für eine ganzzahlige json-Eigenschaft in postgres

7

Ich kann für mein ganzes Leben nicht herausfinden, wie ich einen Index für eine Eigenschaft meiner JSON-Spalte erstellen kann, die eine Ganzzahl ist.

Ich habe es so versucht (und auch Dutzende von anderen)

CREATE INDEX user_reputation_idx ON users(("user"->>'reputation')::int)

Es funktioniert gut in einer Abfrage (zB ORDER BY ("user"->>'reputation')::int)

Was vermisse ich?

AKTUALISIEREN

Ich bekomme einen einfachen Syntaxfehler, aber ich habe wirklich keine Ahnung warum.

ERROR:  syntax error at or near "::"
LINE 1: ... user_reputation_idx ON users (("user"->>'reputation')::int)

Die Tabellendefinition ist recht einfach. Es ist nur eine Spalte uservom Typ json.

Sieht also so aus:

CREATE TABLE users
(
  "user" json
)
Christoph
quelle
Sie müssen die wörtliche Fehlermeldung und den (relevanten Teil) Ihrer Tabellendefinition ( \d tblin psql) sowie die Abfrage, die Sie ausführen möchten, angeben. Für den Anfang kann diese verwandte Antwort auf SO hilfreich sein. Dieser dient jedoch zum Indizieren eines JSON- Arrays . Ihr Fall scheint einfacher ...
Erwin Brandstetter
1
Vielen Dank für Ihren Kommentar. Mir ist diese andere Antwort bekannt und ich verwende diesen Index bereits für Arrays, wie dort erfolgreich beschrieben. Ich verwende auch einen anderen Index für eine jsonEigenschaft, die einfach ist text. Nur für diese intSpalte funktioniert es nicht. Die Verwendung in einer Abfrage zum Sortieren intfunktioniert jedoch hervorragend. Und übrigens, danke für deine großartige Unterstützung hier!
Christoph

Antworten:

13

Versuchen Sie stattdessen Folgendes:

CREATE INDEX user_reputation_idx ON users(cast("user"->>'reputation' AS int));

Die Postgres-Syntaxverknüpfung ::für Casts ist ohne zusätzliche Klammern in einer Indexdefinition nicht zulässig ( siehe Kommentar von @ bma ). Es funktioniert jedoch mit der Standard-SQL-Funktion: cast(expression AS type)Dies hängt nicht mit dem jsonTyp an sich zusammen.

In beiden Fällen können Sie die Syntaxverknüpfung weiterhin expression::typein Ausdrücken verwenden, die den Index verwenden.

Erwin Brandstetter
quelle
Großartig! Das hat funktioniert. In Ihrer Abfrage fehlt nur eine schließende Klammer. Danke, dass du meinen Tag wieder gerettet hast!
Christoph
5
Mit genügend Klammern sollte es funktionieren. ZB CREATE INDEX user_reputation_idx2 ON users ( (("user"->>'reputation')::INT) ). Ich erinnere mich, dass ich eine Antwort in den Seitenlisten gelesen habe, in denen Tom Lane erklärte, warum der Ausdruck zusätzliche Klammern benötigte, aber eine schnelle Suche hat ihn nicht ergeben.
BMA
0

Wie @bma in einem Kommentar erläutert hat, funktioniert Ihr Index unverändert, wenn Sie die gesamte JSON-Definition in doppelte Klammern setzen:

CREATE INDEX user_reputation_idx ON users((("user"->>'reputation')::int));

Stellen Sie sicher, dass Sie im Index und beim Verweisen auf das Feld in einer Abfrage konsistent die JSON-Textnotation [- >>] und nicht die JSON-Objektnotation [->] verwenden. Andernfalls wird der Index nicht verwendet.

Alternativ können Sie die Objektnotation [->] konsistent verwenden. Sie müssen sich nur an das eine oder andere halten, mischen Sie sie nicht.

Moodboom
quelle