Конвертировать LocalDate в метку времени в столбце json Постгреса - PullRequest
0 голосов
/ 11 сентября 2018

Мне нужно перенести столбец в PostgresDB 9.5.

Имя таблицы - testtable, а соответствующий столбец - examplecolumn.

В примере столбца у меня есть этот массив JSON, например:

[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}]

Я хочу преобразовать ребенка с "billingDate" в метку времени в следующем формате:

[{"key":"id","before":null,"after":4371},
{"key":"status","before":null,"after":1},
{"key":"startDate","before":null,"after":1514761200000},
{"key":"endDate","before":null,"after":1546297199000},
{"billingDate":1515974400}]

Я хочу сохранить все остальное. Сначала я попытался получить эти строки примерно так.

SELECT *, examplecolumn::json->4->'after' as export
FROM testtable
WHERE examplecolumn like '%after":{%';

Но я не могу сделать это с помощью индекса исправления (например, 4), и я не знаю, у какой строки есть дочерние объекты с этой LocalDate, поэтому я написал это условие where.

Как я могу это сделать? Я пробовал так много раз с несколькими функциями Postgres JSON, но я сыт по горло.

Спасибо.

1 Ответ

0 голосов
/ 11 сентября 2018

Мне не ясно, идет ли речь о преобразовании этих данных во временную метку в соответствии с заголовком вопроса или об извлечении данных в соответствии с вопросом. Таким образом, этот ответ о извлечении данных.

Во-первых, CTE должен просто рандомизировать порядок элементов в массиве JSON, чтобы показать, что он справляется с проблемой индекса. Очевидно, что вместо этого вы будете выполнять запрос к вашей таблице. Тогда элемент с «billingDate» включается только в четные результаты; нечетные содержат остальные элементы JSON и исключают этот.

WITH cte AS (
        SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
        FROM (
                VALUES
                (1, '{"key":"id","before":null,"after":4371}'),
                (1, '{"key":"status","before":null,"after":1}'),
                (1, '{"key":"startDate","before":null,"after":1514761200000}'),
                (1, '{"key":"endDate","before":null,"after":1546297199000}'),
                (2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
        ) AS v(id, j), generate_series(1, 10) AS g
        GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte

Результат:

enter image description here

Если вы хотите получить только те элементы, которые имеют «billingDate», вы можете добавить предложение WHERE из своего вопроса:

WITH cte AS (
        SELECT ('[' || STRING_AGG(CASE WHEN id = 2 THEN CASE WHEN g % 2 = 0 THEN j::TEXT END ELSE j::TEXT END, ',' ORDER BY RANDOM()) || ']')::JSON AS j
        FROM (
                VALUES
                (1, '{"key":"id","before":null,"after":4371}'),
                (1, '{"key":"status","before":null,"after":1}'),
                (1, '{"key":"startDate","before":null,"after":1514761200000}'),
                (1, '{"key":"endDate","before":null,"after":1546297199000}'),
                (2, '{"key":"billingDate","before":null,"after":{"year":2018,"month":"JANUARY","dayOfMonth":15,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":15,"leapYear":false,"monthValue":1,"chronology":{"calendarType":"iso8601","id":"ISO"}}}')
        ) AS v(id, j), generate_series(1, 10) AS g
        GROUP BY g
)
SELECT j, (SELECT je->'after' FROM JSON_ARRAY_ELEMENTS(j) AS je WHERE je->>'key' = 'billingDate' AND (je->>'after') IS NOT NULL) AS export
FROM cte
WHERE j::TEXT LIKE '%after":{%'

Результат:

enter image description here

...