2016-05-31 3 views
4

Я хотел бы сгладить вложенный объект json, например. {"a":{"b":1}} до {"a.b":1}, чтобы переварить его в solr.Сгладить вложенный JSON с помощью jq

У меня есть 11 TB файлов json, которые вложены и содержат точки в именах полей, что означает не elasticsearch (точки), ни solr (вложенные без обозначения _childDocument_) могут переваривать его как есть.

Другие решения состоят в том, чтобы заменить точки в именах полей на символы подчеркивания и подтолкнуть их к elasticsearch, но у меня гораздо лучший опыт работы с solr, поэтому я предпочитаю решение сглаживания (если solr не может переварить эти вложенные jsons как есть?).

Я предпочел бы поиск elasticsearch только в том случае, если процесс переваривания займет гораздо меньше времени, чем solr, потому что мой приоритет переваривается так быстро, как я могу (поэтому я выбрал qt вместо того, чтобы писать его на python).

Просьба помочь.

EDIT:

Я думаю, что пара примеров 3 & 4 решает это для меня: https://lucidworks.com/blog/2014/08/12/indexing-custom-json-data/

Постараюсь в ближайшее время.

ответ

8

Вы также можете использовать следующий jq команда для выравнивания вложенных объектов JSON таким образом:

[leaf_paths as $path | {"key": $path | join("."), "value": getpath($path)}] | from_entries 

путь это работает: leaf_paths возвращает поток массивов, которые представляют пути на данном JSON документ, на котором появляются «элементы листа», то есть, элементы которые не имеют дочерних элементов, таких как числа, строки и булевы. Мы передаем этот поток в объекты с объектами key и value, где key содержит элементы массива путей в виде строки, соединенной точками, и value содержит элемент на этом пути. Наконец, мы помещаем всю вещь в массив и запускаем ее from_entries, которая преобразует массив объектов {key, value} в объект, содержащий эти пары ключ-значение.

+0

Это решение не работает, когда JSON содержит массивы. Например: '{" a ": {" b ": [1]}}', для которого возникает ошибка: ** jq: error (at : 1): string (".") И number (0) не может быть добавлено ** –

1

Как выясняется, curl -XPOST 'http://localhost:8983/solr/flat/update/json/docs' -d @json_file делает только это:

{ 
    "a.b":[1], 
    "id":"24e3e780-3a9e-4fa7-9159-fc5294e803cd", 
    "_version_":1535841499921514496 
} 

EDIT 1: Solr 6.0.1 с bin/solr -e cloud. имя коллекции flat, все остальные по умолчанию (с data-driven-schema, который также по умолчанию).

EDIT 2: Последний скрипт, который я использовал: find . -name '*.json' -exec curl -XPOST 'http://localhost:8983/solr/collection1/update/json/docs' -d @{} \;.

EDIT 3: Возможно также параллельное использование xargs и добавление поля id с помощью jq: find . -name '*.json' -print0 | xargs -0 -n 1 -P 8 -I {} sh -c "cat {} | jq '. + {id: .a.b}' | curl -XPOST 'http://localhost:8983/solr/collection/update/json/docs' -d @-", где -P - коэффициент параллелизма. Я использовал jq для установки идентификатора, поэтому множественные закачки одного и того же документа не будут создавать дубликаты в коллекции (когда я искал оптимальное значение -P, он создал дубликаты в коллекции)

3

Это просто вариант JQ Сантьяго:

. as $in 
| reduce leaf_paths as $path ({}; 
    . + { ($path | map(tostring) | join(".")): $in | getpath($path) }) 

Это позволяет избежать затрат на строительство ключа/значения и разрушения.

(Если у вас есть доступ к версии jq позже jq 1.5, вы можете опустить "карту (ToString)")

Два важных момента об обоих этих JQ решений:.

  1. Массивы также выравнивают. . дано {"a": {"b": [0,1,2]}} в качестве входных данных, то выход будет:

    { 
        "a.b.0": 0, 
        "a.b.1": 1, 
        "a.b.2": 2 
    } 
    
  2. Если какие-либо из ключей в исходном формате JSON содержит периоды, то ключевые столкновения возможны; такие столкновения, как правило, приводят к потере стоимости. Это будет происходить, например, при следующем входе:

    {"a.b":0, "a": {"b": 1}} 
    
+0

Я получаю jq: error (at : 14): string (".") и number (0) не могут быть добавлены, когда это значение является массивом. –

+0

@peak Я получаю ту же проблему, когда JSON содержит массивы. Например, если входными данными являются '{" a ": {" b ": [1]}}', будет сообщено об ошибке: ** jq: ошибка (по адресу : 1): string (".") и число (0) не может быть добавлено ** –

+0

@SteveAmerige - ответ был обновлен, так что он будет работать с jq 1.4 и более поздними версиями. – peak

1

Вот решение, которое использует tostream, выберите, присоединиться, уменьшить и setpath

reduce (tostream | select(length==2) | .[0] |= [join(".")]) as [$p,$v] (
    {} 
    ; setpath($p; $v) 
) 
Смежные вопросы