Datastax Graph Loader — загрузка мета-свойств неоднородных файлов JSON

Ниже приведены 3 примера файлов JSON и скрипт загрузки графа. Первый файл содержит наибольшую сложность, большую часть которой скрипт загрузки должен игнорировать. Второй файл представляет собой простую вариацию, которая часто встречается. Последний файл предназначен для того, чтобы дать представление о широких различиях, которые могут возникнуть между каждым файлом, и показать самый непосредственный пример того, где проблемы в настоящее время.

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

Пример входного файла JSON 1

/*{
  "peopleInfo": [
    {
      "id": {
        "idProperty1": "property1Value",
        "idProperty2": "someUUID"
      }
    },
    {
      "people": [
        {
          "firstName": "person1FirstName",
          "lastName": "person1LastName",
          "sequence": 1
        },
        {
          "firstName": "person2FirstName",
          "lastName": "person2LastName",
          "sequence": 2
        },
        { //children and twins may be switched such that twins are sequence 3 & 4 and one or both of them have children with corresponding sequences
          "children": [
            {
              "firstName": "firstChildFirstName",
              "lastName": "firstChildLastName",
              "sequence": 3
            },
            {
              "firstName": "secondChildFirstName",
              "lastName": "secondChildLastName",
              "sequence": 4
            },
            {
              "twins": [
                {
                  "firstName": "firstTwinFirstName",
                  "lastName": "firstTwinLastName",
                  "sequence": 5
                },
                {
                  "firstName": "secondTwinFirstName",
                  "lastName": "secondTwinLastName",
                  "sequence": 6
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}*/

Второй файл не содержит дочерних элементов

Пример входного файла JSON 2

/*{
  "peopleInfo": [
    {
      "id": {
        "idProperty1": "property1Value",
        "idProperty2": "someUUID"
      }
    },
    {
      "people": [
        {
          "firstName": "person1FirstName",
          "lastName": "person1LastName",
          "sequence": 1
        },
        {
          "firstName": "person2FirstName",
          "lastName": "person2LastName",
          "sequence": 2
        }
      ]
    }
  ]
}*/

Третий файл содержит близнецов, но не детей-одиночек.

Пример входного файла JSON 3

    /*{
      "peopleInfo": [
        {
          "personsID": {
            "idProperty1": "property1Value",
            "idProperty2": "someUUID"
          }
        },
        {
          "people": [
            { // twins can exist without top level people(parents work well to define this) and without other children. Also, children can exist without twins and without parents as well.
              "twins": [
                {
                  "firstName": "firstTwinFirstName",
                  "lastName": "firstTwinLastName",
                  "sequence": 3
                },
                {
                  "firstName": "secondTwinFirstName",
                  "lastName": "secondTwinLastName",
                  "sequence": 4
                }
              ]
            }
          ]
        }
      ]
    }*/

Скрипт загрузки

inputBaseDir = "/path/to/directories"

import java.io.File as javaFile;
def list = []

new javaFile(inputBaseDir).eachDir() { dir ->
  list << dir.getAbsolutePath()
}
for (item in list){
  def fileBuilder = File.directory(item)
  def peopleInfoMapper = fileBuilder.map {
    it['idProperty1'] = it.peopleInfo.id.idProperty1[0]
    it['idProperty2'] = it.peopleInfo.id.idProperty2[0]

    def ppl = it.peopleInfo.people[1]
    people = ppl.collect{
      if ( it['firstName'] != null){
        it['firstName'] = it['firstName']
      } else if ( it['lastName'] != null){
        it['lastName'] = it['lastName']
      } else if ( it['sequence'] != null) {
        it['sequence'] = it['sequence']
      }

      //filling the null values below is the temporary non-solution to get the data to load
      if ( it['firstName'] == null){
        it['firstName'] = ''
      }
      if ( it['lastName'] == null){
        it['lastName'] = ''
      }
      if ( it['sequence'] == null){
        it['sequence'] = 0
      }
      it
    }
    it['people'] = people
    it.remove('peopleInfo')
    it
    }
  load(peopleInfoMapper).asVertices {
    label "peopleInfo"
    key 'idProperty2'
    vertexProperty 'people',{
      value 'firstName'
      value 'lastName'
      value 'sequence'
      ignore 'children'
      ignore 'twins'
    }
  }

Проблемы

1

Глядя на третий файл: хотя близнецы имеют внутри разрешенные значения, они не должны влиять на загрузку, потому что игнорирование ключа «близнецы» должно игнорировать все значения их мета-свойств. В этом случае я считаю, что приведенное ниже исключение было вызвано тем, что не было людей высшего уровня, которые не были бы детьми или близнецами, и, игнорируя ключ «близнецы», все, что осталось для vertexProperty 'people', — это пустая карта. Мой неответ просто заполнил эту пустую карту пустой строкой для имен и нулем для последовательностей, которые загружаются в базу данных вместе с фактическими данными.

java.lang.IllegalArgumentException: [В поле «люди»] Предоставленная карта не содержит значения свойства в поле [последовательность]: {twin=[{firstName=firstTwinFirstName,lastName=firstTwinLastName, sequence=1},{firstName=secondTwinFirstName,lastName =secondTwinLastName,sequence=2}]}

2

Глядя на первый файл: когда ключ «близнецы» игнорируется или удаляется напрямую, пустая карта по-прежнему остается в качестве заполнителя, которая заполняется тем же нерешением в сценарии загрузки и загружается в базу данных вместе с фактические данные.

Есть ли наилучшая практика для решения этих проблем?


person RodogInfinite    schedule 13.10.2017    source источник


Ответы (1)


Я не знаю, лучшее ли это решение, но, похоже, это помогает.

inputBaseDir = "/path/to/directories"

import java.io.File as javaFile;
def list = []

new javaFile(inputBaseDir).eachDir() { dir ->
  list << dir.getAbsolutePath()
}
for (item in list){
  def fileBuilder = File.directory(item)
  def peopleInfoMapper = fileBuilder.map {
    it['idProperty1'] = it.peopleInfo.id.idProperty1[0]
    it['idProperty2'] = it.peopleInfo.id.idProperty2[0]

    def ppl = it.peopleInfo.people[1]
    people = ppl.collect{
      //removes k:v leaving an empty map
      if (it['children'] != null{
        it.remove('children')
      }
      //removes k:v leaving an empty map
      if (it['twins'] != null{
        it.remove('twins')
      }
      if ( it['firstName'] != null){
        it['firstName'] = it['firstName']
      } else if ( it['lastName'] != null){
        it['lastName'] = it['lastName']
      } else if ( it['sequence'] != null) {
        it['sequence'] = it['sequence']
      }
    }
    if (ppl['firstName'][0] != null && ppl['lastName'][0] != null){
      it['people'] = people.findAll() //only gathers non-empty maps from people
    } else { 
        /* removing people without desired meta-properties enables
         loader to proceed when empty maps from the removal of
         children and/or twins are present, while top-level 
         persons aren't*/
        it.remove('people')}  
    it.remove('peopleInfo')
    it
    }
  load(peopleInfoMapper).asVertices {
    label "peopleInfo"
    key 'idProperty2'
    vertexProperty 'people',{
      value 'firstName'
      value 'lastName'
      value 'sequence'
      ignore 'children'
      ignore 'twins'
    }
  }
person RodogInfinite    schedule 14.10.2017