2015-07-27 2 views
0

Я написал фрагмент импорта, чтобы заполнить мою базу данных Neo4J узлами для городов и связанными с ними округами. Код выглядитОптимизация импорта данных CSV в neo4j

<?php 
function readCSV($csvFile){ 
$file_handle = fopen($csvFile, 'r'); 
$lineCount=0; 
while (!feof($file_handle)) { 
    $line_of_text[] = fgetcsv($file_handle, 1024, ';', '"'); 
    $lineCount++; 
    } 
fclose($file_handle); 
return array($line_of_text,$lineCount); 
} 

// Create an Index for Town and for Country 

$queryString = ' 
CREATE INDEX ON :Country (name) 
'; 
$query = new Everyman\Neo4j\Cypher\Query($client, $queryString); 
$result = $query->getResultSet(); 

$queryString = ' 
CREATE INDEX ON :Town (name) 
'; 
$query = new Everyman\Neo4j\Cypher\Query($client, $queryString); 
$result = $query->getResultSet(); 

// Set path to CSV file 
$importFile = 'files/import_city_country.csv'; 
$completeResult = readCSV($importFile); 
$dataFile = $completeResult[0]; 
$maxLines = $completeResult[1]; 

for ($row = 1; $row < $maxLines; ++ $row) { 
$countryData = array(); 

if(!is_null($dataFile[$row][0])) 
{ 

    // Define parameters for the queries 
    $params =array(
    "nameCountry" => trim($dataFile[$row][0]), 
    "nameTown" => trim($dataFile[$row][1]), 
    "uuid" => uniqid(), 
    ); 

    # Now check if we know that country already to avoid double entries 
    $queryString = ' 
    MATCH (c:Country {name: {nameCountry}}) 
    RETURN c 
    '; 

    $query = new Everyman\Neo4j\Cypher\Query($client, $queryString,$params); 
    $result = $query->getResultSet(); 

    if(COUNT($result)==0) // Country doesnt exist! 
    { 
     $queryString = ' 
     MERGE (c:Country {name: {nameCountry}}) 
     set 
      c.uuid = {uuid}, 
      c.created = timestamp() 
     RETURN c 
     '; 

     $query = new Everyman\Neo4j\Cypher\Query($client, $queryString,$params); 
     $result = $query->getResultSet();  
    } 

    # Now check if we know that town already 
    $queryString = ' 
    MATCH (t:Town {name: {nameTown}}) 
    RETURN t 
    '; 

    $query = new Everyman\Neo4j\Cypher\Query($client, $queryString,$params); 
    $result = $query->getResultSet(); 

    if(COUNT($result)==0) // Town doesnt exist! 
    { 
     $queryString = ' 
     MERGE (t:Town {name: {nameTown}}) 
     set 
      t.created = timestamp() 
     RETURN t 
     '; 

     $query = new Everyman\Neo4j\Cypher\Query($client, $queryString,$params); 
     $result = $query->getResultSet(); 

     // Relate town to country 

     $queryString = ' 
     MATCH (c:Country {name: {nameCountry}}), (t:Town {name: {nameTown}})  
     MERGE (t)-[:BELONGS_TO]->(c); 
     '; 

     $query = new Everyman\Neo4j\Cypher\Query($client, $queryString,$params); 
     $result = $query->getResultSet();    

    } 

} // Excel Last Line is not Null - go on 

} // Next Row 

?> 

Типичный CSV строка выглядит

Country City 
Albania Tirana 

Это все работает отлично - но это занимает более 30 минут на компьютере, чтобы импортировать 9.000 линии. Я знаю, что система должна проверять каждую запись, если она уже существует, а также делает связь между городом и деревней, но кажется довольно длинным, хотя для такого количества CSV-линий.

У вас есть предложения по улучшению кода импорта?

Спасибо, Balael

BTW: Есть ли шанс, чтобы вставить здесь код без редактирования каждой строки и добавление 4 пробела - своего рода скучно дольше кода .....

+0

Вы можете начать, не повторяя цикл дважды, загружая файл в массив, и они зацикливают массив. Или импортируйте CSV напрямую, у меня нет большого опыта работы с Neo4J, но посмотрите на конец этой статьи http://neo4j.com/developer/graph-db-vs-rdbms/ –

+0

Спасибо, у меня будет посмотрите на сайт, который вы связали. – Balael

ответ

2

LOAD CSV Использование внутри neo4j- если это вообще возможно, и не пишите свой собственный код для обработки CSV.

Что это будет для вас в первую очередь, это позволить вам выполнять много элементов в одну транзакцию USING PERIODIC COMMIT.

Если вы хотите использовать REST API удаленно (как я предполагаю, вы здесь делаете), посмотрите на поддержку привязки вашего языка для batch operations. Ваш код, как написано, будет тратить много времени на сервер, вероятно, превращая каждую строку CSV в запрос/ответ, который будет медленным. Лучше многократно загружать файлы и запускать их как одну операцию, что поможет свести к минимуму количество накладных расходов протокола.

+0

Большое спасибо, я попробовал LOAD CSV, но не смог найти способ справиться с проблемами с предстоящими котировками в CSV ("), которые всегда вызывали java-ошибку. Вот почему я ушел - поскольку я не мог найти подход в Google. у вас есть опыт? – Balael

Смежные вопросы