2017-07-11 2 views
1

Mein Benutzermodell haben jsonb Spalte, deren Namen ist raw. Es sieht wie folgt aus:Suche durch Jsonb-Spalte in ActiveRecord

{"client"=>{"tokens"=>["asdasd"]}} 

Jetzt habe ich einen Benutzer durch ein Token finden wollen, die in raw["client"]["tokens"] ist. Wie kann ich das machen?

+1

Versuchen Sie 'User.where (" roh -> 'Client' -> 'Token' =? ", 'Ihr Token hier')' – Pavan

+1

Dies könnte für das, was Sie gesucht haben https: // stackoverflow.com/questions/22667401/postgres-json-data-type-rails-query –

+1

Wenn Sie nach einem Token aus 'tokens' Array suchen müssen, müssen Sie' @> ':' User.find_by ("raw- > 'client' -> 'Tokens' @>? ", ['token']. to_json)' –

Antwort

1

Ich mache solche Abfragen normalerweise zuerst in einer SQL-Konsole und wandle sie dann in ActiveRecord um.

Sie können Hash-Tasten in Postgres navigieren. Die Abfrage

SELECT 
    raw #> '{client,tokens}' 
FROM users 

kehrt nur die tokens Array von diesem Pfad. Jetzt müssen wir prüfen, ob es den Wert enthält, nach dem wir suchen. Die Abfrage

SELECT 
    raw #> '{client,tokens}' ? 'asdasd' 
FROM users 

wählt t für jene Zeile, die einen entsprechenden Token haben. Jetzt können Sie dies den WHERE Abschnitt bewegen:

SELECT 
* 
FROM users 
WHERE raw #> '{client,tokens}' ? 'asdasd' 

Und wenn dies wählt, was Sie erwarten, dann können Sie es zu AR konvertieren:

User.where("config #> '{client, tokens}' ? :token", token: 'asdasd') 

Bitte beachte, dass ich nicht ? für die Parameterersetzung verwenden kann und verwenden Sie stattdessen :token. Beachten Sie auch, dass dies funktioniert nur in JSONB (Postgres 9.4+ https://www.postgresql.org/docs/9.4/static/functions-json.html#FUNCTIONS-JSONB-OP-TABLE)

Update:

Sie sollten (tm) (Ich habe nicht getestet) auszukommen:

CREATE INDEX index_tokens ON users USING GIN ((raw #> '{client, tokens}')); 

Siehe https://www.postgresql.org/docs/9.6/static/datatype-json.html#JSON-INDEXING für mehr Details

Update2:

Eine andere Möglichkeit wäre die Abfrage:

Welche sollte in der Lage sein, einen einfachen GIN Index für die rohe Spalte zu verwenden (die mehr Platz als der oben beschriebene Ausdruck Index verwendet).

CREATE INDEX index_user_raw ON users USING GIN (raw)

Nochmal: Details finden Sie in der INDEXING JSON Link oben. Und verwenden Sie einen Query Visualizer, um die Unterschiede zu sehen. Ich mag http://tatiyants.com/pev

+0

Welcher Index sollte für solche wo definiert werden? –

+0

@PavelMikhailyuk Ich aktualisierte die Antwort. –