Поиск Firebase JSON с помощью Apache Drill

Я экспортировал часть своих данных с https://domain.firebaseio.com/users/

{
  "3": {
    "company": "",
    "d_year": "",
    "email": "[email protected]",
    "facebook": "",
    "fullname": "Mario Test",
    "google": "",
    "igoto": "",
    "image": "",
    "notifications": {
      "-Jx6fpaJHvKPHc8CylPd": {
        "from": "System",
        "image": "/img/system_icon.jpg",
        "msg": "System:",
        "param": "3",
        "posteddate": 1440016723546,
        "type": "system"
      }
    },
    "school": "",
    "school_year": "",
    "tags": {
      "-JxWuEPs183UEwsI-XNb": {
        "title": "Anesthesia"
      },
      "-JxWuZ-ePcx0XqYRmzc6": {
        "title": "Bridges"
      }
    },
    "twitter": ""
  },
  "4": {
    "company": "",
    "d_year": "",
    "email": "[email protected]",
    "fullname": "mario test",
    "igoto": "",
    "image": "img/a0.jpg",
    "notifications": {
      "-JxAQpWGzY-gOzej7Xis": {
        "from": "System",
        "image": "/img/system_icon.jpg",
        "msg": "System:",
        "param": "4",
        "posteddate": 1440079641420,
        "type": "system"
      }
    },
    "school": "",
    "school_year": ""
  }
}

Выполнение: SELECT * FROM dfs./Users/me/Desktop/users.json

работает (или, по крайней мере, я получаю результат) введите описание изображения здесь

Но как мне сопоставить столбцы со значениями в строке. Глядя на это из мира реляционных баз данных, заголовки столбцов на снимке экрана являются уникальными идентификаторами (3, 4) - они должны быть отделены от строки, а не заголовком столбца. То же самое верно для уникально сгенерированного ключа, который создается при использовании push({})

Цель, конечно, состоит в том, чтобы сделать Select Where (например, выбрать * из данных, где fullname="Mario Test")

Есть ли какая-то предварительная обработка, которую я должен выполнить для JSON, прежде чем искать его с помощью Drill?


person lsiunsuex    schedule 03.09.2015    source источник
comment
Должны ли проиндексированные записи 3 и 4 быть строками?   -  person Chris Matta    schedule 04.09.2015


Ответы (2)


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

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

0: jdbc:drill:zk=local> select t.* from dfs.`/Users/vince/data/stackoverflow/users.json` t;
+---+---+
| 3 | 4 |
+---+---+
| {"company":"","d_year":"","email":"[email protected]","facebook":"","fullname":"Mario Test","google":"","igoto":"","image":"","notifications":{"-Jx6fpaJHvKPHc8CylPd":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"3","posteddate":1440016723546,"type":"system"}},"school":"","school_year":"","tags":{"-JxWuEPs183UEwsI-XNb":{"title":"Anesthesia"},"-JxWuZ-ePcx0XqYRmzc6":{"title":"Bridges"}},"twitter":""} | {"company":"","d_year":"","email":"[email protected]","fullname":"mario test","igoto":"","image":"img/a0.jpg","notifications":{"-JxAQpWGzY-gOzej7Xis":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"4","posteddate":1440079641420,"type":"system"}},"school":"","school_year":""} |
+---+---+
1 row selected (0.133 seconds)

Поскольку эти столбцы являются динамическими и находятся на «верхнем уровне» объекта JSON, вы не можете использовать здесь KVGEN. Но если вы немного преобразуете данные, вы можете использовать KVGEN. Я использовал этот вызов самого превосходного инструмента jq для преобразования данных в формат, который может использовать KVGEN:

$ jq '.| { "user": . }' < users.json > users_kv.json

Это примет входные данные и просто обернет объект JSON в другую карту, которая даст нам «статический» столбец, который нам нужен для следующих действий:

