Здравствуйте.
В 9.2 появился долгожданный JSON, а в 9.3 добавились функции обработки значений в нём, но мне так и не понятно из документации как можно сортировать по ключу в JSON-поле. Подход с hstore:
SELECT params->'a' AS a FROM test WHERE params ? 'a';
не подходит...
Допустим есть таблица:
CREATE TABLE "test" ( "id" serial NOT NULL PRIMARY KEY, "params" json, );
Засунем в неё данные:
INSERT INTO test(params) VALUES ('"test"'); INSERT INTO test(params) VALUES ('[1,2,3]'); INSERT INTO test(params) VALUES ('{"a":"test", "b":123}'); INSERT INTO test(params) VALUES ('{"a":"test", "c":{"d":1}}');
Как выбрать строки, где есть ключ "a" и "b"?
Как выбрать строки, где есть ключ "a" и ("b" или "c")?
Как выбрать строки, где в ключе "c" есть ключ "d"?
Как выбрать строки, где полем является строка?
Как выбрать строки, где полем является список?
Как выбрать строки, где полем является объект?
Это вообще возможно и можно ли строить индекс по этим вещам?
UPD: Вопрос открыт всё же... И как строить индекс на наличие ключа, если ключей, собственно, ну очень много?
Только нужно учесть, что
Только нужно учесть, что данные в поле params всё же в json, а не в string или array.
>>Как выбрать строки, где есть ключ "a" и "b"? + сортировка
>>Как выбрать строки, где есть ключ "a" и ("b" или "c")?
>>Как выбрать строки, где в ключе "c" есть ключ "d"?
>>Это вообще возможно и можно ли строить индекс по этим вещам?
Возможно, как показано выше, индекс по условию.
Что касается запихивания в json string и array - это, мне кажется, извращение. Способ, определённо есть, например в ветке dev сейчас есть функция json_typeof - которая и определяет тип вашего json. Наверное есть и способы "через задний проход", или написать функцию самому, но, считаю, это не целесообразным и это приведёт к тому, что в каждом верхнем запросе придётся всегда делать поправку на тип данных, которым вы пытаетесь воспользоваться в данный момент.
Работает но не так
Вернее не совсем так ка хотелось бы.
Если в таблице есть такие разношёрстные данные, то любой запрос выше вообще выпадает в осадок:
В этом то и вся соль, что все перечисленные данные - вполне себе JSON согласно спеки...
Насчёт string согласен, а вот насчет незапихиввания array - что делать со вложенными?
Как видно, команда PostgreSQL
Как видно, команда PostgreSQL особо не заморачивалась над полнейшем покрытии всех нужд связанных с json, при этом как бы показало: что делать с этой штукой можно всё, что угодно (OpenSource же). Но это ведь не освобождает от следования простой логике и хоть какой-нибудь культуре проектирования? Не стоит запихивать arr и str в поле json, моё мнение.
А как же тогда быть?
Можно договориться о типе данных, например:
>> а вот насчет незапихиввания array - что делать со вложенными?
Ты имеешь в виду под "вложенными" вот такой массив:
'{"type": "ArrayClass", "array":[1,2,3]}'
?
Другой
матрицу:
[[1,2,3,4],[1,2,3,4]]
В тему
Опишу чуть подробнее реальную задачу.
Нужно не дожидаясь выхода 9.4 решить нюансы:
В ценах нужно хранить такой приблизительный JSON:
{"all":10, "client1": 10.99, "client2": 11.01, ...}
Товаров около полумиллиона для всех поставщиков. Цены для каждого товара разнятся от клиента к клиенту по каждому поставщику. Клиентов около 300. Но при этом у многих клиентов цена для него == цене для всех. Это облегчает ситуацию, но ненамного.
То есть заводить отдельную таблицу с ценами - это ооочень много строк в этой табличке (более 20 лимонов). И добавление/обновление прайса одного поставщика становится непреодолимой задачей (на несколько десятков минут с большой нагрузкой сервера). А прайсы обновляются каждые полчаса как минимум...
Другое дело писать цены товара в одно поле - это очень быстро. Но...
Hstore для поля prices не вариант (нет правильной сортировки по float, я так понимаю). Или я не правильно понимаю?
Остаётся JSON. Но по нему нужно создавать индекс для сортировки (какой можно сделать в 9.3?) и как сделать проверку по наличию ключа (например так: 'client1' in prices OR 'all' in prices).
Конечно, часть вопросов берёт на себя plv8, но вот как ускорить индексами - не понимаю...
Индекс по условию - не вариант, т.к. индексов будет по количеству клиентов - то есть около 300...
Может быть кто предложит вариант класса операторов для "единственного" индекса на это поле?
Свалить на Монго не предлагать - другие задачи от этого усложнятся...
P.S.: Если это прочитают НАШИ разработчики JSONB - надеюсь к релизу 9.4 внесут необходимое (ребята, я в вас верю!).
UPD: hstore по моим тестам не подходит:
psql (9.4beta2, сервер 9.3.5) из apt.postgresql.org
То же самое в pgAdmin3.
Это нормально (строки 1 и 2) или ошибка в реализации преобразования hstore?