Оптимизировать импорт данных CSV в neo4j

Я написал фрагмент импорта, чтобы заполнить мою базу данных 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

Кстати: любой шанс вставить сюда код без редактирования каждой строки и добавления 4 пробелов — довольно скучно для длинного кода …..

0

Решение

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

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

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

2

Другие решения

Других решений пока нет …