0: jdbc:drill:zk=local> select kvgen(t.`user`) from dfs.`/Users/vince/data/stackoverflow/users_kv.json` t;
+--------+
| EXPR$0 |
+--------+
| [{"key":"3","value":{"company":"","d_year":"","email":"[email protected]","facebook":"","fullname":"Mario Test","google":"","igoto":"","image":"","notifications":{"-Jx6fpaJHvKPHc8CylPd":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"3","posteddate":1440016723546,"type":"system"},"-JxAQpWGzY-gOzej7Xis":{}},"school":"","school_year":"","tags":{"-JxWuEPs183UEwsI-XNb":{"title":"Anesthesia"},"-JxWuZ-ePcx0XqYRmzc6":{"title":"Bridges"}},"twitter":""}},{"key":"4","value":{"company":"","d_year":"","email":"[email protected]","fullname":"mario test","igoto":"","image":"img/a0.jpg","notifications":{"-Jx6fpaJHvKPHc8CylPd":{},"-JxAQpWGzY-gOzej7Xis":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"4","posteddate":1440079641420,"type":"system"}},"school":"","school_year":"","tags":{"-JxWuEPs183UEwsI-XNb":{},"-JxWuZ-ePcx0XqYRmzc6":{}}}}] |
+--------+
1 row selected (1.774 seconds)

Все еще не так, как вы хотите, так как у меня есть список внутри столбца. Поэтому используйте ПЛАТТЕН:

0: jdbc:drill:zk=local> select flatten(kvgen(t.`user`)) as `user` from dfs.`/Users/vince/data/stackoverflow/users_kv.json` t;
+------+
| user |
+------+
| {"key":"3","value":{"company":"","d_year":"","email":"[email protected]","facebook":"","fullname":"Mario Test","google":"","igoto":"","image":"","notifications":{"-Jx6fpaJHvKPHc8CylPd":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"3","posteddate":1440016723546,"type":"system"},"-JxAQpWGzY-gOzej7Xis":{}},"school":"","school_year":"","tags":{"-JxWuEPs183UEwsI-XNb":{"title":"Anesthesia"},"-JxWuZ-ePcx0XqYRmzc6":{"title":"Bridges"}},"twitter":""}} |
| {"key":"4","value":{"company":"","d_year":"","email":"[email protected]","fullname":"mario test","igoto":"","image":"img/a0.jpg","notifications":{"-Jx6fpaJHvKPHc8CylPd":{},"-JxAQpWGzY-gOzej7Xis":{"from":"System","image":"/img/system_icon.jpg","msg":"System:","param":"4","posteddate":1440079641420,"type":"system"}},"school":"","school_year":"","tags":{"-JxWuEPs183UEwsI-XNb":{},"-JxWuZ-ePcx0XqYRmzc6":{}}}} |
+------+
2 rows selected (0.257 seconds)

Два ряда - гораздо лучше. Теперь вы готовы делать то, что хотели (обратите внимание на подзапрос, а также на обратные кавычки вокруг зарезервированных слов user и value:

    0: jdbc:drill:zk=local> select u.`user`.`key` as userid, u.`user`.`value`.fullname as fullname, u.`user`.`value`.email as email from (select flatten(kvgen(t.`user`)) as `user` from dfs.`/Users/vince/data/stackoverflow/users_kv.json` t) u where u.`user`.`value`.fullname = 'Mario Test';
+---------+-------------+-----------------------------+
| userid  |  fullname   |            email            |
+---------+-------------+-----------------------------+
| 3       | Mario Test  | [email protected]  |
+---------+-------------+-----------------------------+
1 row selected (0.22 seconds)
person Vince Gonzalez    schedule 04.09.2015
comment
Круто, это отличный способ решить эту проблему. - person Chris Matta; 04.09.2015

Ключ не должен действительно содержать значение, если на самом деле ключи «3» и «4» являются идентификаторами. Лучший способ отформатировать этот JSON для Drill — использовать фактические ключи для этих значений (также обратите внимание, что вы можете иметь несколько записей в файле, Drill может их анализировать):

{ "id": 3,
  "data": {
       ...
  }
}
{ "id": 4,
   "data": {
        ...
   }
}

Таким образом, вы можете делать такие запросы:

> select t.`id`, t.`data`.`fullname` as `fullname` from `firebase.json` t;
+-----+-------------+
| id  |  fullname   |
+-----+-------------+
| 3   | Mario Test  |
| 4   | mario test  |
+-----+-------------+
2 rows selected (0.269 seconds)
person Chris Matta    schedule 04.09.2015