PostgreSQL 9.4 jsonb как сделать запрос

В настоящее время у меня есть модель листа с определенным атрибутом jsonb:

      create_table "sheets", force: :cascade do |t|
        t.string   "name"
        t.integer  "user_id",    default: 0,    null: false
        t.boolean  "private",    default: true, null: false
        t.jsonb    "t_data",     default: {},   null: false
      end

в атрибуте t_data jsonb я буду хранить список (то есть несколько строк), содержимое которого должно быть таким:

    def sample
Sheet('rows @> ?', {"CSS grade" => "X" }.to_json)
content { headings: [ "Rendering engine", "Browser", "Platform", "Engine version", "CSS grade" ], rows: { "line_0":{ "Rendering engine":"Trident", "Browser":"Internet Explorer 4.0", "Platform":"Win 95+", "Engine version":"4.0", "CSS grade":"X" }, "line_1":{ "Rendering engine":"Trident", "Browser":"Internet Explorer 5.0", "Platform":"Win 95+", "Engine version":"5", "CSS grade":"C" },

этот запрос

Sheet('rows @> ?', {"CSS grade" => "X" }.to_json)

вызывает ошибку

NoMethodError: undefined method `Sheet' for main:Object

Я не уверен, что это лучшая схема... так как я хотел бы запросить все строки с разными заголовками, т.е. "Класс CSS" == "X", "Браузер" содержит "Проводник"...

Любые предложения по переписыванию моей схемы приветствуются...


person Community    schedule 07.09.2015    source источник


Ответы (1)


Я предлагаю не использовать ключ "line_0", так как он выглядит чрезмерным в структуре, которую вы предоставили для столбца содержимого JSONB. Было бы гораздо более гибко использовать простой массив для ключа "rows". Пример DDL с демонстрационными данными может выглядеть примерно так:

CREATE TABLE sheets (content JSONB);
INSERT INTO sheets VALUES
    ('{
     "headings": [
       "Rendering engine",
       "Browser",
       "Platform",
       "Engine version",
       "CSS grade"
     ],
     "rows": [{
                  "Rendering engine":"Trident",
                  "Browser":"Internet Explorer 4.0",
                  "Platform":"Win 95+",
                  "Engine version":"4.0",
                  "CSS grade":"X"
        },
        {
                  "Rendering engine":"Trident",
                  "Browser":"Internet Explorer 5.0",
                  "Platform":"Win 95+",
                  "Engine version":"5",
                  "CSS grade":"C"
        }
     ]
     }'::JSONB);

В этом случае у вас гораздо больше свободы для запроса элементов массива, чем явное указание row->'line_X'->>'jsonAttribute'. Пример запроса может быть следующим:

SELECT * FROM sheets,jsonb_array_elements(content->'rows') as row
WHERE row->>'CSS grade' = 'X' 
AND row->>'Platform' = 'Win 95+';
person Dmitry Savinkov    schedule 07.09.2015