Поиск в Rails по атрибуту JSON - PullRequest
0 голосов
/ 05 июня 2018

У меня есть Foo модель.У него есть ключевые слова.

create_table "foos", force: :cascade do |t|
  t.json "keywords"
end

Ключевые слова хранятся в виде массива: ["quick", "brown", "fox"]

Мне было интересно, как выбрать foos с одним из ключевых слов: "fox".

Iсмотрел это видео и он сказал использовать что-то вроде WHERE details -> 'tags' ? 'techie'

Но это работает только потому, что details в их примере это хеш

{
  "contacts": [...],
  "tags": [...]
}

Iя не копаюсь в хэше, я просто хочу найти массив.Я пробовал это:

Foo.where("keywords -> 'fox'")

но это поднимает

ActiveRecord::StatementInvalid: PG::DatatypeMismatch: ERROR:  argument of WHERE must be type boolean, not type json
LINE 1: SELECT  "foos".* FROM "foos" WHERE (keywords -> 'fox') LIM...
                                              ^
: SELECT  "foos".* FROM "foos" WHERE (keywords -> 'fox') LIMIT $1

A учебник предлагает использовать ?| array[:keys], например, так:

Foo.where('keywords ?| array[:keys]', keys: ['brown', 'fox'])

Но я получаю такую ​​же ошибку

ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  operator does not exist: json ?| text[]
LINE 1: SELECT  "foos".* FROM "foos" WHERE (keywords ?| array['fox...
                                                       ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT  "foos".* FROM "foos" WHERE (keywords ?| array['fox','quick']) LIMIT $1

Идеи кому-нибудь?

1 Ответ

0 голосов
/ 06 июня 2018

Вы должны использовать JSONB тип данных вместо JSON. Здесь - хорошая тема.

Сравните

> select '["a", "fox", "c"]'::jsonb ?| array['fox','quick'] as exists;

 exists
--------
 t
(1 row)

с

> select '["a", "fox", "c"]'::json ?| array['fox','quick'] as exists;

ERROR:  operator does not exist: json ?| text[]
LINE 1: select '["a", "fox", "c"]'::json ?| array['fox','quick'] as ...

PS И тогда у вас есть возможность проиндексировать ваш keywords колонка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...