Задать вопрос
@Luhashan

Полнотекстовый поиск PostgreSQL внутри JSON, индекс внутри JSON?

Есть таблица в postgres – table.
В table есть поле data (jsonb).
В data лежат json-объекты типа:
{
"obj": [
{
"TEXT": "any text here",
"key1": any value,
"key2": any value
},
{
" TEXT ": " any text here ",
"key1": any value,
"key2": any value
},
...
]
}
Пытаюсь сделать полнотекстовый поиск по " TEXT ".
Вопрос:
1. Можно ли не распаковывая json в отдельные таблицы/поля создать gin-индекс (tsvector) для " TEXT " и как?
2. Можно ли в принципе сделать полнотекстовый поиск по " TEXT ", который не будет слишком тормозить (база около 5 гигов) не распаковывая json в отдельные таблицы/поля?
Заранее всем огромное спасибо!
  • Вопрос задан
  • 1069 просмотров
Подписаться 2 Простой 8 комментариев
Решения вопроса 1
@galaxy
Сделать-то можно. Но лучше все-таки хотя бы отдельное поле под tsvector завести.
create table t (col jsonb);
create index ix_t_col using gin(to_tsvector('pg_catalog.english', jsonb_path_query_array(col, '$.obj.TEXT')));

insert into t values('{
"obj": [
{
"TEXT": "These functions act like their counterparts described above without the _tz suffix, except that these functions support comparisons of date/time values that require timezone-aware conversions.",
"key1": 77,
"key2": "a"
},
{
"TEXT": "Returns target with new_value inserted. If the item designated by the path is an array element, new_value will be inserted before that item if insert_after is false (which is the default), or after it if insert_after is true. If the item designated by the path is an object field, new_value will be inserted only if the object does not already contain that key",
"key1": 99,
"key2": false
}
]
}');


select ts_headline(col, 'function'::tsquery),
       ts_headline(arr, 'function'::tsquery)
  from (
    select col, jsonb_path_query_array(col, '$.obj.TEXT') arr,
           to_tsvector('pg_catalog.english', jsonb_path_query_array(col, '$.obj.TEXT')) tsv 
      from t
  ) q
 where tsv @@ 'function'::tsquery;


jsonb_path_query_array(col, '$.obj.TEXT') - выделяет все, что у вас по ключу TEXT в массив. Дальше он индексируется
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Luhashan Автор вопроса
Ну кому интересно, нашел вот такое https://www.depesz.com/2017/04/04/waiting-for-post...
На сколько я понял, проиндексировать можно только весь json как текст, индекса по ключам похоже сделать не получится:
"Nice. It found all words in all values in the json (it didn't index keys of objects)".
Хотя можно было бы и сделать, ведь postgres дает возможность добраться до ключей в запросе, значит какое-то json дерево один хрен строится, особенно учитывая, что очень высокий процент разработчиков часто не парится и херачит полубезумные json объекты в одно поле, даром что реляционная база юзается :( :)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы